OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.src.refactoring.inline_method; | 5 library services.src.refactoring.inline_method; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 9 import 'package:analysis_server/src/protocol_server.dart' hide Element; |
10 import 'package:analysis_server/src/services/correction/source_range.dart'; | 10 import 'package:analysis_server/src/services/correction/source_range.dart'; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 result.add(classMemberElement.displayName); | 184 result.add(classMemberElement.displayName); |
185 } | 185 } |
186 } | 186 } |
187 } | 187 } |
188 } | 188 } |
189 // done | 189 // done |
190 return result; | 190 return result; |
191 } | 191 } |
192 | 192 |
193 /** | 193 /** |
| 194 * Completes with the resolved [CompilationUnit] that contains the [element]. |
| 195 */ |
| 196 typedef Future<CompilationUnit> GetResolvedUnitContainingElement( |
| 197 Element element); |
| 198 |
| 199 /** |
194 * [InlineMethodRefactoring] implementation. | 200 * [InlineMethodRefactoring] implementation. |
195 */ | 201 */ |
196 class InlineMethodRefactoringImpl extends RefactoringImpl | 202 class InlineMethodRefactoringImpl extends RefactoringImpl |
197 implements InlineMethodRefactoring { | 203 implements InlineMethodRefactoring { |
198 final SearchEngine searchEngine; | 204 final SearchEngine searchEngine; |
| 205 final GetResolvedUnitContainingElement getResolvedUnit; |
199 final CompilationUnit unit; | 206 final CompilationUnit unit; |
200 final int offset; | 207 final int offset; |
201 CorrectionUtils utils; | 208 CorrectionUtils utils; |
202 SourceChange change; | 209 SourceChange change; |
203 | 210 |
204 bool isDeclaration = false; | 211 bool isDeclaration = false; |
205 bool deleteSource = false; | 212 bool deleteSource = false; |
206 bool inlineAll = true; | 213 bool inlineAll = true; |
207 | 214 |
208 ExecutableElement _methodElement; | 215 ExecutableElement _methodElement; |
209 bool _isAccessor; | 216 bool _isAccessor; |
210 CompilationUnit _methodUnit; | 217 CompilationUnit _methodUnit; |
211 CorrectionUtils _methodUtils; | 218 CorrectionUtils _methodUtils; |
212 AstNode _methodNode; | 219 AstNode _methodNode; |
213 FormalParameterList _methodParameters; | 220 FormalParameterList _methodParameters; |
214 FunctionBody _methodBody; | 221 FunctionBody _methodBody; |
215 Expression _methodExpression; | 222 Expression _methodExpression; |
216 _SourcePart _methodExpressionPart; | 223 _SourcePart _methodExpressionPart; |
217 _SourcePart _methodStatementsPart; | 224 _SourcePart _methodStatementsPart; |
218 List<_ReferenceProcessor> _referenceProcessors = []; | 225 List<_ReferenceProcessor> _referenceProcessors = []; |
219 Set<FunctionBody> _alreadyMadeAsync = new Set<FunctionBody>(); | 226 Set<FunctionBody> _alreadyMadeAsync = new Set<FunctionBody>(); |
220 | 227 |
221 InlineMethodRefactoringImpl(this.searchEngine, this.unit, this.offset) { | 228 InlineMethodRefactoringImpl( |
| 229 this.searchEngine, this.getResolvedUnit, this.unit, this.offset) { |
222 utils = new CorrectionUtils(unit); | 230 utils = new CorrectionUtils(unit); |
223 } | 231 } |
224 | 232 |
225 @override | 233 @override |
226 String get className { | 234 String get className { |
227 if (_methodElement == null) { | 235 if (_methodElement == null) { |
228 return null; | 236 return null; |
229 } | 237 } |
230 Element classElement = _methodElement.enclosingElement; | 238 Element classElement = _methodElement.enclosingElement; |
231 if (classElement is ClassElement) { | 239 if (classElement is ClassElement) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 change, _methodElement, newSourceEdit_range(linesRange, '')); | 280 change, _methodElement, newSourceEdit_range(linesRange, '')); |
273 } | 281 } |
274 // done | 282 // done |
275 return new Future.value(result); | 283 return new Future.value(result); |
276 } | 284 } |
277 | 285 |
278 @override | 286 @override |
279 Future<RefactoringStatus> checkInitialConditions() async { | 287 Future<RefactoringStatus> checkInitialConditions() async { |
280 RefactoringStatus result = new RefactoringStatus(); | 288 RefactoringStatus result = new RefactoringStatus(); |
281 // prepare method information | 289 // prepare method information |
282 result.addStatus(_prepareMethod()); | 290 result.addStatus(await _prepareMethod()); |
283 if (result.hasFatalError) { | 291 if (result.hasFatalError) { |
284 return new Future<RefactoringStatus>.value(result); | 292 return new Future<RefactoringStatus>.value(result); |
285 } | 293 } |
286 // maybe operator | 294 // maybe operator |
287 if (_methodElement.isOperator) { | 295 if (_methodElement.isOperator) { |
288 result = new RefactoringStatus.fatal('Cannot inline operator.'); | 296 result = new RefactoringStatus.fatal('Cannot inline operator.'); |
289 return new Future<RefactoringStatus>.value(result); | 297 return new Future<RefactoringStatus>.value(result); |
290 } | 298 } |
291 // maybe [a]sync* | 299 // maybe [a]sync* |
292 if (_methodElement.isGenerator) { | 300 if (_methodElement.isGenerator) { |
293 result = new RefactoringStatus.fatal('Cannot inline a generator.'); | 301 result = new RefactoringStatus.fatal('Cannot inline a generator.'); |
294 return new Future<RefactoringStatus>.value(result); | 302 return new Future<RefactoringStatus>.value(result); |
295 } | 303 } |
296 // analyze method body | 304 // analyze method body |
297 result.addStatus(_prepareMethodParts()); | 305 result.addStatus(_prepareMethodParts()); |
298 // process references | 306 // process references |
299 List<SearchMatch> references = | 307 List<SearchMatch> references = |
300 await searchEngine.searchReferences(_methodElement); | 308 await searchEngine.searchReferences(_methodElement); |
301 _referenceProcessors.clear(); | 309 _referenceProcessors.clear(); |
302 for (SearchMatch reference in references) { | 310 for (SearchMatch reference in references) { |
303 _ReferenceProcessor processor = new _ReferenceProcessor(this, reference); | 311 _ReferenceProcessor processor = new _ReferenceProcessor(this, reference); |
| 312 await processor.init(); |
304 _referenceProcessors.add(processor); | 313 _referenceProcessors.add(processor); |
305 } | 314 } |
306 return result; | 315 return result; |
307 } | 316 } |
308 | 317 |
309 @override | 318 @override |
310 Future<SourceChange> createChange() { | 319 Future<SourceChange> createChange() { |
311 return new Future.value(change); | 320 return new Future.value(change); |
312 } | 321 } |
313 | 322 |
314 @override | 323 @override |
315 bool requiresPreview() => false; | 324 bool requiresPreview() => false; |
316 | 325 |
317 _SourcePart _createSourcePart(SourceRange range) { | 326 _SourcePart _createSourcePart(SourceRange range) { |
318 String source = _methodUtils.getRangeText(range); | 327 String source = _methodUtils.getRangeText(range); |
319 String prefix = getLinePrefix(source); | 328 String prefix = getLinePrefix(source); |
320 _SourcePart result = new _SourcePart(range.offset, source, prefix); | 329 _SourcePart result = new _SourcePart(range.offset, source, prefix); |
321 // remember parameters and variables occurrences | 330 // remember parameters and variables occurrences |
322 _methodUnit.accept(new _VariablesVisitor(_methodElement, range, result)); | 331 _methodUnit.accept(new _VariablesVisitor(_methodElement, range, result)); |
323 // done | 332 // done |
324 return result; | 333 return result; |
325 } | 334 } |
326 | 335 |
327 /** | 336 /** |
328 * Initializes [_methodElement] and related fields. | 337 * Initializes [_methodElement] and related fields. |
329 */ | 338 */ |
330 RefactoringStatus _prepareMethod() { | 339 Future<RefactoringStatus> _prepareMethod() async { |
331 _methodElement = null; | 340 _methodElement = null; |
332 _methodParameters = null; | 341 _methodParameters = null; |
333 _methodBody = null; | 342 _methodBody = null; |
334 deleteSource = false; | 343 deleteSource = false; |
335 inlineAll = false; | 344 inlineAll = false; |
336 // prepare for failure | 345 // prepare for failure |
337 RefactoringStatus fatalStatus = new RefactoringStatus.fatal( | 346 RefactoringStatus fatalStatus = new RefactoringStatus.fatal( |
338 'Method declaration or reference must be selected to activate this refac
toring.'); | 347 'Method declaration or reference must be selected to activate this refac
toring.'); |
339 // prepare selected SimpleIdentifier | 348 // prepare selected SimpleIdentifier |
340 AstNode node = new NodeLocator(offset).searchWithin(unit); | 349 AstNode node = new NodeLocator(offset).searchWithin(unit); |
341 if (node is! SimpleIdentifier) { | 350 if (node is! SimpleIdentifier) { |
342 return fatalStatus; | 351 return fatalStatus; |
343 } | 352 } |
344 SimpleIdentifier identifier = node as SimpleIdentifier; | 353 SimpleIdentifier identifier = node as SimpleIdentifier; |
345 // prepare selected ExecutableElement | 354 // prepare selected ExecutableElement |
346 Element element = identifier.bestElement; | 355 Element element = identifier.bestElement; |
347 if (element is! ExecutableElement) { | 356 if (element is! ExecutableElement) { |
348 return fatalStatus; | 357 return fatalStatus; |
349 } | 358 } |
350 if (element.isSynthetic) { | 359 if (element.isSynthetic) { |
351 return fatalStatus; | 360 return fatalStatus; |
352 } | 361 } |
353 _methodElement = element as ExecutableElement; | 362 _methodElement = element as ExecutableElement; |
354 _isAccessor = element is PropertyAccessorElement; | 363 _isAccessor = element is PropertyAccessorElement; |
355 _methodUnit = element.unit; | 364 _methodUnit = await getResolvedUnit(element); |
356 _methodUtils = new CorrectionUtils(_methodUnit); | 365 _methodUtils = new CorrectionUtils(_methodUnit); |
357 // class member | 366 // class member |
358 bool isClassMember = element.enclosingElement is ClassElement; | 367 bool isClassMember = element.enclosingElement is ClassElement; |
359 if (element is MethodElement || _isAccessor && isClassMember) { | 368 if (element is MethodElement || _isAccessor && isClassMember) { |
360 MethodDeclaration methodDeclaration = element.computeNode(); | 369 MethodDeclaration methodDeclaration = element.computeNode(); |
361 _methodNode = methodDeclaration; | 370 _methodNode = methodDeclaration; |
362 _methodParameters = methodDeclaration.parameters; | 371 _methodParameters = methodDeclaration.parameters; |
363 _methodBody = methodDeclaration.body; | 372 _methodBody = methodDeclaration.body; |
364 // prepare mode | 373 // prepare mode |
365 isDeclaration = node == methodDeclaration.name; | 374 isDeclaration = node == methodDeclaration.name; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 final int parentPrecedence; | 437 final int parentPrecedence; |
429 final SourceRange range; | 438 final SourceRange range; |
430 _ParameterOccurrence(this.parentPrecedence, this.range); | 439 _ParameterOccurrence(this.parentPrecedence, this.range); |
431 } | 440 } |
432 | 441 |
433 /** | 442 /** |
434 * Processor for single [SearchMatch] reference to [methodElement]. | 443 * Processor for single [SearchMatch] reference to [methodElement]. |
435 */ | 444 */ |
436 class _ReferenceProcessor { | 445 class _ReferenceProcessor { |
437 final InlineMethodRefactoringImpl ref; | 446 final InlineMethodRefactoringImpl ref; |
| 447 final SearchMatch reference; |
438 | 448 |
439 Element refElement; | 449 Element refElement; |
440 CorrectionUtils _refUtils; | 450 CorrectionUtils _refUtils; |
441 SimpleIdentifier _node; | 451 SimpleIdentifier _node; |
442 SourceRange _refLineRange; | 452 SourceRange _refLineRange; |
443 String _refPrefix; | 453 String _refPrefix; |
444 | 454 |
445 _ReferenceProcessor(this.ref, SearchMatch reference) { | 455 _ReferenceProcessor(this.ref, this.reference); |
| 456 |
| 457 Future<Null> init() async { |
446 refElement = reference.element; | 458 refElement = reference.element; |
447 // prepare CorrectionUtils | 459 // prepare CorrectionUtils |
448 CompilationUnit refUnit = refElement.unit; | 460 CompilationUnit refUnit = await ref.getResolvedUnit(refElement); |
449 _refUtils = new CorrectionUtils(refUnit); | 461 _refUtils = new CorrectionUtils(refUnit); |
450 // prepare node and environment | 462 // prepare node and environment |
451 _node = _refUtils.findNode(reference.sourceRange.offset); | 463 _node = _refUtils.findNode(reference.sourceRange.offset); |
452 Statement refStatement = _node.getAncestor((node) => node is Statement); | 464 Statement refStatement = _node.getAncestor((node) => node is Statement); |
453 if (refStatement != null) { | 465 if (refStatement != null) { |
454 _refLineRange = _refUtils.getLinesRangeStatements([refStatement]); | 466 _refLineRange = _refUtils.getLinesRangeStatements([refStatement]); |
455 _refPrefix = _refUtils.getNodePrefix(refStatement); | 467 _refPrefix = _refUtils.getNodePrefix(refStatement); |
456 } else { | 468 } else { |
457 _refLineRange = null; | 469 _refLineRange = null; |
458 _refPrefix = _refUtils.getLinePrefix(_node.offset); | 470 _refPrefix = _refUtils.getLinePrefix(_node.offset); |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 } | 870 } |
859 | 871 |
860 void _addVariable(SimpleIdentifier node) { | 872 void _addVariable(SimpleIdentifier node) { |
861 VariableElement variableElement = getLocalVariableElement(node); | 873 VariableElement variableElement = getLocalVariableElement(node); |
862 if (variableElement != null) { | 874 if (variableElement != null) { |
863 SourceRange nodeRange = rangeNode(node); | 875 SourceRange nodeRange = rangeNode(node); |
864 result.addVariable(variableElement, nodeRange); | 876 result.addVariable(variableElement, nodeRange); |
865 } | 877 } |
866 } | 878 } |
867 } | 879 } |
OLD | NEW |