Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: pkg/analysis_server/lib/src/services/refactoring/extract_method.dart

Issue 1026503002: Simplify rules for extracting getters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/refactoring/extract_method_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 return new Future.value(result); 172 return new Future.value(result);
173 } 173 }
174 // prepare parts 174 // prepare parts
175 result.addStatus(_initializeParameters()); 175 result.addStatus(_initializeParameters());
176 _initializeReturnType(); 176 _initializeReturnType();
177 // occurrences 177 // occurrences
178 _initializeOccurrences(); 178 _initializeOccurrences();
179 _prepareOffsetsLengths(); 179 _prepareOffsetsLengths();
180 // getter 180 // getter
181 canCreateGetter = _computeCanCreateGetter(); 181 canCreateGetter = _computeCanCreateGetter();
182 _initializeCreateGetter(); 182 createGetter =
183 canCreateGetter && _isExpressionForGetter(_selectionExpression);
183 // names 184 // names
184 _prepareExcludedNames(); 185 _prepareExcludedNames();
185 _prepareNames(); 186 _prepareNames();
186 // closure cannot have parameters 187 // closure cannot have parameters
187 if (_selectionFunctionExpression != null && !_parameters.isEmpty) { 188 if (_selectionFunctionExpression != null && !_parameters.isEmpty) {
188 String message = format( 189 String message = format(
189 'Cannot extract closure as method, it references {0} external variable (s).', 190 'Cannot extract closure as method, it references {0} external variable (s).',
190 _parameters.length); 191 _parameters.length);
191 RefactoringStatus result = new RefactoringStatus.fatal(message); 192 RefactoringStatus result = new RefactoringStatus.fatal(message);
192 return new Future.value(result); 193 return new Future.value(result);
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 String source = SourceEdit.applySequence(originalSource, replaceEdits); 517 String source = SourceEdit.applySequence(originalSource, replaceEdits);
517 pattern.normalizedSource = _getNormalizedSource(source); 518 pattern.normalizedSource = _getNormalizedSource(source);
518 return pattern; 519 return pattern;
519 } 520 }
520 521
521 String _getTypeCode(DartType type) { 522 String _getTypeCode(DartType type) {
522 return utils.getTypeSource(type, librariesToImport); 523 return utils.getTypeSource(type, librariesToImport);
523 } 524 }
524 525
525 /** 526 /**
526 * Initializes [createGetter] flag.
527 */
528 void _initializeCreateGetter() {
529 createGetter = false;
530 // maybe we cannot at all
531 if (!canCreateGetter) {
532 return;
533 }
534 // OK, just expression
535 if (_selectionExpression != null) {
536 createGetter = !_hasMethodInvocation(_selectionExpression);
537 return;
538 }
539 // allow code blocks without cycles
540 if (_selectionStatements != null) {
541 createGetter = true;
542 for (Statement statement in _selectionStatements) {
543 // method invocation is something heavy,
544 // so we don't want to extract it as a part of a getter
545 if (_hasMethodInvocation(statement)) {
546 createGetter = false;
547 return;
548 }
549 // don't allow cycles
550 statement.accept(new _ResetCanCreateGetterVisitor(this));
551 }
552 }
553 }
554
555 /**
556 * Fills [_occurrences] field. 527 * Fills [_occurrences] field.
557 */ 528 */
558 void _initializeOccurrences() { 529 void _initializeOccurrences() {
559 _occurrences.clear(); 530 _occurrences.clear();
560 // prepare selection 531 // prepare selection
561 _SourcePattern selectionPattern = _getSourcePattern(selectionRange); 532 _SourcePattern selectionPattern = _getSourcePattern(selectionRange);
562 Map<String, String> patternToSelectionName = 533 Map<String, String> patternToSelectionName =
563 _inverseMap(selectionPattern.originalToPatternNames); 534 _inverseMap(selectionPattern.originalToPatternNames);
564 // prepare an enclosing parent - class or unit 535 // prepare an enclosing parent - class or unit
565 AstNode enclosingMemberParent = _parentMember.parent; 536 AstNode enclosingMemberParent = _parentMember.parent;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 void _prepareOffsetsLengths() { 670 void _prepareOffsetsLengths() {
700 offsets.clear(); 671 offsets.clear();
701 lengths.clear(); 672 lengths.clear();
702 for (_Occurrence occurrence in _occurrences) { 673 for (_Occurrence occurrence in _occurrences) {
703 offsets.add(occurrence.range.offset); 674 offsets.add(occurrence.range.offset);
704 lengths.add(occurrence.range.length); 675 lengths.add(occurrence.range.length);
705 } 676 }
706 } 677 }
707 678
708 /** 679 /**
709 * Checks if [node] has a [MethodInvocation]. 680 * Checks if the given [expression] is reasonable to extract as a getter.
710 */ 681 */
711 static bool _hasMethodInvocation(AstNode node) { 682 static bool _isExpressionForGetter(Expression expression) {
712 var visitor = new _HasMethodInvocationVisitor(); 683 if (expression is BinaryExpression) {
713 node.accept(visitor); 684 return _isExpressionForGetter(expression.leftOperand) &&
714 return visitor.result; 685 _isExpressionForGetter(expression.rightOperand);
686 }
687 if (expression is Literal) {
688 return true;
689 }
690 if (expression is PrefixExpression) {
691 return _isExpressionForGetter(expression.operand);
692 }
693 if (expression is PrefixedIdentifier) {
694 return _isExpressionForGetter(expression.prefix);
695 }
696 if (expression is PropertyAccess) {
697 return _isExpressionForGetter(expression.target);
698 }
699 if (expression is SimpleIdentifier) {
700 return true;
701 }
702 return false;
715 } 703 }
716 704
717 /** 705 /**
718 * Returns `true` if the given [statement] may end with a [ReturnStatement]. 706 * Returns `true` if the given [statement] may end with a [ReturnStatement].
719 */ 707 */
720 static bool _mayEndWithReturnStatement(Statement statement) { 708 static bool _mayEndWithReturnStatement(Statement statement) {
721 _HasReturnStatementVisitor visitor = new _HasReturnStatementVisitor(); 709 _HasReturnStatementVisitor visitor = new _HasReturnStatementVisitor();
722 statement.accept(visitor); 710 statement.accept(visitor);
723 return visitor.hasReturn; 711 return visitor.hasReturn;
724 } 712 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 patternName = '__refVar${pattern.originalToPatternNames.length}'; 848 patternName = '__refVar${pattern.originalToPatternNames.length}';
861 pattern.originalToPatternNames[originalName] = patternName; 849 pattern.originalToPatternNames[originalName] = patternName;
862 } 850 }
863 replaceEdits.add(new SourceEdit(nodeRange.offset - partRange.offset, 851 replaceEdits.add(new SourceEdit(nodeRange.offset - partRange.offset,
864 nodeRange.length, patternName)); 852 nodeRange.length, patternName));
865 } 853 }
866 } 854 }
867 } 855 }
868 } 856 }
869 857
870 class _HasMethodInvocationVisitor extends RecursiveAstVisitor {
871 bool result = false;
872
873 @override
874 visitMethodInvocation(MethodInvocation node) {
875 result = true;
876 }
877 }
878
879 class _HasReturnStatementVisitor extends RecursiveAstVisitor { 858 class _HasReturnStatementVisitor extends RecursiveAstVisitor {
880 bool hasReturn = false; 859 bool hasReturn = false;
881 860
882 @override 861 @override
883 visitBlockFunctionBody(BlockFunctionBody node) {} 862 visitBlockFunctionBody(BlockFunctionBody node) {}
884 863
885 @override 864 @override
886 visitReturnStatement(ReturnStatement node) { 865 visitReturnStatement(ReturnStatement node) {
887 hasReturn = true; 866 hasReturn = true;
888 } 867 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 return false; 933 return false;
955 } 934 }
956 // prepare node source 935 // prepare node source
957 _SourcePattern nodePattern = ref._getSourcePattern(nodeRange); 936 _SourcePattern nodePattern = ref._getSourcePattern(nodeRange);
958 // if matches normalized node source, then add as occurrence 937 // if matches normalized node source, then add as occurrence
959 if (selectionPattern.isCompatible(nodePattern)) { 938 if (selectionPattern.isCompatible(nodePattern)) {
960 _Occurrence occurrence = 939 _Occurrence occurrence =
961 new _Occurrence(nodeRange, ref.selectionRange.intersects(nodeRange)); 940 new _Occurrence(nodeRange, ref.selectionRange.intersects(nodeRange));
962 ref._occurrences.add(occurrence); 941 ref._occurrences.add(occurrence);
963 // prepare mapping of parameter names to the occurrence variables 942 // prepare mapping of parameter names to the occurrence variables
964 nodePattern.originalToPatternNames.forEach( 943 nodePattern.originalToPatternNames
965 (String originalName, String patternName) { 944 .forEach((String originalName, String patternName) {
966 String selectionName = patternToSelectionName[patternName]; 945 String selectionName = patternToSelectionName[patternName];
967 occurrence._parameterOldToOccurrenceName[selectionName] = originalName; 946 occurrence._parameterOldToOccurrenceName[selectionName] = originalName;
968 }); 947 });
969 // update static 948 // update static
970 if (forceStatic) { 949 if (forceStatic) {
971 ref._staticContext = true; 950 ref._staticContext = true;
972 } 951 }
973 // we have match 952 // we have match
974 return true; 953 return true;
975 } 954 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 */ 1051 */
1073 class _Occurrence { 1052 class _Occurrence {
1074 final SourceRange range; 1053 final SourceRange range;
1075 final bool isSelection; 1054 final bool isSelection;
1076 1055
1077 Map<String, String> _parameterOldToOccurrenceName = <String, String>{}; 1056 Map<String, String> _parameterOldToOccurrenceName = <String, String>{};
1078 1057
1079 _Occurrence(this.range, this.isSelection); 1058 _Occurrence(this.range, this.isSelection);
1080 } 1059 }
1081 1060
1082 class _ResetCanCreateGetterVisitor extends RecursiveAstVisitor {
1083 final ExtractMethodRefactoringImpl ref;
1084
1085 _ResetCanCreateGetterVisitor(this.ref);
1086
1087 @override
1088 visitDoStatement(DoStatement node) {
1089 ref.createGetter = false;
1090 super.visitDoStatement(node);
1091 }
1092
1093 @override
1094 visitForEachStatement(ForEachStatement node) {
1095 ref.createGetter = false;
1096 super.visitForEachStatement(node);
1097 }
1098
1099 @override
1100 visitForStatement(ForStatement node) {
1101 ref.createGetter = false;
1102 super.visitForStatement(node);
1103 }
1104
1105 @override
1106 visitWhileStatement(WhileStatement node) {
1107 ref.createGetter = false;
1108 super.visitWhileStatement(node);
1109 }
1110 }
1111
1112 class _ReturnTypeComputer extends RecursiveAstVisitor { 1061 class _ReturnTypeComputer extends RecursiveAstVisitor {
1113 DartType returnType; 1062 DartType returnType;
1114 1063
1115 @override 1064 @override
1116 visitBlockFunctionBody(BlockFunctionBody node) {} 1065 visitBlockFunctionBody(BlockFunctionBody node) {}
1117 1066
1118 @override 1067 @override
1119 visitReturnStatement(ReturnStatement node) { 1068 visitReturnStatement(ReturnStatement node) {
1120 // prepare expression 1069 // prepare expression
1121 Expression expression = node.expression; 1070 Expression expression = node.expression;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 return false; 1107 return false;
1159 } 1108 }
1160 for (int i = 0; i < parameterTypes.length; i++) { 1109 for (int i = 0; i < parameterTypes.length; i++) {
1161 if (other.parameterTypes[i] != parameterTypes[i]) { 1110 if (other.parameterTypes[i] != parameterTypes[i]) {
1162 return false; 1111 return false;
1163 } 1112 }
1164 } 1113 }
1165 return true; 1114 return true;
1166 } 1115 }
1167 } 1116 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/refactoring/extract_method_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698