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

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

Issue 871013012: Issue 22188. Verify that none or all execution flows return. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes for review comments. Created 5 years, 10 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';
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/java_core.dart'; 25 import 'package:analyzer/src/generated/java_core.dart';
26 import 'package:analyzer/src/generated/scanner.dart'; 26 import 'package:analyzer/src/generated/scanner.dart';
27 import 'package:analyzer/src/generated/source.dart'; 27 import 'package:analyzer/src/generated/source.dart';
28 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector;
28 29
29 30
30 const String _TOKEN_SEPARATOR = '\uFFFF'; 31 const String _TOKEN_SEPARATOR = '\uFFFF';
31 32
32 33
33 /** 34 /**
34 * Returns the "normalized" version of the given source, which is reconstructed 35 * Returns the "normalized" version of the given source, which is reconstructed
35 * from tokens, so ignores all the comments and spaces. 36 * from tokens, so ignores all the comments and spaces.
36 */ 37 */
37 String _getNormalizedSource(String src) { 38 String _getNormalizedSource(String src) {
(...skipping 12 matching lines...) Expand all
50 }); 51 });
51 return result; 52 return result;
52 } 53 }
53 54
54 55
55 /** 56 /**
56 * [ExtractMethodRefactoring] implementation. 57 * [ExtractMethodRefactoring] implementation.
57 */ 58 */
58 class ExtractMethodRefactoringImpl extends RefactoringImpl implements 59 class ExtractMethodRefactoringImpl extends RefactoringImpl implements
59 ExtractMethodRefactoring { 60 ExtractMethodRefactoring {
61 static const ERROR_EXITS =
62 'Selected statements contain a return statement, but not all possible '
63 'execuion flows exit. Semantics may not be preserved.';
64
60 final SearchEngine searchEngine; 65 final SearchEngine searchEngine;
61 final CompilationUnit unit; 66 final CompilationUnit unit;
62 final int selectionOffset; 67 final int selectionOffset;
63 final int selectionLength; 68 final int selectionLength;
64 CompilationUnitElement unitElement; 69 CompilationUnitElement unitElement;
65 SourceRange selectionRange; 70 SourceRange selectionRange;
66 CorrectionUtils utils; 71 CorrectionUtils utils;
67 72
68 String returnType; 73 String returnType;
69 String name; 74 String name;
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 _parameters.clear(); 570 _parameters.clear();
566 _parametersMap.clear(); 571 _parametersMap.clear();
567 _parameterReferencesMap.clear(); 572 _parameterReferencesMap.clear();
568 RefactoringStatus result = new RefactoringStatus(); 573 RefactoringStatus result = new RefactoringStatus();
569 List<VariableElement> assignedUsedVariables = []; 574 List<VariableElement> assignedUsedVariables = [];
570 unit.accept(new _InitializeParametersVisitor(this, assignedUsedVariables)); 575 unit.accept(new _InitializeParametersVisitor(this, assignedUsedVariables));
571 // single expression 576 // single expression
572 if (_selectionExpression != null) { 577 if (_selectionExpression != null) {
573 _returnType = _selectionExpression.bestType; 578 _returnType = _selectionExpression.bestType;
574 } 579 }
575 // may be ends with "return" statement 580 // verify that none or all execution flows end with a "return"
581 if (_selectionStatements != null) {
582 bool hasReturn = _selectionStatements.any(_mayEndWithReturnStatement);
583 if (hasReturn && !ExitDetector.exits(_selectionStatements.last)) {
584 result.addError(ERROR_EXITS);
585 }
586 }
587 // maybe ends with "return" statement
576 if (_selectionStatements != null) { 588 if (_selectionStatements != null) {
577 _ReturnTypeComputer returnTypeComputer = new _ReturnTypeComputer(); 589 _ReturnTypeComputer returnTypeComputer = new _ReturnTypeComputer();
578 _selectionStatements.forEach((statement) { 590 _selectionStatements.forEach((statement) {
579 statement.accept(returnTypeComputer); 591 statement.accept(returnTypeComputer);
580 }); 592 });
581 _returnType = returnTypeComputer.returnType; 593 _returnType = returnTypeComputer.returnType;
582 } 594 }
583 // may be single variable to return 595 // maybe single variable to return
584 if (assignedUsedVariables.length == 1) { 596 if (assignedUsedVariables.length == 1) {
585 // we cannot both return variable and have explicit return statement 597 // we cannot both return variable and have explicit return statement
586 if (_returnType != null) { 598 if (_returnType != null) {
587 result.addFatalError( 599 result.addFatalError(
588 'Ambiguous return value: Selected block contains assignment(s) to ' 600 'Ambiguous return value: Selected block contains assignment(s) to '
589 'local variables and return statement.'); 601 'local variables and return statement.');
590 return result; 602 return result;
591 } 603 }
592 // prepare to return an assigned variable 604 // prepare to return an assigned variable
593 VariableElement returnVariable = assignedUsedVariables[0]; 605 VariableElement returnVariable = assignedUsedVariables[0];
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 } 703 }
692 704
693 /** 705 /**
694 * Checks if [node] has a [MethodInvocation]. 706 * Checks if [node] has a [MethodInvocation].
695 */ 707 */
696 static bool _hasMethodInvocation(AstNode node) { 708 static bool _hasMethodInvocation(AstNode node) {
697 var visitor = new _HasMethodInvocationVisitor(); 709 var visitor = new _HasMethodInvocationVisitor();
698 node.accept(visitor); 710 node.accept(visitor);
699 return visitor.result; 711 return visitor.result;
700 } 712 }
713
714 /**
715 * Returns `true` if the given [statement] may end with a [ReturnStatement].
716 */
717 static bool _mayEndWithReturnStatement(Statement statement) {
718 _HasReturnStatementVisitor visitor = new _HasReturnStatementVisitor();
719 statement.accept(visitor);
720 return visitor.hasReturn;
721 }
701 } 722 }
702 723
703 724
704 /** 725 /**
705 * [SelectionAnalyzer] for [ExtractMethodRefactoringImpl]. 726 * [SelectionAnalyzer] for [ExtractMethodRefactoringImpl].
706 */ 727 */
707 class _ExtractMethodAnalyzer extends StatementAnalyzer { 728 class _ExtractMethodAnalyzer extends StatementAnalyzer {
708 _ExtractMethodAnalyzer(CompilationUnit unit, SourceRange selection) 729 _ExtractMethodAnalyzer(CompilationUnit unit, SourceRange selection)
709 : super(unit, selection); 730 : super(unit, selection);
710 731
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 class _HasMethodInvocationVisitor extends RecursiveAstVisitor { 879 class _HasMethodInvocationVisitor extends RecursiveAstVisitor {
859 bool result = false; 880 bool result = false;
860 881
861 @override 882 @override
862 visitMethodInvocation(MethodInvocation node) { 883 visitMethodInvocation(MethodInvocation node) {
863 result = true; 884 result = true;
864 } 885 }
865 } 886 }
866 887
867 888
889 class _HasReturnStatementVisitor extends RecursiveAstVisitor {
890 bool hasReturn = false;
891
892 @override
893 visitBlockFunctionBody(BlockFunctionBody node) {
894 }
895
896 @override
897 visitReturnStatement(ReturnStatement node) {
898 hasReturn = true;
899 }
900 }
901
902
868 class _InitializeOccurrencesVisitor extends GeneralizingAstVisitor<Object> { 903 class _InitializeOccurrencesVisitor extends GeneralizingAstVisitor<Object> {
869 final ExtractMethodRefactoringImpl ref; 904 final ExtractMethodRefactoringImpl ref;
870 final _SourcePattern selectionPattern; 905 final _SourcePattern selectionPattern;
871 final Map<String, String> patternToSelectionName; 906 final Map<String, String> patternToSelectionName;
872 907
873 bool forceStatic = false; 908 bool forceStatic = false;
874 909
875 _InitializeOccurrencesVisitor(this.ref, this.selectionPattern, 910 _InitializeOccurrencesVisitor(this.ref, this.selectionPattern,
876 this.patternToSelectionName); 911 this.patternToSelectionName);
877 912
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 // next statement 1000 // next statement
966 if (found) { 1001 if (found) {
967 beginStatementIndex += selectionCount; 1002 beginStatementIndex += selectionCount;
968 } else { 1003 } else {
969 beginStatementIndex++; 1004 beginStatementIndex++;
970 } 1005 }
971 } 1006 }
972 } 1007 }
973 } 1008 }
974 1009
975
976 class _InitializeParametersVisitor extends GeneralizingAstVisitor<Object> { 1010 class _InitializeParametersVisitor extends GeneralizingAstVisitor<Object> {
977 final ExtractMethodRefactoringImpl ref; 1011 final ExtractMethodRefactoringImpl ref;
978 final List<VariableElement> assignedUsedVariables; 1012 final List<VariableElement> assignedUsedVariables;
979 1013
980 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables); 1014 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables);
981 1015
982 @override 1016 @override
983 Object visitSimpleIdentifier(SimpleIdentifier node) { 1017 Object visitSimpleIdentifier(SimpleIdentifier node) {
984 SourceRange nodeRange = rangeNode(node); 1018 SourceRange nodeRange = rangeNode(node);
985 if (ref.selectionRange.covers(nodeRange)) { 1019 if (ref.selectionRange.covers(nodeRange)) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 } 1058 }
1025 // remember declaration names 1059 // remember declaration names
1026 if (node.inDeclarationContext()) { 1060 if (node.inDeclarationContext()) {
1027 ref._usedNames.add(node.name); 1061 ref._usedNames.add(node.name);
1028 } 1062 }
1029 } 1063 }
1030 return null; 1064 return null;
1031 } 1065 }
1032 } 1066 }
1033 1067
1068
1034 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor { 1069 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor {
1035 final ExtractMethodRefactoringImpl ref; 1070 final ExtractMethodRefactoringImpl ref;
1036 final VariableElement element; 1071 final VariableElement element;
1037 bool result = false; 1072 bool result = false;
1038 1073
1039 _IsUsedAfterSelectionVisitor(this.ref, this.element); 1074 _IsUsedAfterSelectionVisitor(this.ref, this.element);
1040 1075
1041 @override 1076 @override
1042 visitSimpleIdentifier(SimpleIdentifier node) { 1077 visitSimpleIdentifier(SimpleIdentifier node) {
1043 VariableElement nodeElement = getLocalVariableElement(node); 1078 VariableElement nodeElement = getLocalVariableElement(node);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 return false; 1182 return false;
1148 } 1183 }
1149 for (int i = 0; i < parameterTypes.length; i++) { 1184 for (int i = 0; i < parameterTypes.length; i++) {
1150 if (other.parameterTypes[i] != parameterTypes[i]) { 1185 if (other.parameterTypes[i] != parameterTypes[i]) {
1151 return false; 1186 return false;
1152 } 1187 }
1153 } 1188 }
1154 return true; 1189 return true;
1155 } 1190 }
1156 } 1191 }
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