Index: pkg/analysis_server/lib/src/services/completion/completion_dart.dart |
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_dart.dart b/pkg/analysis_server/lib/src/services/completion/completion_dart.dart |
index 1cfff042d6017ca98311ae8b46b881391146b2e3..1ccc28b5ede0492ae4196f3eb6b56c3b058f60b1 100644 |
--- a/pkg/analysis_server/lib/src/services/completion/completion_dart.dart |
+++ b/pkg/analysis_server/lib/src/services/completion/completion_dart.dart |
@@ -4,11 +4,21 @@ |
library analysis_server.src.services.completion.completion_dart; |
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'; |
+import 'dart:async'; |
+ |
+import 'package:analysis_server/src/provisional/completion/completion_core.dart' |
+ show CompletionRequest; |
import 'package:analysis_server/src/provisional/completion/completion_dart.dart'; |
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart'; |
import 'package:analysis_server/src/services/completion/completion_core.dart'; |
+import 'package:analyzer/file_system/file_system.dart'; |
+import 'package:analyzer/src/context/context.dart' |
+ show AnalysisFutureHelper, AnalysisContextImpl; |
import 'package:analyzer/src/generated/ast.dart'; |
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl; |
+import 'package:analyzer/src/generated/source.dart'; |
+import 'package:analyzer/src/task/dart.dart'; |
+import 'package:analyzer/task/dart.dart'; |
/** |
* The information about a requested list of completions within a Dart file. |
@@ -16,26 +26,75 @@ import 'package:analyzer/src/generated/ast.dart'; |
class DartCompletionRequestImpl extends CompletionRequestImpl |
implements DartCompletionRequest { |
/** |
- * The compilation unit in which the completion was requested. |
+ * The cached completion target or `null` if not computed yet. |
*/ |
- final CompilationUnit unit; |
+ CompletionTarget _target; |
/** |
- * A flag indicating whether the compilation [unit] is resolved. |
+ * `true` if [resolveDeclarationsInScope] has partially resolved the unit |
+ * referenced by [target], else `false`. |
*/ |
- final bool isResolved; |
+ bool _haveResolveDeclarationsInScope = false; |
/** |
- * The completion target. This determines what part of the parse tree |
- * will receive the newly inserted text. |
+ * Initialize a newly created completion request based on the given request. |
*/ |
- final CompletionTarget target; |
+ factory DartCompletionRequestImpl.forRequest(CompletionRequest request) { |
+ return new DartCompletionRequestImpl._(request.context, |
+ request.resourceProvider, request.source, request.offset); |
+ } |
- /** |
- * Initialize a newly created completion request based on the given arguments. |
- */ |
- DartCompletionRequestImpl( |
- CompletionRequest request, this.unit, this.isResolved, this.target) |
- : super(request.context, request.resourceProvider, request.source, |
- request.offset); |
+ DartCompletionRequestImpl._(AnalysisContext context, |
+ ResourceProvider resourceProvider, Source source, int offset) |
+ : super(context, resourceProvider, source, offset); |
+ |
+ @override |
+ Future<CompilationUnit> resolveDeclarationsInScope() async { |
+ CompilationUnit unit = target.unit; |
+ if (_haveResolveDeclarationsInScope) { |
+ return unit; |
+ } |
+ |
+ // Determine the library source |
+ Source librarySource; |
+ if (unit.directives.any((d) => d is PartOfDirective)) { |
+ List<Source> libraries = context.getLibrariesContaining(source); |
+ if (libraries.isEmpty) { |
+ return null; |
+ } |
+ librarySource = libraries[0]; |
+ } else { |
+ librarySource = source; |
+ } |
+ |
+ // Resolve declarations in the target unit |
+ CompilationUnit resolvedUnit = |
+ await new AnalysisFutureHelper<CompilationUnit>( |
+ context, |
+ new LibrarySpecificUnit(librarySource, source), |
+ RESOLVED_UNIT3).computeAsync(); |
+ |
+ // TODO(danrubel) determine if the underlying source has been modified |
+ // in a way that invalidates the completion request |
+ // and return null |
+ |
+ // Gracefully degrade if unit cannot be resolved |
+ if (resolvedUnit == null) { |
+ return null; |
+ } |
+ |
+ // Recompute the target for the newly resolved unit |
+ _target = new CompletionTarget.forOffset(resolvedUnit, offset); |
+ _haveResolveDeclarationsInScope = true; |
+ return resolvedUnit; |
+ } |
+ |
+ @override |
+ CompletionTarget get target { |
+ if (_target == null) { |
+ CompilationUnit unit = context.computeResult(source, PARSED_UNIT); |
+ _target = new CompletionTarget.forOffset(unit, offset); |
+ } |
+ return _target; |
+ } |
} |