From 9263f70a3deb722c270052b55a81693c6584703d Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Wed, 13 Nov 2019 14:10:20 -0800 Subject: [PATCH] Initial nnbd implementation and cleanup (#2069) --- analysis_options.yaml | 3 - lib/src/model/field.dart | 4 + lib/src/model/package_builder.dart | 3 +- pubspec.yaml | 4 +- test/dartdoc_test.dart | 13 ++- test/model_special_cases_test.dart | 59 ++++-------- test/model_test.dart | 91 +++++++++++++++---- test/src/utils.dart | 12 ++- .../lib/set_literals.dart} | 0 .../analysis_options.yaml | 4 + .../lib/late_final_without_initializer.dart | 18 ++++ 11 files changed, 137 insertions(+), 74 deletions(-) rename testing/{test_package_experiments/lib/main.dart => test_package/lib/set_literals.dart} (100%) create mode 100644 testing/test_package_experiments/analysis_options.yaml create mode 100644 testing/test_package_experiments/lib/late_final_without_initializer.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 9ab324b018..5bbf4f3e53 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,9 +1,6 @@ include: package:pedantic/analysis_options.1.8.0.yaml analyzer: - # enable for analysis on test package sources. - enable-experiment: - - extension-methods exclude: - 'doc/**' - 'lib/src/third_party/pkg/**' diff --git a/lib/src/model/field.dart b/lib/src/model/field.dart index fe8c27ace5..0232a2d577 100644 --- a/lib/src/model/field.dart +++ b/lib/src/model/field.dart @@ -4,6 +4,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/element/element.dart'; +import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/model.dart'; class Field extends ModelElement @@ -184,6 +185,9 @@ class Field extends ModelElement } } + @override + CallableElementType get modelType => super.modelType; + @override Inheritable get overriddenElement => null; } diff --git a/lib/src/model/package_builder.dart b/lib/src/model/package_builder.dart index 02c6048a0d..8d82ca138f 100644 --- a/lib/src/model/package_builder.dart +++ b/lib/src/model/package_builder.dart @@ -152,8 +152,7 @@ class PackageBuilder { AnalysisOptionsImpl options = AnalysisOptionsImpl(); // TODO(jcollins-g): pass in an ExperimentStatus instead? - options.enabledExperiments = config.enableExperiment - ..add('extension-methods'); + options.enabledExperiments = config.enableExperiment; // TODO(jcollins-g): Make use of currently not existing API for managing // many AnalysisDrivers diff --git a/pubspec.yaml b/pubspec.yaml index 86e0fd62d7..4d24979772 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,10 +5,10 @@ author: Dart Team description: A documentation generator for Dart. homepage: https://github.com/dart-lang/dartdoc environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.6.0 <3.0.0' dependencies: - analyzer: ^0.39.0 + analyzer: ^0.39.1 args: '>=1.5.0 <2.0.0' collection: ^1.2.0 crypto: ^2.0.6 diff --git a/test/dartdoc_test.dart b/test/dartdoc_test.dart index 02400fe720..2b393bd29a 100644 --- a/test/dartdoc_test.dart +++ b/test/dartdoc_test.dart @@ -258,7 +258,9 @@ void main() { expect(p.name, 'test_package'); expect(p.hasDocumentationFile, isTrue); // Total number of public libraries in test_package. - expect(packageGraph.defaultPackage.publicLibraries, hasLength(16)); + // +2 since we are not manually excluding anything. + expect(packageGraph.defaultPackage.publicLibraries, + hasLength(kTestPackagePublicLibraries + 2)); expect(packageGraph.localPackages.length, equals(1)); }); @@ -313,8 +315,8 @@ void main() { PackageGraph p = results.packageGraph; expect(p.defaultPackage.name, 'test_package'); expect(p.defaultPackage.hasDocumentationFile, isTrue); - expect(p.libraries, hasLength(1)); - expect(p.libraries.map((lib) => lib.name), contains('fake')); + expect(p.localPublicLibraries, hasLength(1)); + expect(p.localPublicLibraries.map((lib) => lib.name), contains('fake')); }); test('generate docs excluding a single library', () async { @@ -327,7 +329,10 @@ void main() { PackageGraph p = results.packageGraph; expect(p.defaultPackage.name, 'test_package'); expect(p.defaultPackage.hasDocumentationFile, isTrue); - expect(p.localPublicLibraries, hasLength(15)); + // Plus 1 here because we're excluding only two libraries (the specified + // one and the 'excluded' library) instead of three. + expect( + p.localPublicLibraries, hasLength(kTestPackagePublicLibraries + 1)); expect(p.localPublicLibraries.map((lib) => lib.name).contains('fake'), isFalse); }); diff --git a/test/model_special_cases_test.dart b/test/model_special_cases_test.dart index e94f3c28e3..c8575a70db 100644 --- a/test/model_special_cases_test.dart +++ b/test/model_special_cases_test.dart @@ -29,49 +29,26 @@ void main() { // Experimental features not yet enabled by default. Move tests out of this block // when the feature is enabled by default. group('Experiments', () { - Library main; - TopLevelVariable aComplexSet, - inferredTypeSet, - specifiedSet, - untypedMap, - typedSet; - + Library lateFinalWithoutInitializer; setUpAll(() async { - main = (await utils.testPackageGraphExperiments) + lateFinalWithoutInitializer = (await utils.testPackageGraphExperiments) .libraries - .firstWhere((lib) => lib.name == 'main'); - aComplexSet = main.constants.firstWhere((v) => v.name == 'aComplexSet'); - inferredTypeSet = - main.constants.firstWhere((v) => v.name == 'inferredTypeSet'); - specifiedSet = main.constants.firstWhere((v) => v.name == 'specifiedSet'); - untypedMap = main.constants.firstWhere((v) => v.name == 'untypedMap'); - typedSet = main.constants.firstWhere((v) => v.name == 'typedSet'); - }); - - test('Set literals test', () { - expect(aComplexSet.modelType.name, equals('Set')); - expect(aComplexSet.modelType.typeArguments.map((a) => a.name).toList(), - equals(['AClassContainingLiterals'])); - expect(aComplexSet.constantValue, - equals('const {const AClassContainingLiterals(3, 5)}')); - expect(inferredTypeSet.modelType.name, equals('Set')); - expect( - inferredTypeSet.modelType.typeArguments.map((a) => a.name).toList(), - equals(['num'])); - expect(inferredTypeSet.constantValue, equals('const {1, 2.5, 3}')); - expect(specifiedSet.modelType.name, equals('Set')); - expect(specifiedSet.modelType.typeArguments.map((a) => a.name).toList(), - equals(['int'])); - expect(specifiedSet.constantValue, equals('const {}')); - expect(untypedMap.modelType.name, equals('Map')); - expect(untypedMap.modelType.typeArguments.map((a) => a.name).toList(), - equals(['dynamic', 'dynamic'])); - expect(untypedMap.constantValue, equals('const {}')); - expect(typedSet.modelType.name, equals('Set')); - expect(typedSet.modelType.typeArguments.map((a) => a.name).toList(), - equals(['String'])); - expect(typedSet.constantValue, - matches(RegExp(r'const <String>\s?{}'))); + .firstWhere((lib) => lib.name == 'late_final_without_initializer'); + }); + + test('Late finals test', () { + Class c = lateFinalWithoutInitializer.allClasses + .firstWhere((c) => c.name == 'C'); + Field a = c.allFields.firstWhere((f) => f.name == 'a'); + Field b = c.allFields.firstWhere((f) => f.name == 'b'); + Field cField = c.allFields.firstWhere((f) => f.name == 'cField'); + Field dField = c.allFields.firstWhere((f) => f.name == 'dField'); + // If nnbd isn't enabled, fields named 'late' come back from the analyzer. + expect(c.allFields.any((f) => f.name == 'late'), isFalse); + expect(a.modelType.returnType.name, equals('dynamic')); + expect(b.modelType.returnType.name, equals('int')); + expect(cField.modelType.returnType.name, equals('dynamic')); + expect(dField.modelType.returnType.name, equals('double')); }); }); diff --git a/test/model_test.dart b/test/model_test.dart index a7cbc1ac36..1d74f7e909 100644 --- a/test/model_test.dart +++ b/test/model_test.dart @@ -76,6 +76,55 @@ void main() { packageGraph.libraries.firstWhere((lib) => lib.name == 'base_class'); }); + group('Set Literals', () { + Library set_literals; + TopLevelVariable aComplexSet, + inferredTypeSet, + specifiedSet, + untypedMap, + typedSet; + + setUpAll(() async { + set_literals = packageGraph.libraries + .firstWhere((lib) => lib.name == 'set_literals'); + aComplexSet = + set_literals.constants.firstWhere((v) => v.name == 'aComplexSet'); + inferredTypeSet = + set_literals.constants.firstWhere((v) => v.name == 'inferredTypeSet'); + specifiedSet = + set_literals.constants.firstWhere((v) => v.name == 'specifiedSet'); + untypedMap = + set_literals.constants.firstWhere((v) => v.name == 'untypedMap'); + typedSet = set_literals.constants.firstWhere((v) => v.name == 'typedSet'); + }); + + test('Set literals test', () { + expect(aComplexSet.modelType.name, equals('Set')); + expect(aComplexSet.modelType.typeArguments.map((a) => a.name).toList(), + equals(['AClassContainingLiterals'])); + expect(aComplexSet.constantValue, + equals('const {const AClassContainingLiterals(3, 5)}')); + expect(inferredTypeSet.modelType.name, equals('Set')); + expect( + inferredTypeSet.modelType.typeArguments.map((a) => a.name).toList(), + equals(['num'])); + expect(inferredTypeSet.constantValue, equals('const {1, 2.5, 3}')); + expect(specifiedSet.modelType.name, equals('Set')); + expect(specifiedSet.modelType.typeArguments.map((a) => a.name).toList(), + equals(['int'])); + expect(specifiedSet.constantValue, equals('const {}')); + expect(untypedMap.modelType.name, equals('Map')); + expect(untypedMap.modelType.typeArguments.map((a) => a.name).toList(), + equals(['dynamic', 'dynamic'])); + expect(untypedMap.constantValue, equals('const {}')); + expect(typedSet.modelType.name, equals('Set')); + expect(typedSet.modelType.typeArguments.map((a) => a.name).toList(), + equals(['String'])); + expect(typedSet.constantValue, + matches(RegExp(r'const <String>\s?{}'))); + }); + }); + group('Tools', () { Class toolUser; Class _NonCanonicalToolUser, CanonicalToolUser, PrivateLibraryToolUser; @@ -291,10 +340,6 @@ void main() { ])); expect(packageCategories.map((c) => c.libraries.length).toList(), orderedEquals([0, 2, 3, 1, 0, 0])); - expect( - packageGraph - .localPackages.first.defaultCategory.publicLibraries.length, - equals(9)); }); test('Verify libraries with multiple categories show up in multiple places', @@ -313,7 +358,8 @@ void main() { expect( packageGraph .localPackages.first.defaultCategory.publicLibraries.length, - equals(9)); + // Only 5 libraries have categories, the rest belong in default. + equals(utils.kTestPackagePublicLibraries - 5)); }); }); @@ -383,7 +429,8 @@ void main() { }); test('libraries', () { - expect(packageGraph.localPublicLibraries, hasLength(14)); + expect(packageGraph.localPublicLibraries, + hasLength(utils.kTestPackagePublicLibraries)); expect(interceptorsLib.isPublic, isFalse); }); @@ -398,7 +445,8 @@ void main() { Package package = packageGraph.localPackages.first; expect(package.name, 'test_package'); - expect(package.publicLibraries, hasLength(14)); + expect(package.publicLibraries, + hasLength(utils.kTestPackagePublicLibraries)); }); test('is documented in library', () { @@ -710,11 +758,12 @@ void main() { EnumField enumValue2; setUpAll(() { - enumWithAnimation = exLibrary.enums.firstWhere((c) => c.name == 'EnumWithAnimation'); - enumValue1 = enumWithAnimation.constants - .firstWhere((m) => m.name == 'value1'); - enumValue2 = enumWithAnimation.constants - .firstWhere((m) => m.name == 'value2'); + enumWithAnimation = + exLibrary.enums.firstWhere((c) => c.name == 'EnumWithAnimation'); + enumValue1 = + enumWithAnimation.constants.firstWhere((m) => m.name == 'value1'); + enumValue2 = + enumWithAnimation.constants.firstWhere((m) => m.name == 'value2'); dog = exLibrary.classes.firstWhere((c) => c.name == 'Dog'); withAnimation = dog.allInstanceMethods.firstWhere((m) => m.name == 'withAnimation'); @@ -775,12 +824,18 @@ void main() { contains('