diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb72cc29b..9cdf7fcd49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ -## 4.1.0-dev +## 4.1.0 +* Move to analyzer 2.7.0. (#2845) +* The library interface is now explicitly marked as experimental via meta. * Experimental feature: HTML output from markdown rendering, `{@tool}` and `{@inject-html}` is sanitized when hidden option `--sanitize-html` is passed. +* Refactor of ModelElement and ElementType constructors. Technically breaking + but known users of the API do not attempt to construct these types by hand. + (#2828, #2829) +* Move to recommended set of hints in linter and correct some small errors + in regexps. (#2833) ## 4.0.0 * BREAKING CHANGE: Refactors to support NNBD and adapt to new analyzer diff --git a/dartdoc_options.yaml b/dartdoc_options.yaml index 3102516a30..e6f2ee1b2f 100644 --- a/dartdoc_options.yaml +++ b/dartdoc_options.yaml @@ -1,4 +1,4 @@ dartdoc: linkToSource: root: '.' - uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v4.1.0-dev/%f%#L%l%' + uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v4.1.0/%f%#L%l%' diff --git a/lib/src/io_utils.dart b/lib/src/io_utils.dart index fb42181930..0e7bd9337e 100644 --- a/lib/src/io_utils.dart +++ b/lib/src/io_utils.dart @@ -12,22 +12,10 @@ import 'dart:io' as io; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; -// ignore: implementation_imports -import 'package:analyzer/src/generated/sdk.dart' show SdkLibrary; -// ignore: implementation_imports -import 'package:analyzer/src/test_utilities/mock_sdk.dart' show MockSdkLibrary; import 'package:path/path.dart' as path show Context; Encoding utf8AllowMalformed = Utf8Codec(allowMalformed: true); -bool isSdkLibraryDocumented(SdkLibrary library) { - if (library is MockSdkLibrary) { - // Not implemented in [MockSdkLibrary]. - return true; - } - return library.isDocumented; -} - extension PathExtensions on path.Context { /// Returns a canonicalized path including the home directory in place of /// tilde references. diff --git a/lib/src/model/library.dart b/lib/src/model/library.dart index f5bc68d8aa..776557bdee 100644 --- a/lib/src/model/library.dart +++ b/lib/src/model/library.dart @@ -17,7 +17,6 @@ import 'package:analyzer/src/dart/element/inheritance_manager3.dart' show InheritanceManager3; // ignore: implementation_imports import 'package:analyzer/src/generated/sdk.dart' show SdkLibrary; -import 'package:dartdoc/src/io_utils.dart'; import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/package_meta.dart' show PackageMeta; @@ -201,8 +200,7 @@ class Library extends ModelElement with Categorization, TopLevelContainer { @override bool get isPublic { if (!super.isPublic) return false; - if (sdkLib != null && - (sdkLib.isInternal || !isSdkLibraryDocumented(sdkLib))) { + if (sdkLib != null && (sdkLib.isInternal || !sdkLib.isDocumented)) { return false; } if (config.isLibraryExcluded(name) || diff --git a/lib/src/version.dart b/lib/src/version.dart index e1b28724bd..2384f91ac4 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '4.1.0-dev'; +const packageVersion = '4.1.0'; diff --git a/pubspec.yaml b/pubspec.yaml index b1830f627c..98a53c7e7d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,17 +1,17 @@ name: dartdoc # Run `dart run grinder build` after updating. -version: 4.1.0-dev +version: 4.1.0 description: A non-interactive HTML documentation generator for Dart source code. homepage: https://github.com/dart-lang/dartdoc environment: sdk: '>=2.12.0 <3.0.0' dependencies: - analyzer: ^2.4.0 + analyzer: ^2.7.0 args: ^2.3.0 charcode: ^1.3.1 collection: ^1.15.0 - cli_util: ^0.3.4 + cli_util: ^0.3.5 crypto: ^3.0.1 glob: ^2.0.1 html: ^0.15.0 @@ -36,7 +36,7 @@ dev_dependencies: grinder: ^0.9.0 http: ^0.13.3 lints: ^1.0.1 - test: ^1.17.12 + test: ^1.19.0 executables: dartdoc: null diff --git a/test/documentation_comment_test.dart b/test/documentation_comment_test.dart index 8857410cc5..c88b79ce5b 100644 --- a/test/documentation_comment_test.dart +++ b/test/documentation_comment_test.dart @@ -6,6 +6,7 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; import 'package:dartdoc/src/model/model.dart'; @@ -20,8 +21,6 @@ void main() { MemoryResourceProvider resourceProvider; PackageMetaProvider packageMetaProvider; FakePackageConfigProvider packageConfigProvider; - MockSdk mockSdk; - Folder sdkFolder; Folder projectRoot; String projectPath; var packageName = 'my_package'; @@ -42,16 +41,22 @@ void main() { group('documentation_comment tests', () { setUp(() async { resourceProvider = MemoryResourceProvider(); - mockSdk = MockSdk(resourceProvider: resourceProvider); - sdkFolder = utils.writeMockSdkFiles(mockSdk); + final sdkRoot = resourceProvider.getFolder( + resourceProvider.convertPath('/sdk'), + ); + createMockSdk( + resourceProvider: resourceProvider, + root: sdkRoot, + ); + utils.writeMockSdkFiles(sdkRoot); packageMetaProvider = PackageMetaProvider( PubPackageMeta.fromElement, PubPackageMeta.fromFilename, PubPackageMeta.fromDir, resourceProvider, - sdkFolder, - defaultSdk: mockSdk, + sdkRoot, + defaultSdk: FolderBasedDartSdk(resourceProvider, sdkRoot), messageForMissingPackageMeta: PubPackageMeta.messageForMissingPackageMeta, ); @@ -62,7 +67,7 @@ void main() { // To build the package graph, we always ask package_config for a // [PackageConfig] for the SDK directory. Put a dummy entry in. packageConfigProvider.addPackageToConfigFor( - sdkFolder.path, 'analyzer', Uri.file('/sdk/pkg/analyzer/')); + sdkRoot.path, 'analyzer', Uri.file('/sdk/pkg/analyzer/')); projectRoot = utils.writePackage( packageName, resourceProvider, packageConfigProvider); diff --git a/test/html_generator_test.dart b/test/html_generator_test.dart index 18c7674bd8..611909124b 100644 --- a/test/html_generator_test.dart +++ b/test/html_generator_test.dart @@ -25,156 +25,165 @@ import 'package:test/test.dart'; import 'src/utils.dart' as utils; void main() { - MemoryResourceProvider resourceProvider; - p.Context pathContext; - - PackageMetaProvider packageMetaProvider; - FakePackageConfigProvider packageConfigProvider; - - final Templates templates = HtmlAotTemplates(); - GeneratorFrontEnd generator; - DartdocFileWriter writer; - - Folder projectRoot; - String projectPath; - - setUp(() async { - packageMetaProvider = utils.testPackageMetaProvider; - resourceProvider = packageMetaProvider.resourceProvider; - pathContext = resourceProvider.pathContext; - packageConfigProvider = utils - .getTestPackageConfigProvider(packageMetaProvider.defaultSdkDir.path); - for (var template in [ - '_accessor_getter', - '_accessor_setter', - '_callable', - '_callable_multiline', - '_categorization', - '_class', - '_constant', - '_documentation', - '_extension', - '_features', - '_feature_set', - '_footer', - '_head', - '_library', - '_mixin', - '_name_summary', - '_packages', - '_property', - '_search_sidebar', - '_sidebar_for_category', - '_sidebar_for_container', - '_sidebar_for_library', - '_source_code', - '_source_link', - '_type', - '_typedef', - '_type_multiline', - '_typedef_multiline', - '404error', - 'category', - 'class', - 'constructor', - 'enum', - 'extension', - 'function', - 'index', - 'library', - 'method', - 'mixin', - 'property', - 'top_level_property', - 'typedef', - ]) { - await resourceProvider.writeDartdocResource( - 'templates/html/$template.html', 'CONTENT'); - } - - for (var resource in [ - 'favicon.png', - 'github.css', - 'highlight.pack.js', - 'play_button.svg', - 'readme.md', - 'script.js', - 'styles.css', - ]) { - await resourceProvider.writeDartdocResource( - 'resources/$resource', 'CONTENT'); - } - - var optionRoot = await DartdocOptionRoot.fromOptionGenerators( - 'dartdoc', - [ - createDartdocOptions, - createGeneratorOptions, - ], - packageMetaProvider); - optionRoot.parseArguments([]); - - var defaultContext = - DartdocGeneratorOptionContext.fromDefaultContextLocation( - optionRoot, resourceProvider); - var options = DartdocGeneratorBackendOptions.fromContext(defaultContext); - - generator = GeneratorFrontEnd( - HtmlGeneratorBackend(options, templates, resourceProvider)); - - projectRoot = utils.writePackage( - 'my_package', resourceProvider, packageConfigProvider); - projectPath = projectRoot.path; - var outputPath = projectRoot.getChildAssumingFolder('doc').path; - writer = DartdocFileWriter(outputPath, resourceProvider); + group('HTML generator tests', () { + MemoryResourceProvider resourceProvider; + p.Context pathContext; + + PackageMetaProvider packageMetaProvider; + FakePackageConfigProvider packageConfigProvider; + + final Templates templates = HtmlAotTemplates(); + GeneratorFrontEnd generator; + DartdocFileWriter writer; + + Folder projectRoot; + String projectPath; + + setUp(() async { + packageMetaProvider = utils.testPackageMetaProvider; + resourceProvider = packageMetaProvider.resourceProvider; + pathContext = resourceProvider.pathContext; + packageConfigProvider = utils + .getTestPackageConfigProvider(packageMetaProvider.defaultSdkDir.path); + for (var template in [ + '_accessor_getter', + '_accessor_setter', + '_callable', + '_callable_multiline', + '_categorization', + '_class', + '_constant', + '_documentation', + '_extension', + '_features', + '_feature_set', + '_footer', + '_head', + '_library', + '_mixin', + '_name_summary', + '_packages', + '_property', + '_search_sidebar', + '_sidebar_for_category', + '_sidebar_for_container', + '_sidebar_for_library', + '_source_code', + '_source_link', + '_type', + '_typedef', + '_type_multiline', + '_typedef_multiline', + '404error', + 'category', + 'class', + 'constructor', + 'enum', + 'extension', + 'function', + 'index', + 'library', + 'method', + 'mixin', + 'property', + 'top_level_property', + 'typedef', + ]) { + await resourceProvider.writeDartdocResource( + 'templates/html/$template.html', 'CONTENT'); + } + + for (var resource in [ + 'favicon.png', + 'github.css', + 'highlight.pack.js', + 'play_button.svg', + 'readme.md', + 'script.js', + 'styles.css', + ]) { + await resourceProvider.writeDartdocResource( + 'resources/$resource', 'CONTENT'); + } + + var optionRoot = await DartdocOptionRoot.fromOptionGenerators( + 'dartdoc', + [ + createDartdocOptions, + createGeneratorOptions, + ], + packageMetaProvider); + optionRoot.parseArguments([]); + + var defaultContext = + DartdocGeneratorOptionContext.fromDefaultContextLocation( + optionRoot, resourceProvider); + var options = DartdocGeneratorBackendOptions.fromContext(defaultContext); + + generator = GeneratorFrontEnd( + HtmlGeneratorBackend(options, templates, resourceProvider)); + + projectRoot = utils.writePackage( + 'my_package', resourceProvider, packageConfigProvider); + projectPath = projectRoot.path; + var outputPath = projectRoot.getChildAssumingFolder('doc').path; + writer = DartdocFileWriter(outputPath, resourceProvider); + }); + + File getConvertedFile(String path) => + resourceProvider.getFile(resourceProvider.convertPath(path)); + + tearDown(() { + projectRoot = null; + projectPath = null; + clearPackageMetaCache(); + }); + + test('a null package has some assets', () async { + await generator.generate(null, writer); + var outputPath = projectRoot.getChildAssumingFolder('doc').path; + var output = resourceProvider + .getFolder(pathContext.join(outputPath, 'static-assets')); + expect(output, doesExist); + + for (var resource in resourceNames.map((r) => + pathContext.relative(Uri.parse(r).path, from: 'dartdoc/resources'))) { + expect( + resourceProvider.getFile(pathContext.join(output.path, resource)), + doesExist); + } + }); + + test('libraries with no duplicates are not warned about', () async { + getConvertedFile('$projectPath/lib/a.dart') + .writeAsStringSync('library a;'); + getConvertedFile('$projectPath/lib/b.dart') + .writeAsStringSync('library b;'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + await generator.generate(packageGraph, writer); + + expect(packageGraph.packageWarningCounter.errorCount, 0); + }, onPlatform: {'windows': Skip('Test does not work on Windows (#2446)')}); + + test('libraries with duplicate names are warned about', () async { + getConvertedFile('$projectPath/lib/a.dart') + .writeAsStringSync('library a;'); + getConvertedFile('$projectPath/lib/b.dart') + .writeAsStringSync('library a;'); + var packageGraph = await utils.bootBasicPackage( + projectPath, packageMetaProvider, packageConfigProvider); + await generator.generate(packageGraph, writer); + + var expectedPath = pathContext.join('a', 'a-library.html'); + expect( + packageGraph.localPublicLibraries, + anyElement((l) => packageGraph.packageWarningCounter + .hasWarning(l, PackageWarning.duplicateFile, expectedPath))); + }, onPlatform: {'windows': Skip('Test does not work on Windows (#2446)')}); + }, onPlatform: { + 'windows': Skip('Tests do not work on Windows after NNBD conversion') }); - - File getConvertedFile(String path) => - resourceProvider.getFile(resourceProvider.convertPath(path)); - - tearDown(() { - projectRoot = null; - projectPath = null; - clearPackageMetaCache(); - }); - - test('a null package has some assets', () async { - await generator.generate(null, writer); - var outputPath = projectRoot.getChildAssumingFolder('doc').path; - var output = resourceProvider - .getFolder(pathContext.join(outputPath, 'static-assets')); - expect(output, doesExist); - - for (var resource in resourceNames.map((r) => - pathContext.relative(Uri.parse(r).path, from: 'dartdoc/resources'))) { - expect(resourceProvider.getFile(pathContext.join(output.path, resource)), - doesExist); - } - }); - - test('libraries with no duplicates are not warned about', () async { - getConvertedFile('$projectPath/lib/a.dart').writeAsStringSync('library a;'); - getConvertedFile('$projectPath/lib/b.dart').writeAsStringSync('library b;'); - var packageGraph = await utils.bootBasicPackage( - projectPath, packageMetaProvider, packageConfigProvider); - await generator.generate(packageGraph, writer); - - expect(packageGraph.packageWarningCounter.errorCount, 0); - }, onPlatform: {'windows': Skip('Test does not work on Windows (#2446)')}); - - test('libraries with duplicate names are warned about', () async { - getConvertedFile('$projectPath/lib/a.dart').writeAsStringSync('library a;'); - getConvertedFile('$projectPath/lib/b.dart').writeAsStringSync('library a;'); - var packageGraph = await utils.bootBasicPackage( - projectPath, packageMetaProvider, packageConfigProvider); - await generator.generate(packageGraph, writer); - - var expectedPath = pathContext.join('a', 'a-library.html'); - expect( - packageGraph.localPublicLibraries, - anyElement((l) => packageGraph.packageWarningCounter - .hasWarning(l, PackageWarning.duplicateFile, expectedPath))); - }, onPlatform: {'windows': Skip('Test does not work on Windows (#2446)')}); } const Matcher doesExist = _DoesExist(); diff --git a/test/src/utils.dart b/test/src/utils.dart index bf3e3c4b42..c288806484 100644 --- a/test/src/utils.dart +++ b/test/src/utils.dart @@ -10,6 +10,7 @@ import 'dart:io'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; +import 'package:analyzer/src/dart/sdk/sdk.dart'; import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; import 'package:dartdoc/src/markdown_processor.dart'; @@ -84,50 +85,35 @@ PackageConfigProvider getTestPackageConfigProvider(String sdkPath) { /// Returns a [PackageMetaProvider] using a [MemoryResourceProvider]. PackageMetaProvider get testPackageMetaProvider { var resourceProvider = MemoryResourceProvider(); - var mockSdk = MockSdk(resourceProvider: resourceProvider); - var sdkFolder = writeMockSdkFiles(mockSdk); + final sdkRoot = resourceProvider.getFolder( + resourceProvider.convertPath('/sdk'), + ); + createMockSdk( + resourceProvider: resourceProvider, + root: sdkRoot, + ); + writeMockSdkFiles(sdkRoot); return PackageMetaProvider( PubPackageMeta.fromElement, PubPackageMeta.fromFilename, PubPackageMeta.fromDir, resourceProvider, - sdkFolder, - defaultSdk: mockSdk, + sdkRoot, + defaultSdk: FolderBasedDartSdk(resourceProvider, sdkRoot), messageForMissingPackageMeta: PubPackageMeta.messageForMissingPackageMeta, ); } -/// Writes [mockSdk] to disk at both its original path, and its canonicalized -/// path (they may be different on Windows). +/// Writes additional files for a mock SDK. /// /// Included is a "version" file and an "api_readme.md" file. -Folder writeMockSdkFiles(MockSdk mockSdk) { - var resourceProvider = mockSdk.resourceProvider; - var pathContext = resourceProvider.pathContext; - - // The [MockSdk] only works in non-canonicalized paths, which include - // "C:\sdk", on Windows. However, dartdoc works almost exclusively with - // canonical paths ("c:\sdk"). Copy all MockSdk files to the canonicalized - // path. - for (var l in mockSdk.sdkLibraries) { - var p = l.path; - resourceProvider - .getFile(pathContext.canonicalize(p)) - .writeAsStringSync(resourceProvider.getFile(p).readAsStringSync()); - } - var sdkFolder = resourceProvider.getFolder( - pathContext.canonicalize(resourceProvider.convertPath(sdkRoot))) - ..create(); +void writeMockSdkFiles(Folder sdkFolder) { sdkFolder.getChildAssumingFile('version').writeAsStringSync('2.9.0'); sdkFolder.getChildAssumingFile('api_readme.md').writeAsStringSync( 'Welcome to the [Dart](https://dart.dev/) API reference documentation'); _writeMockSdkBinFiles(sdkFolder); - _writeMockSdkBinFiles( - resourceProvider.getFolder(resourceProvider.convertPath(sdkRoot))); - - return sdkFolder; } /// Dartdoc has a few indicator files it uses to verify that a directory