diff --git a/test/co19/co19_test_base.dart b/test/co19/co19_test_base.dart new file mode 100644 index 0000000000..c98183bb18 --- /dev/null +++ b/test/co19/co19_test_base.dart @@ -0,0 +1,69 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/file_system/file_system.dart'; +import 'package:dartdoc/src/dartdoc_options.dart'; +import 'package:dartdoc/src/model/model.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../dartdoc_test_base.dart'; +import '../src/utils.dart' as utils; + +@reflectiveTest +class Co19TestBase extends DartdocTestBase { + @override + String get libraryName => 'co19'; + + late Folder projectRoot; + late PackageGraph packageGraph; + late ModelElement libraryModel; + + void expectNoWarnings() { + expect(packageGraph.packageWarningCounter.countedWarnings, isEmpty); + expect(packageGraph.packageWarningCounter.hasWarnings, isFalse); + } + + Future writePackageWithCommentedLibraries( + List<(String, String)> filesAndComments, { + List additionalArguments = const [], + }) async { + projectRoot = + utils.writePackage('co19', resourceProvider, packageConfigProvider); + projectRoot + .getChildAssumingFile('dartdoc_options.yaml') + .writeAsStringSync(''' + dartdoc: + warnings: + - missing-code-block-language + '''); + + for (var (fileName, comment) in filesAndComments) { + projectRoot + .getChildAssumingFolder('lib') + .getChildAssumingFile(fileName) + .writeAsStringSync('$comment\n' + 'library;'); + } + + var optionSet = DartdocOptionRoot.fromOptionGenerators( + 'dartdoc', [createDartdocOptions], packageMetaProvider); + optionSet.parseArguments([]); + packageGraph = await utils.bootBasicPackage( + projectRoot.path, packageMetaProvider, packageConfigProvider, + additionalArguments: additionalArguments); + libraryModel = packageGraph.defaultPackage.libraries.first; + } + + Future writePackageWithCommentedLibrary( + String comment, { + List additionalArguments = const [], + }) => + writePackageWithCommentedLibraries([('a.dart', comment)], + additionalArguments: additionalArguments); + + void expectDocComment(matcher) { + expect(libraryModel.documentation, matcher); + } +} diff --git a/test/co19/line_based_doc_comments_test.dart b/test/co19/line_based_doc_comments_test.dart new file mode 100644 index 0000000000..1851454b2a --- /dev/null +++ b/test/co19/line_based_doc_comments_test.dart @@ -0,0 +1,166 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion A line-based doc comment is a comment that starts with `///`. One +/// or more consecutive lines that begin with `///` form a doc comment block. +/// +/// The block continues even if interrupted by single-line non-doc comments +/// (lines starting with `//`) or by blank lines. The interrupting lines are +/// ignored when extracting documentation text. +/// +/// For each line that begins with `///`, the parser removes the three slashes +/// and all leading whitespace to produce the documentation text. Exception: +/// inside fenced code blocks (` ``` `), whitespace after the leading `///` is +/// preserved to maintain code formatting. +/// @author sgrekhov22@gmail.com +library; + +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import 'co19_test_base.dart'; + +void main() { + defineReflectiveSuite(() { + defineReflectiveTests(LineBasedDocCommentsTest); + }); +} + +@reflectiveTest +class LineBasedDocCommentsTest extends Co19TestBase { + /// Check that the parser removes the three slashes and all leading + /// whitespaces + void test_removesTripleSlashes() async { + await writePackageWithCommentedLibrary(''' +/// Text. +/// More text. +'''); + expectDocComment(equals(''' +Text. +More text.''')); + } + + /// Check empty lines after three slashes are preserved + void test_leavesBlankLines() async { + await writePackageWithCommentedLibrary(''' +/// Text. +/// +/// More text. +'''); + expectDocComment(equals(''' +Text. + +More text.''')); + } + + /// Check that the parser removes the three slashes and all leading + /// whitespaces + void test_removesSpaceAfterTripleSlashes() async { + markTestSkipped('Skipping until issue ' + 'https://github.com/dart-lang/dartdoc/issues/4137 is resolved.'); + return; + await writePackageWithCommentedLibrary(''' +/// Text. +/// More text. +'''); + expectDocComment(equals(''' +Text. +More text.''')); + } + + /// Check that interrupting blank lines and starting with `// ` are ignored. + void test_interruptingLinesIgnored() async { + await writePackageWithCommentedLibrary(''' +/// Text. +// +/// More text. +// Some text +/// And more text. + +/// And more. +'''); + expectDocComment(equals(''' +Text. +More text. +And more text. +And more.''')); + } + + /// Check that the doc comment starts after `///` even there is no trailing + /// whitespace. + void test_noTrailingWhitespace() async { + await writePackageWithCommentedLibrary(''' +//// Text. +/////More text. +///And more. +'''); + expectDocComment(equals(''' +/ Text. +//More text. +And more.''')); + } + + /// Check that inside fenced code blocks (```), whitespaces after the leading + /// `///` are preserved + void test_whitespacesInBacktickCodeBlocks() async { + await writePackageWithCommentedLibrary(''' +/// ``` +/// void main() { +/// /// This line prints "Hello, world!" +/// print('Hello, world!'); +/// } +/// ``` +'''); + expectDocComment(equals(''' +``` +void main() { + /// This line prints "Hello, world!" + print('Hello, world!'); +} +```''')); + } + + /// Check that inside fenced code blocks (~~~), whitespaces after the leading + /// `///` are preserved + void test_whitespacesInTildesCodeBlocks() async { + await writePackageWithCommentedLibrary(''' +/// ~~~ +/// void main() { +/// /// This line prints "Hello, world!" +/// print('Hello, world!'); +/// } +/// ~~~ +'''); + expectDocComment(equals(''' +~~~ +void main() { + /// This line prints "Hello, world!" + print('Hello, world!'); +} +~~~''')); + } + + /// Check that inside fenced code span (`), whitespaces after the leading + /// `///` are removed. + void test_whitespacesInCodeSpan() async { + markTestSkipped('Skipping until issue ' + 'https://github.com/dart-lang/dartdoc/issues/4138 is resolved.'); + return; + await writePackageWithCommentedLibrary(''' +/// ` +/// void main() { +/// /// This line prints "Hello, world!" +/// print('Hello, world!'); +/// } +/// ` +'''); + expectDocComment(equals(''' +` +void main() { +/// This line prints "Hello, world!" +print('Hello, world!'); +} +`''')); + } +} diff --git a/test/dartdoc_test_base.dart b/test/dartdoc_test_base.dart index be046a1569..5b4c34e0a7 100644 --- a/test/dartdoc_test_base.dart +++ b/test/dartdoc_test_base.dart @@ -40,7 +40,7 @@ abstract class DartdocTestBase { String get dartCoreUrlPrefix => '$dartSdkUrlPrefix/dart-core'; - String get dartSdkUrlPrefix => 'https://api.dart.dev/stable/3.2.0'; + String get dartSdkUrlPrefix => 'https://api.dart.dev/stable/3.10.6'; String get sdkConstraint => '>=3.7.0 <4.0.0';