Move NNBD migration tool to a fresh package.

This gives us more flexibility for how we want to publish and deploy
the tool.  We now have the option, for example, of making a command
line app that invokes the tool and does not depend on analysis_server.

Note that some testing infrastructure had to be duplicated.  I plan to
consolidate this infrastructure in follow-up CLs.

Change-Id: I046506bc2bb5c3e467e15885f198ee0632351ee9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105463
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Paul Berry 2019-06-09 17:45:35 +00:00 committed by commit-bot@chromium.org
parent 6c358d3ba6
commit 51046368c5
23 changed files with 282 additions and 46 deletions

View file

@ -61,6 +61,7 @@ mime:third_party/pkg/mime/lib
mockito:third_party/pkg/mockito/lib
modular_test:pkg/modular_test/lib
mustache:third_party/pkg/mustache/lib
nnbd_migration:pkg/nnbd_migration/lib
oauth2:third_party/pkg/oauth2/lib
observatory:runtime/observatory/lib
observatory_test_package:runtime/observatory/tests/service/observatory_test_package

View file

@ -5,7 +5,7 @@
import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
import 'package:analysis_server/src/nullability/provisional_api.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';

View file

@ -15,6 +15,7 @@ dependencies:
linter: any
logging: any
meta: any
nnbd_migration: any
source_span: any
package_config: any
path: any

View file

