OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library services.completion.dart.manager; | 5 library services.completion.dart.manager; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/plugin/protocol/protocol.dart'; | 9 import 'package:analysis_server/plugin/protocol/protocol.dart'; |
10 import 'package:analysis_server/src/provisional/completion/completion_core.dart' | 10 import 'package:analysis_server/src/provisional/completion/completion_core.dart' |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 implements DartCompletionRequest { | 61 implements DartCompletionRequest { |
62 /** | 62 /** |
63 * The source for the library containing the completion request. | 63 * The source for the library containing the completion request. |
64 * This may be different from the source in which the completion is requested | 64 * This may be different from the source in which the completion is requested |
65 * if the completion is being requested in a part file. | 65 * if the completion is being requested in a part file. |
66 * This may be `null` if the library for a part file cannot be determined. | 66 * This may be `null` if the library for a part file cannot be determined. |
67 */ | 67 */ |
68 Source _librarySource; | 68 Source _librarySource; |
69 | 69 |
70 /** | 70 /** |
71 * The cached completion target or `null` if not computed yet. | |
72 */ | |
73 CompletionTarget _target; | |
74 | |
75 /** | |
76 * The [DartType] for Object in dart:core | 71 * The [DartType] for Object in dart:core |
77 */ | 72 */ |
78 InterfaceType _objectType; | 73 InterfaceType _objectType; |
79 | 74 |
80 /** | 75 /** |
81 * `true` if [resolveDeclarationsInScope] has partially resolved the unit | 76 * `true` if [resolveDeclarationsInScope] has partially resolved the unit |
82 * referenced by [target], else `false`. | 77 * referenced by [target], else `false`. |
83 */ | 78 */ |
84 bool _haveResolveDeclarationsInScope = false; | 79 bool _haveResolveDeclarationsInScope = false; |
85 | 80 |
| 81 @override |
| 82 Expression dotTarget; |
| 83 |
| 84 @override |
| 85 CompletionTarget target; |
| 86 |
86 /** | 87 /** |
87 * Initialize a newly created completion request based on the given request. | 88 * Initialize a newly created completion request based on the given request. |
88 */ | 89 */ |
89 factory DartCompletionRequestImpl.forRequest(CompletionRequest request) { | 90 factory DartCompletionRequestImpl.forRequest(CompletionRequest request) { |
90 return new DartCompletionRequestImpl._( | 91 return new DartCompletionRequestImpl._( |
91 request.context, | 92 request.context, |
92 request.resourceProvider, | 93 request.resourceProvider, |
93 request.searchEngine, | 94 request.searchEngine, |
94 request.source, | 95 request.source, |
95 request.offset); | 96 request.offset); |
96 } | 97 } |
97 | 98 |
98 DartCompletionRequestImpl._( | 99 DartCompletionRequestImpl._( |
99 AnalysisContext context, | 100 AnalysisContext context, |
100 ResourceProvider resourceProvider, | 101 ResourceProvider resourceProvider, |
101 SearchEngine searchEngine, | 102 SearchEngine searchEngine, |
102 Source source, | 103 Source source, |
103 int offset) | 104 int offset) |
104 : super(context, resourceProvider, searchEngine, source, offset) { | 105 : super(context, resourceProvider, searchEngine, source, offset) { |
| 106 _updateTargets(context.computeResult(source, PARSED_UNIT)); |
105 if (target.unit.directives.any((d) => d is PartOfDirective)) { | 107 if (target.unit.directives.any((d) => d is PartOfDirective)) { |
106 List<Source> libraries = context.getLibrariesContaining(source); | 108 List<Source> libraries = context.getLibrariesContaining(source); |
107 if (libraries.isNotEmpty) { | 109 if (libraries.isNotEmpty) { |
108 _librarySource = libraries[0]; | 110 _librarySource = libraries[0]; |
109 } | 111 } |
110 } else { | 112 } else { |
111 _librarySource = source; | 113 _librarySource = source; |
112 } | 114 } |
113 } | 115 } |
114 | 116 |
(...skipping 14 matching lines...) Expand all Loading... |
129 InterfaceType get objectType { | 131 InterfaceType get objectType { |
130 if (_objectType == null) { | 132 if (_objectType == null) { |
131 Source coreUri = context.sourceFactory.forUri('dart:core'); | 133 Source coreUri = context.sourceFactory.forUri('dart:core'); |
132 LibraryElement coreLib = context.getLibraryElement(coreUri); | 134 LibraryElement coreLib = context.getLibraryElement(coreUri); |
133 _objectType = coreLib.getType('Object').type; | 135 _objectType = coreLib.getType('Object').type; |
134 } | 136 } |
135 return _objectType; | 137 return _objectType; |
136 } | 138 } |
137 | 139 |
138 @override | 140 @override |
139 CompletionTarget get target { | |
140 if (_target == null) { | |
141 CompilationUnit unit = context.computeResult(source, PARSED_UNIT); | |
142 _target = new CompletionTarget.forOffset(unit, offset); | |
143 } | |
144 return _target; | |
145 } | |
146 | |
147 @override | |
148 Future<CompilationUnit> resolveDeclarationsInScope() async { | 141 Future<CompilationUnit> resolveDeclarationsInScope() async { |
149 CompilationUnit unit = target.unit; | 142 CompilationUnit unit = target.unit; |
150 if (_haveResolveDeclarationsInScope) { | 143 if (_haveResolveDeclarationsInScope) { |
151 return unit; | 144 return unit; |
152 } | 145 } |
153 | 146 |
154 // Gracefully degrade if librarySource cannot be determined | 147 // Gracefully degrade if librarySource cannot be determined |
155 if (_librarySource == null) { | 148 if (_librarySource == null) { |
156 return null; | 149 return null; |
157 } | 150 } |
158 | 151 |
159 // Resolve declarations in the target unit | 152 // Resolve declarations in the target unit |
160 CompilationUnit resolvedUnit = | 153 CompilationUnit resolvedUnit = |
161 await new AnalysisFutureHelper<CompilationUnit>(context, | 154 await new AnalysisFutureHelper<CompilationUnit>(context, |
162 new LibrarySpecificUnit(_librarySource, source), RESOLVED_UNIT3) | 155 new LibrarySpecificUnit(_librarySource, source), RESOLVED_UNIT3) |
163 .computeAsync(); | 156 .computeAsync(); |
164 | 157 |
165 // TODO(danrubel) determine if the underlying source has been modified | 158 // TODO(danrubel) determine if the underlying source has been modified |
166 // in a way that invalidates the completion request | 159 // in a way that invalidates the completion request |
167 // and return null | 160 // and return null |
168 | 161 |
169 // Gracefully degrade if unit cannot be resolved | 162 // Gracefully degrade if unit cannot be resolved |
170 if (resolvedUnit == null) { | 163 if (resolvedUnit == null) { |
171 return null; | 164 return null; |
172 } | 165 } |
173 | 166 |
174 // Recompute the target for the newly resolved unit | 167 // Recompute the target for the newly resolved unit |
175 _target = new CompletionTarget.forOffset(resolvedUnit, offset); | 168 _updateTargets(resolvedUnit); |
176 _haveResolveDeclarationsInScope = true; | 169 _haveResolveDeclarationsInScope = true; |
177 return resolvedUnit; | 170 return resolvedUnit; |
178 } | 171 } |
179 | 172 |
180 @override | 173 @override |
181 Future<List<Directive>> resolveDirectives() async { | 174 Future<List<Directive>> resolveDirectives() async { |
182 CompilationUnit libUnit; | 175 CompilationUnit libUnit; |
183 if (_librarySource == source) { | 176 if (_librarySource == source) { |
184 libUnit = await resolveDeclarationsInScope(); | 177 libUnit = await resolveDeclarationsInScope(); |
185 } else if (_librarySource != null) { | 178 } else if (_librarySource != null) { |
186 libUnit = | 179 libUnit = await new AnalysisFutureHelper<CompilationUnit>( |
187 await new AnalysisFutureHelper<CompilationUnit>( | 180 context, |
188 context, | 181 new LibrarySpecificUnit(_librarySource, _librarySource), |
189 new LibrarySpecificUnit(_librarySource, _librarySource), | 182 RESOLVED_UNIT3) |
190 RESOLVED_UNIT3) | 183 .computeAsync(); |
191 .computeAsync(); | |
192 } | 184 } |
193 return libUnit?.directives; | 185 return libUnit?.directives; |
194 } | 186 } |
195 | 187 |
196 @override | 188 @override |
197 Future resolveExpression(Expression expression) async { | 189 Future resolveExpression(Expression expression) async { |
198 //TODO(danrubel) resolve the expression or containing method | 190 //TODO(danrubel) resolve the expression or containing method |
199 // rather than the entire complilation unit | 191 // rather than the entire complilation unit |
200 | 192 |
201 // Gracefully degrade if librarySource cannot be determined | 193 // Gracefully degrade if librarySource cannot be determined |
(...skipping 10 matching lines...) Expand all Loading... |
212 // TODO(danrubel) determine if the underlying source has been modified | 204 // TODO(danrubel) determine if the underlying source has been modified |
213 // in a way that invalidates the completion request | 205 // in a way that invalidates the completion request |
214 // and return null | 206 // and return null |
215 | 207 |
216 // Gracefully degrade if unit cannot be resolved | 208 // Gracefully degrade if unit cannot be resolved |
217 if (resolvedUnit == null) { | 209 if (resolvedUnit == null) { |
218 return null; | 210 return null; |
219 } | 211 } |
220 | 212 |
221 // Recompute the target for the newly resolved unit | 213 // Recompute the target for the newly resolved unit |
222 _target = new CompletionTarget.forOffset(resolvedUnit, offset); | 214 _updateTargets(resolvedUnit); |
223 _haveResolveDeclarationsInScope = true; | 215 _haveResolveDeclarationsInScope = true; |
224 } | 216 } |
| 217 |
| 218 /** |
| 219 * Update the completion [target] and [dotTarget] based on the given [unit]. |
| 220 */ |
| 221 void _updateTargets(CompilationUnit unit) { |
| 222 dotTarget = null; |
| 223 target = new CompletionTarget.forOffset(unit, offset); |
| 224 AstNode node = target.containingNode; |
| 225 if (node is MethodInvocation) { |
| 226 if (identical(node.methodName, target.entity)) { |
| 227 dotTarget = node.realTarget; |
| 228 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { |
| 229 dotTarget = node.realTarget; |
| 230 } |
| 231 } |
| 232 if (node is PropertyAccess) { |
| 233 if (identical(node.propertyName, target.entity)) { |
| 234 dotTarget = node.realTarget; |
| 235 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { |
| 236 dotTarget = node.realTarget; |
| 237 } |
| 238 } |
| 239 if (node is PrefixedIdentifier) { |
| 240 if (identical(node.identifier, target.entity)) { |
| 241 dotTarget = node.prefix; |
| 242 } |
| 243 } |
| 244 } |
225 } | 245 } |
OLD | NEW |