| 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 |