| 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.extract_method; | 5 library services.src.refactoring.extract_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/name_suggestion.dart'; | 10 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; |
| 11 import 'package:analysis_server/src/services/correction/selection_analyzer.dart'
; | 11 import 'package:analysis_server/src/services/correction/selection_analyzer.dart'
; |
| 12 import 'package:analysis_server/src/services/correction/source_range.dart'; | 12 import 'package:analysis_server/src/services/correction/source_range.dart'; |
| 13 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; | 13 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; |
| 14 import 'package:analysis_server/src/services/correction/status.dart'; | 14 import 'package:analysis_server/src/services/correction/status.dart'; |
| 15 import 'package:analysis_server/src/services/correction/util.dart'; | 15 import 'package:analysis_server/src/services/correction/util.dart'; |
| 16 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; | 16 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; |
| 17 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 17 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 18 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 18 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 19 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; | 19 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; |
| 20 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; | 20 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; |
| 21 import 'package:analysis_server/src/services/search/element_visitors.dart'; | 21 import 'package:analysis_server/src/services/search/element_visitors.dart'; |
| 22 import 'package:analysis_server/src/services/search/search_engine.dart'; | 22 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 23 import 'package:analyzer/src/generated/ast.dart'; | 23 import 'package:analyzer/src/generated/ast.dart'; |
| 24 import 'package:analyzer/src/generated/element.dart'; | 24 import 'package:analyzer/src/generated/element.dart'; |
| 25 import 'package:analyzer/src/generated/engine.dart'; |
| 25 import 'package:analyzer/src/generated/java_core.dart'; | 26 import 'package:analyzer/src/generated/java_core.dart'; |
| 26 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector; | 27 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector; |
| 27 import 'package:analyzer/src/generated/scanner.dart'; | 28 import 'package:analyzer/src/generated/scanner.dart'; |
| 28 import 'package:analyzer/src/generated/source.dart'; | 29 import 'package:analyzer/src/generated/source.dart'; |
| 29 | 30 |
| 30 const String _TOKEN_SEPARATOR = '\uFFFF'; | 31 const String _TOKEN_SEPARATOR = '\uFFFF'; |
| 31 | 32 |
| 32 /** | 33 /** |
| 33 * Returns the "normalized" version of the given source, which is reconstructed | 34 * Returns the "normalized" version of the given source, which is reconstructed |
| 34 * from tokens, so ignores all the comments and spaces. | 35 * from tokens, so ignores all the comments and spaces. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 55 class ExtractMethodRefactoringImpl extends RefactoringImpl | 56 class ExtractMethodRefactoringImpl extends RefactoringImpl |
| 56 implements ExtractMethodRefactoring { | 57 implements ExtractMethodRefactoring { |
| 57 static const ERROR_EXITS = | 58 static const ERROR_EXITS = |
| 58 'Selected statements contain a return statement, but not all possible ' | 59 'Selected statements contain a return statement, but not all possible ' |
| 59 'execuion flows exit. Semantics may not be preserved.'; | 60 'execuion flows exit. Semantics may not be preserved.'; |
| 60 | 61 |
| 61 final SearchEngine searchEngine; | 62 final SearchEngine searchEngine; |
| 62 final CompilationUnit unit; | 63 final CompilationUnit unit; |
| 63 final int selectionOffset; | 64 final int selectionOffset; |
| 64 final int selectionLength; | 65 final int selectionLength; |
| 66 AnalysisContext context; |
| 65 CompilationUnitElement unitElement; | 67 CompilationUnitElement unitElement; |
| 66 LibraryElement libraryElement; | 68 LibraryElement libraryElement; |
| 67 SourceRange selectionRange; | 69 SourceRange selectionRange; |
| 68 CorrectionUtils utils; | 70 CorrectionUtils utils; |
| 69 Set<LibraryElement> librariesToImport = new Set<LibraryElement>(); | 71 Set<LibraryElement> librariesToImport = new Set<LibraryElement>(); |
| 70 | 72 |
| 71 String returnType; | 73 String returnType; |
| 74 String variableType; |
| 72 String name; | 75 String name; |
| 73 bool extractAll = true; | 76 bool extractAll = true; |
| 74 bool canCreateGetter = false; | 77 bool canCreateGetter = false; |
| 75 bool createGetter = false; | 78 bool createGetter = false; |
| 76 final List<String> names = <String>[]; | 79 final List<String> names = <String>[]; |
| 77 final List<int> offsets = <int>[]; | 80 final List<int> offsets = <int>[]; |
| 78 final List<int> lengths = <int>[]; | 81 final List<int> lengths = <int>[]; |
| 79 | 82 |
| 80 /** | 83 /** |
| 81 * The map of local names to their visibility ranges. | 84 * The map of local names to their visibility ranges. |
| 82 */ | 85 */ |
| 83 Map<String, List<SourceRange>> _localNames = <String, List<SourceRange>>{}; | 86 Map<String, List<SourceRange>> _localNames = <String, List<SourceRange>>{}; |
| 84 | 87 |
| 85 /** | 88 /** |
| 86 * The set of names that are referenced without any qualifier. | 89 * The set of names that are referenced without any qualifier. |
| 87 */ | 90 */ |
| 88 Set<String> _unqualifiedNames = new Set<String>(); | 91 Set<String> _unqualifiedNames = new Set<String>(); |
| 89 | 92 |
| 90 Set<String> _excludedNames = new Set<String>(); | 93 Set<String> _excludedNames = new Set<String>(); |
| 91 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[]; | 94 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[]; |
| 92 Map<String, RefactoringMethodParameter> _parametersMap = | 95 Map<String, RefactoringMethodParameter> _parametersMap = |
| 93 <String, RefactoringMethodParameter>{}; | 96 <String, RefactoringMethodParameter>{}; |
| 94 Map<String, List<SourceRange>> _parameterReferencesMap = | 97 Map<String, List<SourceRange>> _parameterReferencesMap = |
| 95 <String, List<SourceRange>>{}; | 98 <String, List<SourceRange>>{}; |
| 99 bool _hasAwait = false; |
| 96 DartType _returnType; | 100 DartType _returnType; |
| 97 String _returnVariableName; | 101 String _returnVariableName; |
| 98 AstNode _parentMember; | 102 AstNode _parentMember; |
| 99 Expression _selectionExpression; | 103 Expression _selectionExpression; |
| 100 FunctionExpression _selectionFunctionExpression; | 104 FunctionExpression _selectionFunctionExpression; |
| 101 List<Statement> _selectionStatements; | 105 List<Statement> _selectionStatements; |
| 102 List<_Occurrence> _occurrences = []; | 106 List<_Occurrence> _occurrences = []; |
| 103 bool _staticContext = false; | 107 bool _staticContext = false; |
| 104 | 108 |
| 105 ExtractMethodRefactoringImpl(this.searchEngine, this.unit, | 109 ExtractMethodRefactoringImpl(this.searchEngine, this.unit, |
| 106 this.selectionOffset, this.selectionLength) { | 110 this.selectionOffset, this.selectionLength) { |
| 107 unitElement = unit.element; | 111 unitElement = unit.element; |
| 108 libraryElement = unitElement.library; | 112 libraryElement = unitElement.library; |
| 113 context = libraryElement.context; |
| 109 selectionRange = new SourceRange(selectionOffset, selectionLength); | 114 selectionRange = new SourceRange(selectionOffset, selectionLength); |
| 110 utils = new CorrectionUtils(unit); | 115 utils = new CorrectionUtils(unit); |
| 111 } | 116 } |
| 112 | 117 |
| 113 @override | 118 @override |
| 114 List<RefactoringMethodParameter> get parameters => _parameters; | 119 List<RefactoringMethodParameter> get parameters => _parameters; |
| 115 | 120 |
| 116 @override | 121 @override |
| 117 void set parameters(List<RefactoringMethodParameter> parameters) { | 122 void set parameters(List<RefactoringMethodParameter> parameters) { |
| 118 _parameters = parameters.toList(); | 123 _parameters = parameters.toList(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 @override | 180 @override |
| 176 Future<RefactoringStatus> checkInitialConditions() { | 181 Future<RefactoringStatus> checkInitialConditions() { |
| 177 RefactoringStatus result = new RefactoringStatus(); | 182 RefactoringStatus result = new RefactoringStatus(); |
| 178 // selection | 183 // selection |
| 179 result.addStatus(_checkSelection()); | 184 result.addStatus(_checkSelection()); |
| 180 if (result.hasFatalError) { | 185 if (result.hasFatalError) { |
| 181 return new Future.value(result); | 186 return new Future.value(result); |
| 182 } | 187 } |
| 183 // prepare parts | 188 // prepare parts |
| 184 result.addStatus(_initializeParameters()); | 189 result.addStatus(_initializeParameters()); |
| 190 _initializeHasAwait(); |
| 185 _initializeReturnType(); | 191 _initializeReturnType(); |
| 186 // occurrences | 192 // occurrences |
| 187 _initializeOccurrences(); | 193 _initializeOccurrences(); |
| 188 _prepareOffsetsLengths(); | 194 _prepareOffsetsLengths(); |
| 189 // getter | 195 // getter |
| 190 canCreateGetter = _computeCanCreateGetter(); | 196 canCreateGetter = _computeCanCreateGetter(); |
| 191 createGetter = | 197 createGetter = |
| 192 canCreateGetter && _isExpressionForGetter(_selectionExpression); | 198 canCreateGetter && _isExpressionForGetter(_selectionExpression); |
| 193 // names | 199 // names |
| 194 _prepareExcludedNames(); | 200 _prepareExcludedNames(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 219 if (!extractAll && !occurence.isSelection) { | 225 if (!extractAll && !occurence.isSelection) { |
| 220 continue; | 226 continue; |
| 221 } | 227 } |
| 222 // prepare invocation source | 228 // prepare invocation source |
| 223 String invocationSource; | 229 String invocationSource; |
| 224 if (_selectionFunctionExpression != null) { | 230 if (_selectionFunctionExpression != null) { |
| 225 invocationSource = name; | 231 invocationSource = name; |
| 226 } else { | 232 } else { |
| 227 StringBuffer sb = new StringBuffer(); | 233 StringBuffer sb = new StringBuffer(); |
| 228 // may be returns value | 234 // may be returns value |
| 229 if (_selectionStatements != null && returnType != 'void') { | 235 if (_selectionStatements != null && variableType != null) { |
| 230 // single variable assignment / return statement | 236 // single variable assignment / return statement |
| 231 if (_returnVariableName != null) { | 237 if (_returnVariableName != null) { |
| 232 String occurrenceName = | 238 String occurrenceName = |
| 233 occurence._parameterOldToOccurrenceName[_returnVariableName]; | 239 occurence._parameterOldToOccurrenceName[_returnVariableName]; |
| 234 // may be declare variable | 240 // may be declare variable |
| 235 if (!_parametersMap.containsKey(_returnVariableName)) { | 241 if (!_parametersMap.containsKey(_returnVariableName)) { |
| 236 if (returnType.isEmpty) { | 242 if (variableType.isEmpty) { |
| 237 sb.write('var '); | 243 sb.write('var '); |
| 238 } else { | 244 } else { |
| 239 sb.write(returnType); | 245 sb.write(variableType); |
| 240 sb.write(' '); | 246 sb.write(' '); |
| 241 } | 247 } |
| 242 } | 248 } |
| 243 // assign the return value | 249 // assign the return value |
| 244 sb.write(occurrenceName); | 250 sb.write(occurrenceName); |
| 245 sb.write(' = '); | 251 sb.write(' = '); |
| 246 } else { | 252 } else { |
| 247 sb.write('return '); | 253 sb.write('return '); |
| 248 } | 254 } |
| 249 } | 255 } |
| 256 // await |
| 257 if (_hasAwait) { |
| 258 sb.write('await '); |
| 259 } |
| 250 // invocation itself | 260 // invocation itself |
| 251 sb.write(name); | 261 sb.write(name); |
| 252 if (!createGetter) { | 262 if (!createGetter) { |
| 253 sb.write('('); | 263 sb.write('('); |
| 254 bool firstParameter = true; | 264 bool firstParameter = true; |
| 255 for (RefactoringMethodParameter parameter in _parameters) { | 265 for (RefactoringMethodParameter parameter in _parameters) { |
| 256 // may be comma | 266 // may be comma |
| 257 if (firstParameter) { | 267 if (firstParameter) { |
| 258 firstParameter = false; | 268 firstParameter = false; |
| 259 } else { | 269 } else { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 String declarationSource = null; | 305 String declarationSource = null; |
| 296 { | 306 { |
| 297 String returnExpressionSource = _getMethodBodySource(); | 307 String returnExpressionSource = _getMethodBodySource(); |
| 298 // closure | 308 // closure |
| 299 if (_selectionFunctionExpression != null) { | 309 if (_selectionFunctionExpression != null) { |
| 300 declarationSource = '${name}${returnExpressionSource}'; | 310 declarationSource = '${name}${returnExpressionSource}'; |
| 301 if (_selectionFunctionExpression.body is ExpressionFunctionBody) { | 311 if (_selectionFunctionExpression.body is ExpressionFunctionBody) { |
| 302 declarationSource += ';'; | 312 declarationSource += ';'; |
| 303 } | 313 } |
| 304 } | 314 } |
| 315 // optional 'async' body modifier |
| 316 String asyncKeyword = _hasAwait ? ' async' : ''; |
| 305 // expression | 317 // expression |
| 306 if (_selectionExpression != null) { | 318 if (_selectionExpression != null) { |
| 307 // add return type | 319 // add return type |
| 308 if (returnType.isNotEmpty) { | 320 if (returnType.isNotEmpty) { |
| 309 annotations += '$returnType '; | 321 annotations += '$returnType '; |
| 310 } | 322 } |
| 311 // just return expression | 323 // just return expression |
| 312 declarationSource = | 324 declarationSource = '$annotations$signature$asyncKeyword => '; |
| 313 '${annotations}${signature} => ${returnExpressionSource};'; | 325 declarationSource += '$returnExpressionSource;'; |
| 314 } | 326 } |
| 315 // statements | 327 // statements |
| 316 if (_selectionStatements != null) { | 328 if (_selectionStatements != null) { |
| 317 if (returnType.isNotEmpty) { | 329 if (returnType.isNotEmpty) { |
| 318 annotations += returnType + ' '; | 330 annotations += returnType + ' '; |
| 319 } | 331 } |
| 320 declarationSource = '${annotations}${signature} {${eol}'; | 332 declarationSource = '$annotations$signature$asyncKeyword {$eol'; |
| 321 declarationSource += returnExpressionSource; | 333 declarationSource += returnExpressionSource; |
| 322 if (_returnVariableName != null) { | 334 if (_returnVariableName != null) { |
| 323 declarationSource += | 335 declarationSource += |
| 324 '${prefix} return ${_returnVariableName};$eol'; | 336 '${prefix} return ${_returnVariableName};$eol'; |
| 325 } | 337 } |
| 326 declarationSource += '${prefix}}'; | 338 declarationSource += '${prefix}}'; |
| 327 } | 339 } |
| 328 } | 340 } |
| 329 // insert declaration | 341 // insert declaration |
| 330 if (declarationSource != null) { | 342 if (declarationSource != null) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 replaceEdits = replaceEdits.reversed.toList(); | 537 replaceEdits = replaceEdits.reversed.toList(); |
| 526 String source = SourceEdit.applySequence(originalSource, replaceEdits); | 538 String source = SourceEdit.applySequence(originalSource, replaceEdits); |
| 527 pattern.normalizedSource = _getNormalizedSource(source); | 539 pattern.normalizedSource = _getNormalizedSource(source); |
| 528 return pattern; | 540 return pattern; |
| 529 } | 541 } |
| 530 | 542 |
| 531 String _getTypeCode(DartType type) { | 543 String _getTypeCode(DartType type) { |
| 532 return utils.getTypeSource(type, librariesToImport); | 544 return utils.getTypeSource(type, librariesToImport); |
| 533 } | 545 } |
| 534 | 546 |
| 547 void _initializeHasAwait() { |
| 548 _HasAwaitVisitor visitor = new _HasAwaitVisitor(); |
| 549 if (_selectionExpression != null) { |
| 550 _selectionExpression.accept(visitor); |
| 551 } else if (_selectionStatements != null) { |
| 552 _selectionStatements.forEach((statement) => statement.accept(visitor)); |
| 553 } |
| 554 _hasAwait = visitor.result; |
| 555 } |
| 556 |
| 535 /** | 557 /** |
| 536 * Fills [_occurrences] field. | 558 * Fills [_occurrences] field. |
| 537 */ | 559 */ |
| 538 void _initializeOccurrences() { | 560 void _initializeOccurrences() { |
| 539 _occurrences.clear(); | 561 _occurrences.clear(); |
| 540 // prepare selection | 562 // prepare selection |
| 541 _SourcePattern selectionPattern = _getSourcePattern(selectionRange); | 563 _SourcePattern selectionPattern = _getSourcePattern(selectionRange); |
| 542 Map<String, String> patternToSelectionName = | 564 Map<String, String> patternToSelectionName = |
| 543 _inverseMap(selectionPattern.originalToPatternNames); | 565 _inverseMap(selectionPattern.originalToPatternNames); |
| 544 // prepare an enclosing parent - class or unit | 566 // prepare an enclosing parent - class or unit |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 result.addFatalError(format( | 624 result.addFatalError(format( |
| 603 'Ambiguous return value: Selected block contains more than one ' | 625 'Ambiguous return value: Selected block contains more than one ' |
| 604 'assignment to local variables. Affected variables are:\n\n{0}', | 626 'assignment to local variables. Affected variables are:\n\n{0}', |
| 605 sb.toString().trim())); | 627 sb.toString().trim())); |
| 606 } | 628 } |
| 607 // done | 629 // done |
| 608 return result; | 630 return result; |
| 609 } | 631 } |
| 610 | 632 |
| 611 void _initializeReturnType() { | 633 void _initializeReturnType() { |
| 634 InterfaceType futureType = context.typeProvider.futureType; |
| 612 if (_selectionFunctionExpression != null) { | 635 if (_selectionFunctionExpression != null) { |
| 636 variableType = ''; |
| 613 returnType = ''; | 637 returnType = ''; |
| 614 } else if (_returnType == null) { | 638 } else if (_returnType == null) { |
| 615 returnType = 'void'; | 639 variableType = null; |
| 640 if (_hasAwait) { |
| 641 returnType = _getTypeCode(futureType); |
| 642 } else { |
| 643 returnType = 'void'; |
| 644 } |
| 645 } else if (_returnType.isDynamic) { |
| 646 variableType = ''; |
| 647 if (_hasAwait) { |
| 648 returnType = _getTypeCode(futureType); |
| 649 } else { |
| 650 returnType = ''; |
| 651 } |
| 616 } else { | 652 } else { |
| 617 returnType = _getTypeCode(_returnType); | 653 variableType = _getTypeCode(_returnType); |
| 618 } | 654 if (_hasAwait) { |
| 619 if (returnType == 'dynamic') { | 655 if (_returnType.element != futureType.element) { |
| 620 returnType = ''; | 656 returnType = _getTypeCode(futureType.substitute4([_returnType])); |
| 657 } |
| 658 } else { |
| 659 returnType = variableType; |
| 660 } |
| 621 } | 661 } |
| 622 } | 662 } |
| 623 | 663 |
| 624 /** | 664 /** |
| 625 * Checks if the given [VariableElement] is declared in [selectionRange]. | 665 * Checks if the given [VariableElement] is declared in [selectionRange]. |
| 626 */ | 666 */ |
| 627 bool _isDeclaredInSelection(VariableElement element) { | 667 bool _isDeclaredInSelection(VariableElement element) { |
| 628 return selectionRange.contains(element.nameOffset); | 668 return selectionRange.contains(element.nameOffset); |
| 629 } | 669 } |
| 630 | 670 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 patternName = '__refVar${pattern.originalToPatternNames.length}'; | 917 patternName = '__refVar${pattern.originalToPatternNames.length}'; |
| 878 pattern.originalToPatternNames[originalName] = patternName; | 918 pattern.originalToPatternNames[originalName] = patternName; |
| 879 } | 919 } |
| 880 replaceEdits.add(new SourceEdit(nodeRange.offset - partRange.offset, | 920 replaceEdits.add(new SourceEdit(nodeRange.offset - partRange.offset, |
| 881 nodeRange.length, patternName)); | 921 nodeRange.length, patternName)); |
| 882 } | 922 } |
| 883 } | 923 } |
| 884 } | 924 } |
| 885 } | 925 } |
| 886 | 926 |
| 927 class _HasAwaitVisitor extends GeneralizingAstVisitor { |
| 928 bool result = false; |
| 929 |
| 930 @override |
| 931 visitAwaitExpression(AwaitExpression node) { |
| 932 result = true; |
| 933 } |
| 934 |
| 935 @override |
| 936 visitForEachStatement(ForEachStatement node) { |
| 937 if (node.awaitKeyword != null) { |
| 938 result = true; |
| 939 } |
| 940 super.visitForEachStatement(node); |
| 941 } |
| 942 } |
| 943 |
| 887 class _HasReturnStatementVisitor extends RecursiveAstVisitor { | 944 class _HasReturnStatementVisitor extends RecursiveAstVisitor { |
| 888 bool hasReturn = false; | 945 bool hasReturn = false; |
| 889 | 946 |
| 890 @override | 947 @override |
| 891 visitBlockFunctionBody(BlockFunctionBody node) {} | 948 visitBlockFunctionBody(BlockFunctionBody node) {} |
| 892 | 949 |
| 893 @override | 950 @override |
| 894 visitReturnStatement(ReturnStatement node) { | 951 visitReturnStatement(ReturnStatement node) { |
| 895 hasReturn = true; | 952 hasReturn = true; |
| 896 } | 953 } |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1144 return false; | 1201 return false; |
| 1145 } | 1202 } |
| 1146 for (int i = 0; i < parameterTypes.length; i++) { | 1203 for (int i = 0; i < parameterTypes.length; i++) { |
| 1147 if (other.parameterTypes[i] != parameterTypes[i]) { | 1204 if (other.parameterTypes[i] != parameterTypes[i]) { |
| 1148 return false; | 1205 return false; |
| 1149 } | 1206 } |
| 1150 } | 1207 } |
| 1151 return true; | 1208 return true; |
| 1152 } | 1209 } |
| 1153 } | 1210 } |
| OLD | NEW |