Chromium Code Reviews| Index: pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
| diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
| index ad50ac35aacb0c5f6bd24ec2d813931568524957..2fd0746026a8600a02f4b652eef0d481dad1e263 100644 |
| --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
| +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
| @@ -27,6 +27,7 @@ import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/dart/element/type.dart'; |
| import 'package:analyzer/error/error.dart'; |
| import 'package:analyzer/file_system/file_system.dart'; |
| +import 'package:analyzer/src/dart/analysis/driver.dart'; |
| import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; |
| import 'package:analyzer/src/dart/ast/token.dart'; |
| import 'package:analyzer/src/dart/ast/utilities.dart'; |
| @@ -40,6 +41,7 @@ import 'package:analyzer/src/generated/engine.dart'; |
| import 'package:analyzer/src/generated/error_verifier.dart'; |
| import 'package:analyzer/src/generated/java_core.dart'; |
| import 'package:analyzer/src/generated/parser.dart'; |
| +import 'package:analyzer/src/generated/resolver.dart'; |
| import 'package:analyzer/src/generated/source.dart'; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:analyzer_plugin/protocol/protocol_common.dart' |
| @@ -59,13 +61,17 @@ typedef bool ElementPredicate(Element argument); |
| * Clients may not extend, implement or mix-in this class. |
| */ |
| class DartFixContextImpl extends FixContextImpl implements DartFixContext { |
| - final GetTopLevelDeclarations getTopLevelDeclarations; |
| + @override |
| final AstProvider astProvider; |
| + |
| + @override |
| final CompilationUnit unit; |
| - DartFixContextImpl(FixContext fixContext, this.getTopLevelDeclarations, |
| - this.astProvider, this.unit) |
| + DartFixContextImpl(FixContext fixContext, this.astProvider, this.unit) |
| : super.from(fixContext); |
| + |
| + GetTopLevelDeclarations get getTopLevelDeclarations => |
| + analysisDriver.getTopLevelNameDeclarations; |
| } |
| /** |
| @@ -95,7 +101,12 @@ class FixProcessor { |
| GetTopLevelDeclarations getTopLevelDeclarations; |
| CompilationUnit unit; |
| AnalysisError error; |
| - AnalysisContext context; |
| + |
| + /** |
| + * The analysis driver being used to perform analysis. |
| + */ |
| + AnalysisDriver driver; |
| + |
| String file; |
| int fileStamp; |
| CompilationUnitElement unitElement; |
| @@ -120,18 +131,21 @@ class FixProcessor { |
| AstNode node; |
| AstNode coveredNode; |
| + TypeProvider _typeProvider; |
| + TypeSystem _typeSystem; |
| + |
| FixProcessor(DartFixContext dartContext) { |
| resourceProvider = dartContext.resourceProvider; |
| astProvider = dartContext.astProvider; |
| getTopLevelDeclarations = dartContext.getTopLevelDeclarations; |
| - context = dartContext.analysisContext; |
| + driver = dartContext.analysisDriver; |
| // unit |
| unit = dartContext.unit; |
| unitElement = unit.element; |
| unitSource = unitElement.source; |
| // file |
| file = unitSource.fullName; |
| - fileStamp = context.getModificationStamp(unitSource); |
| + fileStamp = _modificationStamp(file); |
| // library |
| unitLibraryElement = unitElement.library; |
| String unitLibraryPath = unitLibraryElement.source.fullName; |
| @@ -148,10 +162,30 @@ class FixProcessor { |
| */ |
| String get eol => utils.endOfLine; |
| + Future<TypeProvider> get typeProvider async { |
| + if (_typeProvider == null) { |
|
scheglov
2017/05/22 15:48:55
We are already given dartContext.unit, with its el
Brian Wilkerson
2017/05/22 16:03:01
Is it better to introduce a temporary dependency o
scheglov
2017/05/22 16:07:33
I think it is better to keep AnalysisContext depen
Brian Wilkerson
2017/05/22 17:41:12
I've put it back for now, but the next step for th
|
| + LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core'); |
| + LibraryElement asyncLibrary = await driver.getLibraryByUri('dart:async'); |
| + _typeProvider = new TypeProviderImpl(coreLibrary, asyncLibrary); |
| + } |
| + return _typeProvider; |
| + } |
| + |
| + Future<TypeSystem> get typeSystem async { |
| + if (_typeSystem == null) { |
| + if (driver.analysisOptions.strongMode) { |
| + _typeSystem = new StrongTypeSystemImpl(await typeProvider); |
| + } else { |
| + _typeSystem = new TypeSystemImpl(await typeProvider); |
| + } |
| + } |
| + return _typeSystem; |
| + } |
| + |
| Future<List<Fix>> compute() async { |
| // If the source was changed between the constructor and running |
| // this asynchronous method, it is not safe to use the unit. |
| - if (context.getModificationStamp(unitSource) != fileStamp) { |
| + if (_modificationStamp(unitSource.fullName) != fileStamp) { |
| return const <Fix>[]; |
| } |
| @@ -178,7 +212,7 @@ class FixProcessor { |
| _addFix_replaceWithConstInstanceCreation(); |
| } |
| if (errorCode == CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT) { |
| - _addFix_addAsync_asyncFor(); |
| + await _addFix_addAsync(); |
| } |
| if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION) { |
| if (node is Annotation) { |
| @@ -296,7 +330,7 @@ class FixProcessor { |
| _addFix_makeEnclosingClassAbstract(); |
| _addFix_createNoSuchMethod(); |
| // implement methods |
| - _addFix_createMissingOverrides(); |
| + await _addFix_createMissingOverrides(); |
| } |
| if (errorCode == CompileTimeErrorCode.UNDEFINED_CLASS || |
| errorCode == StaticWarningCode.CAST_TO_NON_TYPE || |
| @@ -326,10 +360,10 @@ class FixProcessor { |
| _addFix_createLocalVariable(); |
| } |
| if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) { |
| - _addFix_addAsync(); |
| + await _addFix_addAsync(); |
| } |
| if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) { |
| - _addFix_illegalAsyncReturnType(); |
| + await _addFix_illegalAsyncReturnType(); |
| } |
| if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { |
| _addFix_useStaticAccess_method(); |
| @@ -459,23 +493,12 @@ class FixProcessor { |
| /** |
| * Returns `true` if the `async` proposal was added. |
| */ |
| - bool _addFix_addAsync() { |
| + Future<Null> _addFix_addAsync() async { |
| AstNode node = this.node; |
| FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
| if (body != null && body.keyword == null) { |
| _addReplaceEdit(range.startLength(body, 0), 'async '); |
| - _replaceReturnTypeWithFuture(body); |
| - _addFix(DartFixKind.ADD_ASYNC, []); |
| - return true; |
| - } |
| - return false; |
| - } |
| - |
| - void _addFix_addAsync_asyncFor() { |
| - FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
| - if (body != null && body.keyword == null) { |
| - _addReplaceEdit(range.startLength(body, 0), 'async '); |
| - _replaceReturnTypeWithFuture(body); |
| + _replaceReturnTypeWithFuture(body, await typeProvider); |
| _addFix(DartFixKind.ADD_ASYNC, []); |
| } |
| } |
| @@ -1413,16 +1436,16 @@ class FixProcessor { |
| _addFix(DartFixKind.CREATE_LOCAL_VARIABLE, [name]); |
| } |
| - void _addFix_createMissingOverrides() { |
| + Future<Null> _addFix_createMissingOverrides() async { |
| // prepare target |
| ClassDeclaration targetClass = node.parent as ClassDeclaration; |
| ClassElement targetClassElement = targetClass.element; |
| utils.targetClassElement = targetClassElement; |
| List<ExecutableElement> elements = ErrorVerifier |
| .computeMissingOverrides( |
| - context.analysisOptions.strongMode, |
| - context.typeProvider, |
| - context.typeSystem, |
| + driver.analysisOptions.strongMode, |
| + await typeProvider, |
| + await typeSystem, |
| new InheritanceManager(unitLibraryElement), |
| targetClassElement) |
| .toList(); |
| @@ -1588,10 +1611,10 @@ class FixProcessor { |
| } |
| } |
| - void _addFix_illegalAsyncReturnType() { |
| + Future<Null> _addFix_illegalAsyncReturnType() async { |
| // prepare the existing type |
| TypeAnnotation typeName = node.getAncestor((n) => n is TypeAnnotation); |
| - _replaceTypeWithFuture(typeName); |
| + _replaceTypeWithFuture(typeName, await typeProvider); |
| // add proposal |
| _addFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, []); |
| } |
| @@ -3105,6 +3128,12 @@ class FixProcessor { |
| .isWithin(packageRoot.path, source.fullName); |
| } |
| + int _modificationStamp(String filePath) { |
| + // TODO(brianwilkerson) We have lost the ability for clients to know whether |
| + // it is safe to apply an edit. |
| + return driver.fsState.getFileForPath(filePath).exists ? 0 : -1; |
| + } |
| + |
| /** |
| * Removes any [ParenthesizedExpression] enclosing [expr]. |
| * |
| @@ -3123,20 +3152,21 @@ class FixProcessor { |
| } |
| } |
| - void _replaceReturnTypeWithFuture(AstNode node) { |
| + void _replaceReturnTypeWithFuture(AstNode node, TypeProvider typeProvider) { |
| for (; node != null; node = node.parent) { |
| if (node is FunctionDeclaration) { |
| - _replaceTypeWithFuture(node.returnType); |
| + _replaceTypeWithFuture(node.returnType, typeProvider); |
| return; |
| } else if (node is MethodDeclaration) { |
| - _replaceTypeWithFuture(node.returnType); |
| + _replaceTypeWithFuture(node.returnType, typeProvider); |
| return; |
| } |
| } |
| } |
| - void _replaceTypeWithFuture(TypeAnnotation typeName) { |
| - InterfaceType futureType = context.typeProvider.futureType; |
| + void _replaceTypeWithFuture( |
| + TypeAnnotation typeName, TypeProvider typeProvider) { |
| + InterfaceType futureType = typeProvider.futureType; |
| // validate the type |
| DartType type = typeName?.type; |
| if (type == null || |