@ -9,7 +9,6 @@ import 'domain_abstract_test.dart' as domain_abstract;
import 'domains/test_all.dart' as domains;
import 'flutter/test_all.dart' as flutter;
import 'lsp/test_all.dart' as lsp;
import 'nullability/test_all.dart' as nullability;
import 'plugin/test_all.dart' as plugin;
import 'services/test_all.dart' as services;
import 'utilities/test_all.dart' as utilities;
@ -25,7 +24,6 @@ main() {
domains.main();
flutter.main();
lsp.main();
nullability.main();
plugin.main();
services.main();
utilities.main();

View file

@ -0,0 +1,2 @@
## 0.1.0-dev (not yet published)
* Separated from analysis_server project.

View file

@ -0,0 +1,26 @@
Copyright 2019, the Dart project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,4 @@
# NNBD Migration Engine
This package provides infrastructure for migrating code to be non-nullable by
default.

View file

@ -2,16 +2,13 @@
// 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:analysis_server/src/nullability/decorated_type.dart'
as analyzer;
import 'package:analysis_server/src/nullability/expression_checks.dart'
as analyzer;
import 'package:analysis_server/src/nullability/transitional_api.dart'
as analyzer;
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/decorated_type.dart' as analyzer;
import 'package:nnbd_migration/src/expression_checks.dart' as analyzer;
import 'package:nnbd_migration/src/transitional_api.dart' as analyzer;
/// Kinds of fixes that might be performed by nullability migration.
class NullabilityFixKind {

View file

@ -2,7 +2,7 @@
// 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:analysis_server/src/nullability/nullability_node.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
/// Container for information gathered during nullability migration about a
/// conditional check that might need to be discarded.

View file

@ -2,12 +2,12 @@
// 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:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/transitional_api.dart';
/// Representation of a type in the code to be migrated. In addition to
/// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s

View file

@ -2,11 +2,11 @@
// 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:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/node_builder.dart';
/// [TypeOperations] that works with [DecoratedType]s.
class DecoratedTypeOperations implements TypeOperations<DecoratedType> {

View file

@ -2,9 +2,9 @@
// 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:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/transitional_api.dart';
/// Container for information gathered during nullability migration about the
/// set of runtime checks that might need to be performed on the value of an

View file

@ -2,12 +2,6 @@
// 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:analysis_server/src/nullability/conditional_discard.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/provisional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@ -17,6 +11,12 @@ import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
/// Visitor that builds nullability graph edges by examining code to be
/// migrated.

View file

@ -2,11 +2,6 @@
// 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:analysis_server/src/nullability/conditional_discard.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/provisional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
@ -15,6 +10,11 @@ import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:front_end/src/scanner/token.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
/// Visitor that builds nullability nodes based on visiting code to be migrated.
///

View file

@ -2,18 +2,18 @@
// 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:analysis_server/src/nullability/conditional_discard.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
import 'package:analysis_server/src/nullability/graph_builder.dart';
import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/provisional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/graph_builder.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
/// Records information about how a conditional expression or statement might
/// need to be modified.

View file

@ -0,0 +1,6 @@
name: nnbd_migration
publish_to: none
environment:
sdk: '>=2.2.2 <3.0.0'
dependencies:
analyzer: ^0.36.3

View file

@ -0,0 +1,140 @@
// Copyright (c) 2019, 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/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
/// TODO(paulberry): this logic is duplicated from other packages. Find a way
/// share it, or avoid relying on it.
class AbstractContextTest with ResourceProviderMixin {
OverlayResourceProvider overlayResourceProvider;
AnalysisContextCollection _analysisContextCollection;
AnalysisDriver _driver;
AnalysisDriver get driver => _driver;
AnalysisSession get session => driver.currentSession;
void addMetaPackage() {
addPackageFile('meta', 'meta.dart', r'''
library meta;
const Required required = const Required();
class Required {
final String reason;
const Required([this.reason]);
}
''');
}
/// Add a new file with the given [pathInLib] to the package with the
/// given [packageName]. Then ensure that the test package depends on the
/// [packageName].
File addPackageFile(String packageName, String pathInLib, String content) {
var packagePath = '/.pub-cache/$packageName';
_addTestPackageDependency(packageName, packagePath);
return newFile('$packagePath/lib/$pathInLib', content: content);
}
Source addSource(String path, String content, [Uri uri]) {
File file = newFile(path, content: content);
Source source = file.createSource(uri);
driver.addFile(file.path);
driver.changeFile(file.path);
return source;
}
/// Create all analysis contexts in `/home`.
void createAnalysisContexts() {
_analysisContextCollection = AnalysisContextCollectionImpl(
includedPaths: [convertPath('/home')],
enableIndex: true,
resourceProvider: overlayResourceProvider,
sdkPath: convertPath('/sdk'),
);
var testPath = convertPath('/home/test');
_driver = getDriver(testPath);
}
/// Return the existing analysis context that should be used to analyze the
/// given [path], or throw [StateError] if the [path] is not analyzed in any
/// of the created analysis contexts.
AnalysisContext getContext(String path) {
path = convertPath(path);
return _analysisContextCollection.contextFor(path);
}
/// Return the existing analysis driver that should be used to analyze the
/// given [path], or throw [StateError] if the [path] is not analyzed in any
/// of the created analysis contexts.
AnalysisDriver getDriver(String path) {
DriverBasedAnalysisContext context =
getContext(path) as DriverBasedAnalysisContext;
return context.driver;
}
void setUp() {
setupResourceProvider();
overlayResourceProvider = OverlayResourceProvider(resourceProvider);
new MockSdk(resourceProvider: resourceProvider);
newFolder('/home/test');
newFile('/home/test/.packages', content: r'''
test:file:///home/test/lib
''');
createAnalysisContexts();
}
void setupResourceProvider() {}
void tearDown() {
AnalysisEngine.instance.clearCaches();
AnalysisEngine.instance.logger = null;
}
void _addTestPackageDependency(String name, String rootPath) {
var packagesFile = getFile('/home/test/.packages');
var packagesContent = packagesFile.readAsStringSync();
// Ignore if there is already the same package dependency.
if (packagesContent.contains('$name:file://')) {
return;
}
packagesContent += '$name:${toUri('$rootPath/lib')}\n';
packagesFile.writeAsStringSync(packagesContent);
_createDriver();
}
void _createDriver() {
var collection = AnalysisContextCollectionImpl(
includedPaths: [convertPath('/home')],
enableIndex: true,
resourceProvider: resourceProvider,
sdkPath: convertPath('/sdk'),
);
var testPath = convertPath('/home/test');
var context = collection.contextFor(testPath) as DriverBasedAnalysisContext;
_driver = context.driver;
}
}

View file

@ -0,0 +1,60 @@
// Copyright (c) 2019, 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/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:test/test.dart';
import 'abstract_context.dart';
/// TODO(paulberry): this logic is duplicated from other packages. Find a way
/// share it, or avoid relying on it.
class AbstractSingleUnitTest extends AbstractContextTest {
bool verifyNoTestUnitErrors = true;
String testCode;
String testFile;
Source testSource;
ResolvedUnitResult testAnalysisResult;
CompilationUnit testUnit;
CompilationUnitElement testUnitElement;
LibraryElement testLibraryElement;
FindNode findNode;
void addTestSource(String code, [Uri uri]) {
testCode = code;
testSource = addSource(testFile, code, uri);
}
Future<void> resolveTestUnit(String code) async {
addTestSource(code);
testAnalysisResult = await session.getResolvedUnit(testFile);
testUnit = testAnalysisResult.unit;
if (verifyNoTestUnitErrors) {
expect(testAnalysisResult.errors.where((AnalysisError error) {
return error.errorCode != HintCode.DEAD_CODE &&
error.errorCode != HintCode.UNUSED_CATCH_CLAUSE &&
error.errorCode != HintCode.UNUSED_CATCH_STACK &&
error.errorCode != HintCode.UNUSED_ELEMENT &&
error.errorCode != HintCode.UNUSED_FIELD &&
error.errorCode != HintCode.UNUSED_IMPORT &&
error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
}), isEmpty);
}
testUnitElement = testUnit.declaredElement;
testLibraryElement = testUnitElement.library;
findNode = FindNode(code, testUnit);
}
@override
void setUp() {
super.setUp();
testFile = convertPath('/home/test/lib/test.dart');
}
}

View file

@ -2,13 +2,13 @@
// 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:analysis_server/src/nullability/provisional_api.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../abstract_context.dart';
import 'abstract_context.dart';
main() {
defineReflectiveSuite(() {

View file

@ -2,21 +2,21 @@
// 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:analysis_server/src/nullability/conditional_discard.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
import 'package:analysis_server/src/nullability/graph_builder.dart';
import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/graph_builder.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/transitional_api.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../abstract_single_unit.dart';
import 'abstract_single_unit.dart';
main() {
defineReflectiveSuite(() {

View file

@ -4,12 +4,12 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'api_test.dart' as api_test;
import 'migration_visitor_test.dart' as migration_visitor_test;
import 'provisional_api_test.dart' as provisional_api_test;
main() {
defineReflectiveSuite(() {
migration_visitor_test.main();
provisional_api_test.main();
api_test.main();
});
}

View file

@ -78,6 +78,7 @@ compiler/tool/*: SkipByDesign # Only meant to run on vm
dartfix/test/*: SkipByDesign # Only meant to run on vm
front_end/test/*: SkipByDesign # Only meant to run on vm, most use dart:mirrors and dart:io
front_end/tool/*: SkipByDesign # Only meant to run on vm
nnbd_migration/test/*: SkipByDesign # Uses mirrors
smith/test/*: SkipByDesign # Only meant to run on vm
status_file/test/normalize_test: SkipByDesign # Uses dart:io
status_file/test/parse_and_normalize_test: SkipByDesign # Uses dart:io