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

Side by Side Diff: pkg/analysis_server/lib/src/services/generated/util.dart

Issue 482143002: Remove already ported generated code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 | « pkg/analysis_server/lib/src/services/generated/status.dart ('k') | no next file » | 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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library services.util; 8 library services.util;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
11 import 'package:analyzer/src/generated/java_core.dart' hide StringUtils; 11 import 'package:analyzer/src/generated/java_core.dart' hide StringUtils;
12 import 'package:analyzer/src/generated/ast.dart'; 12 import 'package:analyzer/src/generated/ast.dart';
13 import 'package:analyzer/src/generated/element.dart'; 13 import 'package:analyzer/src/generated/element.dart';
14 import 'package:analyzer/src/generated/engine.dart'; 14 import 'package:analyzer/src/generated/engine.dart';
15 import 'package:analyzer/src/generated/error.dart'; 15 import 'package:analyzer/src/generated/error.dart';
16 import 'package:analyzer/src/generated/resolver.dart'; 16 import 'package:analyzer/src/generated/resolver.dart';
17 import 'package:analyzer/src/generated/source.dart'; 17 import 'package:analyzer/src/generated/source.dart';
18 import 'package:analyzer/src/generated/scanner.dart'; 18 import 'package:analyzer/src/generated/scanner.dart';
19 import 'change.dart';
20 import 'proposal.dart';
21 import 'status.dart';
22 import 'stubs.dart'; 19 import 'stubs.dart';
23 20
24 /** 21 /**
25 * Context for which assistance should be provided. 22 * Context for which assistance should be provided.
26 */ 23 */
27 class AssistContext { 24 class AssistContext {
28 final SearchEngine searchEngine; 25 final SearchEngine searchEngine;
29 26
30 final AnalysisContext analysisContext; 27 final AnalysisContext analysisContext;
31 28
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 class CorrectionUtils { 113 class CorrectionUtils {
117 /** 114 /**
118 * If `true` then [addEdit] validates that 115 * If `true` then [addEdit] validates that
119 * [Edit] replaces correct part of the [Source]. 116 * [Edit] replaces correct part of the [Source].
120 */ 117 */
121 static bool _DEBUG_VALIDATE_EDITS = true; 118 static bool _DEBUG_VALIDATE_EDITS = true;
122 119
123 static List<String> _KNOWN_METHOD_NAME_PREFIXES = ["get", "is", "to"]; 120 static List<String> _KNOWN_METHOD_NAME_PREFIXES = ["get", "is", "to"];
124 121
125 /** 122 /**
126 * Validates that the [Edit] replaces the expected part of the [Source] and ad ds this
127 * [Edit] to the [SourceChange].
128 */
129 static void addEdit(AnalysisContext context, SourceChange change, String descr iption, String expected, Edit edit) {
130 if (_DEBUG_VALIDATE_EDITS) {
131 Source source = change.source;
132 String sourceContent = getSourceContent(context, source);
133 // prepare range
134 int beginIndex = edit.offset;
135 int endIndex = beginIndex + edit.length;
136 int sourceLength = sourceContent.length;
137 if (beginIndex >= sourceLength || endIndex >= sourceLength) {
138 throw new IllegalStateException("${source} has ${sourceLength} character s but ${beginIndex} to ${endIndex} requested.\n\nTry to use Tools | Reanalyze So urces.");
139 }
140 // check that range has expected content
141 String rangeContent = sourceContent.substring(beginIndex, endIndex);
142 if (rangeContent != expected) {
143 throw new IllegalStateException("${source} expected |${expected}| at ${b eginIndex} to ${endIndex} but |${rangeContent}| found.\n\nTry to use Tools | Rea nalyze Sources.");
144 }
145 }
146 // do add the Edit
147 change.addEdit(edit, description);
148 }
149
150 /**
151 * @return <code>true</code> if given [List]s are equals at given position. 123 * @return <code>true</code> if given [List]s are equals at given position.
152 */ 124 */
153 static bool allListsEqual(List<List> lists, int position) { 125 static bool allListsEqual(List<List> lists, int position) {
154 Object element = lists[0][position]; 126 Object element = lists[0][position];
155 for (List list in lists) { 127 for (List list in lists) {
156 if (!identical(list[position], element)) { 128 if (!identical(list[position], element)) {
157 return false; 129 return false;
158 } 130 }
159 } 131 }
160 return true; 132 return true;
161 } 133 }
162 134
163 /** 135 /**
164 * @return the updated [String] with applied [Edit]s.
165 */
166 static String applyReplaceEdits(String s, List<Edit> edits) {
167 // sort edits
168 edits = [];
169 edits.sort((Edit o1, Edit o2) => o1.offset - o2.offset);
170 // apply edits
171 int delta = 0;
172 for (Edit edit in edits) {
173 int editOffset = edit.offset + delta;
174 String beforeEdit = s.substring(0, editOffset);
175 String afterEdit = s.substring(editOffset + edit.length);
176 s = "${beforeEdit}${edit.replacement}${afterEdit}";
177 delta += getDeltaOffset(edit);
178 }
179 // done
180 return s;
181 }
182
183 /**
184 * @return <code>true</code> if given [SourceRange] covers given [AstNode]. 136 * @return <code>true</code> if given [SourceRange] covers given [AstNode].
185 */ 137 */
186 static bool covers(SourceRange r, AstNode node) { 138 static bool covers(SourceRange r, AstNode node) {
187 SourceRange nodeRange = SourceRangeFactory.rangeNode(node); 139 SourceRange nodeRange = SourceRangeFactory.rangeNode(node);
188 return r.covers(nodeRange); 140 return r.covers(nodeRange);
189 } 141 }
190 142
191 /** 143 /**
192 * @return all direct children of the given [Element]. 144 * @return all direct children of the given [Element].
193 */ 145 */
(...skipping 24 matching lines...) Expand all
218 } 170 }
219 if (typeName == "String") { 171 if (typeName == "String") {
220 return "''"; 172 return "''";
221 } 173 }
222 } 174 }
223 // no better guess 175 // no better guess
224 return "null"; 176 return "null";
225 } 177 }
226 178
227 /** 179 /**
228 * @return the number of characters this [Edit] will move offsets after its ra nge.
229 */
230 static int getDeltaOffset(Edit edit) => edit.replacement.length - edit.length;
231
232 /**
233 * @return the name of the [Element] kind. 180 * @return the name of the [Element] kind.
234 */ 181 */
235 static String getElementKindName(Element element) { 182 static String getElementKindName(Element element) {
236 ElementKind kind = element.kind; 183 ElementKind kind = element.kind;
237 return getElementKindName2(kind); 184 return getElementKindName2(kind);
238 } 185 }
239 186
240 /** 187 /**
241 * @return the display name of the [ElementKind]. 188 * @return the display name of the [ElementKind].
242 */ 189 */
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 static List<String> _getVariableNameSuggestions(String name) { 879 static List<String> _getVariableNameSuggestions(String name) {
933 List<String> result = []; 880 List<String> result = [];
934 List<String> parts = name.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z] )"); 881 List<String> parts = name.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z] )");
935 for (int i = 0; i < parts.length; i++) { 882 for (int i = 0; i < parts.length; i++) {
936 String suggestion = "${parts[i].toLowerCase()}${StringUtils.join(parts, "" , i + 1, parts.length)}"; 883 String suggestion = "${parts[i].toLowerCase()}${StringUtils.join(parts, "" , i + 1, parts.length)}";
937 result.add(suggestion); 884 result.add(suggestion);
938 } 885 }
939 return result; 886 return result;
940 } 887 }
941 888
942 /**
943 * Adds enclosing parenthesis if the precedence of the [InvertedCondition] if less than the
944 * precedence of the expression we are going it to use in.
945 */
946 static String _parenthesizeIfRequired(CorrectionUtils_InvertedCondition expr, int newOperatorPrecedence) {
947 if (expr._precedence < newOperatorPrecedence) {
948 return "(${expr._source})";
949 }
950 return expr._source;
951 }
952
953 final CompilationUnit unit; 889 final CompilationUnit unit;
954 890
955 LibraryElement _library; 891 LibraryElement _library;
956 892
957 String _buffer; 893 String _buffer;
958 894
959 String _endOfLine; 895 String _endOfLine;
960 896
961 CorrectionUtils(this.unit) { 897 CorrectionUtils(this.unit) {
962 CompilationUnitElement element = unit.element; 898 CompilationUnitElement element = unit.element;
963 this._library = element.library; 899 this._library = element.library;
964 this._buffer = getSourceContent(element.context, element.source); 900 this._buffer = getSourceContent(element.context, element.source);
965 } 901 }
966 902
967 /** 903 /**
968 * @return the source of the given [SourceRange] with indentation changed from "oldIndent"
969 * to "newIndent", keeping indentation of the lines relative to each o ther.
970 */
971 Edit createIndentEdit(SourceRange range, String oldIndent, String newIndent) {
972 String newSource = getIndentSource(range, oldIndent, newIndent);
973 return new Edit(range.offset, range.length, newSource);
974 }
975
976 /**
977 * @return the [AstNode] that encloses the given offset. 904 * @return the [AstNode] that encloses the given offset.
978 */ 905 */
979 AstNode findNode(int offset) => new NodeLocator.con1(offset).searchWithin(unit ); 906 AstNode findNode(int offset) => new NodeLocator.con1(offset).searchWithin(unit );
980 907
981 /** 908 /**
982 * TODO(scheglov) replace with nodes once there will be [CompilationUnit#getCo mments]. 909 * TODO(scheglov) replace with nodes once there will be [CompilationUnit#getCo mments].
983 * 910 *
984 * @return the [SourceRange]s of all comments in [CompilationUnit]. 911 * @return the [SourceRange]s of all comments in [CompilationUnit].
985 */ 912 */
986 List<SourceRange> get commentRanges { 913 List<SourceRange> get commentRanges {
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 sb.append(getTypeSource2(argument)); 1426 sb.append(getTypeSource2(argument));
1500 } 1427 }
1501 sb.append(">"); 1428 sb.append(">");
1502 } 1429 }
1503 } 1430 }
1504 // done 1431 // done
1505 return sb.toString(); 1432 return sb.toString();
1506 } 1433 }
1507 1434
1508 /** 1435 /**
1509 * @return the source of the inverted condition for the given logical expressi on.
1510 */
1511 String invertCondition(Expression expression) => _invertCondition0(expression) ._source;
1512
1513 /**
1514 * @return <code>true</code> if selection range contains only whitespace. 1436 * @return <code>true</code> if selection range contains only whitespace.
1515 */ 1437 */
1516 bool isJustWhitespace(SourceRange range) => getText3(range).trim().length == 0 ; 1438 bool isJustWhitespace(SourceRange range) => getText3(range).trim().length == 0 ;
1517 1439
1518 /** 1440 /**
1519 * @return <code>true</code> if selection range contains only whitespace or co mments 1441 * @return <code>true</code> if selection range contains only whitespace or co mments
1520 */ 1442 */
1521 bool isJustWhitespaceOrComment(SourceRange range) { 1443 bool isJustWhitespaceOrComment(SourceRange range) {
1522 String trimmedText = getText3(range).trim(); 1444 String trimmedText = getText3(range).trim();
1523 // may be whitespace 1445 // may be whitespace
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1564 ImportElement _getImportElement(Element element) { 1486 ImportElement _getImportElement(Element element) {
1565 for (ImportElement imp in _library.imports) { 1487 for (ImportElement imp in _library.imports) {
1566 Map<String, Element> definedNames = getImportNamespace(imp); 1488 Map<String, Element> definedNames = getImportNamespace(imp);
1567 if (definedNames.containsValue(element)) { 1489 if (definedNames.containsValue(element)) {
1568 return imp; 1490 return imp;
1569 } 1491 }
1570 } 1492 }
1571 return null; 1493 return null;
1572 } 1494 }
1573 1495
1574 /**
1575 * @return the [InvertedCondition] for the given logical expression.
1576 */
1577 CorrectionUtils_InvertedCondition _invertCondition0(Expression expression) {
1578 if (expression is BooleanLiteral) {
1579 BooleanLiteral literal = expression;
1580 if (literal.value) {
1581 return CorrectionUtils_InvertedCondition._simple("false");
1582 } else {
1583 return CorrectionUtils_InvertedCondition._simple("true");
1584 }
1585 }
1586 if (expression is BinaryExpression) {
1587 BinaryExpression binary = expression;
1588 TokenType operator = binary.operator.type;
1589 Expression le = binary.leftOperand;
1590 Expression re = binary.rightOperand;
1591 CorrectionUtils_InvertedCondition ls = _invertCondition0(le);
1592 CorrectionUtils_InvertedCondition rs = _invertCondition0(re);
1593 if (operator == TokenType.LT) {
1594 return CorrectionUtils_InvertedCondition._binary2(ls, " >= ", rs);
1595 }
1596 if (operator == TokenType.GT) {
1597 return CorrectionUtils_InvertedCondition._binary2(ls, " <= ", rs);
1598 }
1599 if (operator == TokenType.LT_EQ) {
1600 return CorrectionUtils_InvertedCondition._binary2(ls, " > ", rs);
1601 }
1602 if (operator == TokenType.GT_EQ) {
1603 return CorrectionUtils_InvertedCondition._binary2(ls, " < ", rs);
1604 }
1605 if (operator == TokenType.EQ_EQ) {
1606 return CorrectionUtils_InvertedCondition._binary2(ls, " != ", rs);
1607 }
1608 if (operator == TokenType.BANG_EQ) {
1609 return CorrectionUtils_InvertedCondition._binary2(ls, " == ", rs);
1610 }
1611 if (operator == TokenType.AMPERSAND_AMPERSAND) {
1612 int newPrecedence = TokenType.BAR_BAR.precedence;
1613 return CorrectionUtils_InvertedCondition._binary(newPrecedence, ls, " || ", rs);
1614 }
1615 if (operator == TokenType.BAR_BAR) {
1616 int newPrecedence = TokenType.AMPERSAND_AMPERSAND.precedence;
1617 return CorrectionUtils_InvertedCondition._binary(newPrecedence, ls, " && ", rs);
1618 }
1619 }
1620 if (expression is IsExpression) {
1621 IsExpression isExpression = expression;
1622 String expressionSource = getText(isExpression.expression);
1623 String typeSource = getText(isExpression.type);
1624 if (isExpression.notOperator == null) {
1625 return CorrectionUtils_InvertedCondition._simple("${expressionSource} is ! ${typeSource}");
1626 } else {
1627 return CorrectionUtils_InvertedCondition._simple("${expressionSource} is ${typeSource}");
1628 }
1629 }
1630 if (expression is PrefixExpression) {
1631 PrefixExpression prefixExpression = expression;
1632 TokenType operator = prefixExpression.operator.type;
1633 if (operator == TokenType.BANG) {
1634 Expression operand = prefixExpression.operand;
1635 while (operand is ParenthesizedExpression) {
1636 ParenthesizedExpression pe = operand as ParenthesizedExpression;
1637 operand = pe.expression;
1638 }
1639 return CorrectionUtils_InvertedCondition._simple(getText(operand));
1640 }
1641 }
1642 if (expression is ParenthesizedExpression) {
1643 ParenthesizedExpression pe = expression;
1644 Expression innerExpresion = pe.expression;
1645 while (innerExpresion is ParenthesizedExpression) {
1646 innerExpresion = (innerExpresion as ParenthesizedExpression).expression;
1647 }
1648 return _invertCondition0(innerExpresion);
1649 }
1650 DartType type = expression.bestType;
1651 if (type.displayName == "bool") {
1652 return CorrectionUtils_InvertedCondition._simple("!${getText(expression)}" );
1653 }
1654 return CorrectionUtils_InvertedCondition._simple(getText(expression));
1655 }
1656
1657 bool _selectionIncludesNonWhitespaceOutsideOperands(SourceRange selection, Lis t<Expression> operands) => _selectionIncludesNonWhitespaceOutsideRange(selection , SourceRangeFactory.rangeNodes(operands)); 1496 bool _selectionIncludesNonWhitespaceOutsideOperands(SourceRange selection, Lis t<Expression> operands) => _selectionIncludesNonWhitespaceOutsideRange(selection , SourceRangeFactory.rangeNodes(operands));
1658 1497
1659 /** 1498 /**
1660 * @return <code>true</code> if "selection" covers "range" and there are any n on-whitespace tokens 1499 * @return <code>true</code> if "selection" covers "range" and there are any n on-whitespace tokens
1661 * between "selection" and "range" start/end. 1500 * between "selection" and "range" start/end.
1662 */ 1501 */
1663 bool _selectionIncludesNonWhitespaceOutsideRange(SourceRange selection, Source Range range) { 1502 bool _selectionIncludesNonWhitespaceOutsideRange(SourceRange selection, Source Range range) {
1664 // selection should cover range 1503 // selection should cover range
1665 if (!selection.covers(range)) { 1504 if (!selection.covers(range)) {
1666 return false; 1505 return false;
(...skipping 15 matching lines...) Expand all
1682 * Describes where to insert new directive or top-level declaration. 1521 * Describes where to insert new directive or top-level declaration.
1683 */ 1522 */
1684 class CorrectionUtils_InsertDesc { 1523 class CorrectionUtils_InsertDesc {
1685 int offset = 0; 1524 int offset = 0;
1686 1525
1687 String prefix = ""; 1526 String prefix = "";
1688 1527
1689 String suffix = ""; 1528 String suffix = "";
1690 } 1529 }
1691 1530
1692 /**
1693 * This class is used to hold the source and also its precedence during invertin g logical
1694 * expressions.
1695 */
1696 class CorrectionUtils_InvertedCondition {
1697 static CorrectionUtils_InvertedCondition _binary(int precedence, CorrectionUti ls_InvertedCondition left, String operation, CorrectionUtils_InvertedCondition r ight) => new CorrectionUtils_InvertedCondition(precedence, "${CorrectionUtils._p arenthesizeIfRequired(left, precedence)}${operation}${CorrectionUtils._parenthes izeIfRequired(right, precedence)}");
1698
1699 static CorrectionUtils_InvertedCondition _binary2(CorrectionUtils_InvertedCond ition left, String operation, CorrectionUtils_InvertedCondition right) => new Co rrectionUtils_InvertedCondition(2147483647, "${left._source}${operation}${right. _source}");
1700
1701 static CorrectionUtils_InvertedCondition _simple(String source) => new Correct ionUtils_InvertedCondition(2147483647, source);
1702
1703 final int _precedence;
1704
1705 final String _source;
1706
1707 CorrectionUtils_InvertedCondition(this._precedence, this._source);
1708 }
1709
1710 class GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor extends Gener alizingAstVisitor<Object> { 1531 class GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor extends Gener alizingAstVisitor<Object> {
1711 TokenType groupOperatorType; 1532 TokenType groupOperatorType;
1712 1533
1713 List<Expression> operands; 1534 List<Expression> operands;
1714 1535
1715 GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor(this.groupOperato rType, this.operands) : super(); 1536 GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor(this.groupOperato rType, this.operands) : super();
1716 1537
1717 @override 1538 @override
1718 Object visitExpression(Expression node) { 1539 Object visitExpression(Expression node) {
1719 if (node is BinaryExpression && node.operator.type == groupOperatorType) { 1540 if (node is BinaryExpression && node.operator.type == groupOperatorType) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 } 1695 }
1875 1696
1876 void _match(Element element, AstNode node) { 1697 void _match(Element element, AstNode node) {
1877 if (identical(_target, element) || identical(_target2, element) || identical (_target3, element) || identical(_target4, element)) { 1698 if (identical(_target, element) || identical(_target2, element) || identical (_target3, element) || identical(_target4, element)) {
1878 _matches.add(node); 1699 _matches.add(node);
1879 } 1700 }
1880 } 1701 }
1881 } 1702 }
1882 1703
1883 /** 1704 /**
1884 * Abstract visitor for visiting [AstNode]s covered by the selection [SourceRang e].
1885 */
1886 class SelectionAnalyzer extends GeneralizingAstVisitor<Object> {
1887 SourceRange selection;
1888
1889 AstNode _coveringNode;
1890
1891 List<AstNode> _selectedNodes;
1892
1893 SelectionAnalyzer(SourceRange selection) {
1894 assert(selection != null);
1895 this.selection = selection;
1896 }
1897
1898 /**
1899 * @return the [AstNode] with the shortest length which completely covers the specified
1900 * selection.
1901 */
1902 AstNode get coveringNode => _coveringNode;
1903
1904 /**
1905 * @return the first selected [AstNode], may be <code>null</code>.
1906 */
1907 AstNode get firstSelectedNode {
1908 if (_selectedNodes == null || _selectedNodes.isEmpty) {
1909 return null;
1910 }
1911 return _selectedNodes[0];
1912 }
1913
1914 /**
1915 * @return the last selected [AstNode], may be <code>null</code>.
1916 */
1917 AstNode get lastSelectedNode {
1918 if (_selectedNodes == null || _selectedNodes.isEmpty) {
1919 return null;
1920 }
1921 return _selectedNodes[_selectedNodes.length - 1];
1922 }
1923
1924 /**
1925 * @return the [SourceRange] which covers selected [AstNode]s, may be
1926 * <code>null</code> if no [AstNode]s under selection.
1927 */
1928 SourceRange get selectedNodeRange {
1929 if (_selectedNodes == null || _selectedNodes.isEmpty) {
1930 return null;
1931 }
1932 AstNode firstNode = _selectedNodes[0];
1933 AstNode lastNode = _selectedNodes[_selectedNodes.length - 1];
1934 return SourceRangeFactory.rangeStartEnd(firstNode, lastNode);
1935 }
1936
1937 /**
1938 * @return the [AstNode]s fully covered by the selection [SourceRange].
1939 */
1940 List<AstNode> get selectedNodes {
1941 if (_selectedNodes == null || _selectedNodes.isEmpty) {
1942 return [];
1943 }
1944 return _selectedNodes;
1945 }
1946
1947 /**
1948 * @return <code>true</code> if there are [AstNode] fully covered by the selec tion
1949 * [SourceRange].
1950 */
1951 bool get hasSelectedNodes => _selectedNodes != null && !_selectedNodes.isEmpty ;
1952
1953 @override
1954 Object visitNode(AstNode node) {
1955 SourceRange nodeRange = SourceRangeFactory.rangeNode(node);
1956 if (selection.covers(nodeRange)) {
1957 if (isFirstNode) {
1958 handleFirstSelectedNode(node);
1959 } else {
1960 handleNextSelectedNode(node);
1961 }
1962 return null;
1963 } else if (selection.coveredBy(nodeRange)) {
1964 _coveringNode = node;
1965 node.visitChildren(this);
1966 return null;
1967 } else if (selection.startsIn(nodeRange)) {
1968 handleSelectionStartsIn(node);
1969 node.visitChildren(this);
1970 return null;
1971 } else if (selection.endsIn(nodeRange)) {
1972 handleSelectionEndsIn(node);
1973 node.visitChildren(this);
1974 return null;
1975 }
1976 // no intersection
1977 return null;
1978 }
1979
1980 /**
1981 * Adds first selected [AstNode].
1982 */
1983 void handleFirstSelectedNode(AstNode node) {
1984 _selectedNodes = [];
1985 _selectedNodes.add(node);
1986 }
1987
1988 /**
1989 * Adds second or more selected [AstNode].
1990 */
1991 void handleNextSelectedNode(AstNode node) {
1992 if (identical(firstSelectedNode.parent, node.parent)) {
1993 _selectedNodes.add(node);
1994 }
1995 }
1996
1997 /**
1998 * Notifies that selection ends in given [AstNode].
1999 */
2000 void handleSelectionEndsIn(AstNode node) {
2001 }
2002
2003 /**
2004 * Notifies that selection starts in given [AstNode].
2005 */
2006 void handleSelectionStartsIn(AstNode node) {
2007 }
2008
2009 /**
2010 * Resets selected nodes.
2011 */
2012 void reset() {
2013 _selectedNodes = null;
2014 }
2015
2016 /**
2017 * @return <code>true</code> if there was no selected nodes yet.
2018 */
2019 bool get isFirstNode => _selectedNodes == null;
2020 }
2021
2022 /**
2023 * Helper for building Dart source with tracked positions.
2024 */
2025 class SourceBuilder {
2026 final int offset;
2027
2028 JavaStringBuilder _buffer = new JavaStringBuilder();
2029
2030 Map<String, List<SourceRange>> _linkedPositions = {};
2031
2032 final Map<String, List<LinkedPositionProposal>> linkedProposals = {};
2033
2034 String _currentPositionGroupId;
2035
2036 int _currentPositionStart = 0;
2037
2038 int _endPosition = -1;
2039
2040 SourceBuilder.con1(this.offset);
2041
2042 SourceBuilder.con2(SourceRange offsetRange) : this.con1(offsetRange.offset);
2043
2044 /**
2045 * Adds proposal for the current position, may be called after [startPosition] .
2046 */
2047 void addProposal(CorrectionImage icon, String text) {
2048 List<LinkedPositionProposal> proposals = linkedProposals[_currentPositionGro upId];
2049 if (proposals == null) {
2050 proposals = [];
2051 linkedProposals[_currentPositionGroupId] = proposals;
2052 }
2053 proposals.add(new LinkedPositionProposal(icon, text));
2054 }
2055
2056 /**
2057 * Appends source to the buffer.
2058 */
2059 SourceBuilder append(String s) {
2060 _buffer.append(s);
2061 return this;
2062 }
2063
2064 /**
2065 * Ends position started using [startPosition].
2066 */
2067 void endPosition() {
2068 assert(_currentPositionGroupId != null);
2069 _addPosition();
2070 _currentPositionGroupId = null;
2071 }
2072
2073 /**
2074 * @return the "end position" for the [CorrectionProposal], may be <code>-1</c ode> if not
2075 * set in this [SourceBuilder].
2076 */
2077 int get endPosition2 {
2078 if (_endPosition == -1) {
2079 return -1;
2080 }
2081 return offset + _endPosition;
2082 }
2083
2084 /**
2085 * @return the [Map] or position IDs to their locations.
2086 */
2087 Map<String, List<SourceRange>> get linkedPositions => _linkedPositions;
2088
2089 /**
2090 * @return the length of the built source.
2091 */
2092 int length() => _buffer.length;
2093
2094 /**
2095 * Marks current position as "end position" of the [CorrectionProposal].
2096 */
2097 void setEndPosition() {
2098 _endPosition = _buffer.length;
2099 }
2100
2101 /**
2102 * Sets text-only proposals for the current position.
2103 */
2104 void set proposals(List<String> proposals) {
2105 List<LinkedPositionProposal> proposalList = [];
2106 for (String proposalText in proposals) {
2107 proposalList.add(new LinkedPositionProposal(null, proposalText));
2108 }
2109 linkedProposals[_currentPositionGroupId] = proposalList;
2110 }
2111
2112 /**
2113 * Starts linked position with given ID.
2114 */
2115 void startPosition(String groupId) {
2116 assert(_currentPositionGroupId == null);
2117 _currentPositionGroupId = groupId;
2118 _currentPositionStart = _buffer.length;
2119 }
2120
2121 @override
2122 String toString() => _buffer.toString();
2123
2124 /**
2125 * Adds position location [SourceRange] using current fields.
2126 */
2127 void _addPosition() {
2128 List<SourceRange> locations = _linkedPositions[_currentPositionGroupId];
2129 if (locations == null) {
2130 locations = [];
2131 _linkedPositions[_currentPositionGroupId] = locations;
2132 }
2133 int start = offset + _currentPositionStart;
2134 int end = offset + _buffer.length;
2135 locations.add(SourceRangeFactory.rangeStartEnd(start, end));
2136 }
2137 }
2138
2139 /**
2140 * Analyzer to check if a selection covers a valid set of statements of AST.
2141 */
2142 class StatementAnalyzer extends SelectionAnalyzer {
2143 /**
2144 * @return <code>true</code> if "nodes" contains "node".
2145 */
2146 static bool _contains(List<AstNode> nodes, AstNode node) => nodes.contains(nod e);
2147
2148 /**
2149 * @return <code>true</code> if "nodes" contains one of the "otherNodes".
2150 */
2151 static bool _contains2(List<AstNode> nodes, List<AstNode> otherNodes) {
2152 for (AstNode otherNode in otherNodes) {
2153 if (nodes.contains(otherNode)) {
2154 return true;
2155 }
2156 }
2157 return false;
2158 }
2159
2160 CorrectionUtils utils;
2161
2162 RefactoringStatus _status = new RefactoringStatus();
2163
2164 StatementAnalyzer.con1(CompilationUnit cunit, SourceRange selection) : this.co n2(new CorrectionUtils(cunit), selection);
2165
2166 StatementAnalyzer.con2(CorrectionUtils utils, SourceRange selection) : super(s election) {
2167 this.utils = utils;
2168 }
2169
2170 /**
2171 * @return the [RefactoringStatus] result of checking selection.
2172 */
2173 RefactoringStatus get status => _status;
2174
2175 @override
2176 Object visitCompilationUnit(CompilationUnit node) {
2177 super.visitCompilationUnit(node);
2178 if (!hasSelectedNodes) {
2179 return null;
2180 }
2181 // check that selection does not begin/end in comment
2182 {
2183 int selectionStart = selection.offset;
2184 int selectionEnd = selection.end;
2185 List<SourceRange> commentRanges = utils.commentRanges;
2186 for (SourceRange commentRange in commentRanges) {
2187 if (commentRange.contains(selectionStart)) {
2188 invalidSelection("Selection begins inside a comment.");
2189 }
2190 if (commentRange.containsExclusive(selectionEnd)) {
2191 invalidSelection("Selection ends inside a comment.");
2192 }
2193 }
2194 }
2195 // more checks
2196 if (!_status.hasFatalError) {
2197 _checkSelectedNodes(node);
2198 }
2199 return null;
2200 }
2201
2202 @override
2203 Object visitDoStatement(DoStatement node) {
2204 super.visitDoStatement(node);
2205 List<AstNode> selectedNodes = this.selectedNodes;
2206 if (_contains(selectedNodes, node.body)) {
2207 invalidSelection("Operation not applicable to a 'do' statement's body and expression.");
2208 }
2209 return null;
2210 }
2211
2212 @override
2213 Object visitForStatement(ForStatement node) {
2214 super.visitForStatement(node);
2215 List<AstNode> selectedNodes = this.selectedNodes;
2216 bool containsInit = _contains(selectedNodes, node.initialization) || _contai ns(selectedNodes, node.variables);
2217 bool containsCondition = _contains(selectedNodes, node.condition);
2218 bool containsUpdaters = _contains2(selectedNodes, node.updaters);
2219 bool containsBody = _contains(selectedNodes, node.body);
2220 if (containsInit && containsCondition) {
2221 invalidSelection("Operation not applicable to a 'for' statement's initiali zer and condition.");
2222 } else if (containsCondition && containsUpdaters) {
2223 invalidSelection("Operation not applicable to a 'for' statement's conditio n and updaters.");
2224 } else if (containsUpdaters && containsBody) {
2225 invalidSelection("Operation not applicable to a 'for' statement's updaters and body.");
2226 }
2227 return null;
2228 }
2229
2230 @override
2231 Object visitSwitchStatement(SwitchStatement node) {
2232 super.visitSwitchStatement(node);
2233 List<AstNode> selectedNodes = this.selectedNodes;
2234 List<SwitchMember> switchMembers = node.members;
2235 for (AstNode selectedNode in selectedNodes) {
2236 if (switchMembers.contains(selectedNode)) {
2237 invalidSelection("Selection must either cover whole switch statement or parts of a single case block.");
2238 break;
2239 }
2240 }
2241 return null;
2242 }
2243
2244 @override
2245 Object visitTryStatement(TryStatement node) {
2246 super.visitTryStatement(node);
2247 AstNode firstSelectedNode = this.firstSelectedNode;
2248 if (firstSelectedNode != null) {
2249 if (identical(firstSelectedNode, node.body) || identical(firstSelectedNode , node.finallyBlock)) {
2250 invalidSelection("Selection must either cover whole try statement or par ts of try, catch, or finally block.");
2251 } else {
2252 List<CatchClause> catchClauses = node.catchClauses;
2253 for (CatchClause catchClause in catchClauses) {
2254 if (identical(firstSelectedNode, catchClause) || identical(firstSelect edNode, catchClause.body) || identical(firstSelectedNode, catchClause.exceptionP arameter)) {
2255 invalidSelection("Selection must either cover whole try statement or parts of try, catch, or finally block.");
2256 }
2257 }
2258 }
2259 }
2260 return null;
2261 }
2262
2263 @override
2264 Object visitWhileStatement(WhileStatement node) {
2265 super.visitWhileStatement(node);
2266 List<AstNode> selectedNodes = this.selectedNodes;
2267 if (_contains(selectedNodes, node.condition) && _contains(selectedNodes, nod e.body)) {
2268 invalidSelection("Operation not applicable to a while statement's expressi on and body.");
2269 }
2270 return null;
2271 }
2272
2273 /**
2274 * Records fatal error with given message.
2275 */
2276 void invalidSelection(String message) {
2277 invalidSelection2(message, null);
2278 }
2279
2280 /**
2281 * Records fatal error with given message and [RefactoringStatusContext].
2282 */
2283 void invalidSelection2(String message, RefactoringStatusContext context) {
2284 _status.addFatalError(message, context);
2285 reset();
2286 }
2287
2288 /**
2289 * Checks final selected [AstNode]s after processing [CompilationUnit].
2290 */
2291 void _checkSelectedNodes(CompilationUnit unit) {
2292 List<AstNode> nodes = selectedNodes;
2293 // some tokens before first selected node
2294 {
2295 AstNode firstNode = nodes[0];
2296 SourceRange rangeBeforeFirstNode = SourceRangeFactory.rangeStartStart(sele ction, firstNode);
2297 if (_hasTokens(rangeBeforeFirstNode)) {
2298 invalidSelection2("The beginning of the selection contains characters th at do not belong to a statement.", new RefactoringStatusContext.forUnit(unit, ra ngeBeforeFirstNode));
2299 }
2300 }
2301 // some tokens after last selected node
2302 {
2303 AstNode lastNode = nodes.last;
2304 SourceRange rangeAfterLastNode = SourceRangeFactory.rangeEndEnd(lastNode, selection);
2305 if (_hasTokens(rangeAfterLastNode)) {
2306 invalidSelection2("The end of the selection contains characters that do not belong to a statement.", new RefactoringStatusContext.forUnit(unit, rangeAft erLastNode));
2307 }
2308 }
2309 }
2310
2311 /**
2312 * @return the [Token]s in given [SourceRange].
2313 */
2314 List<Token> _getTokens(SourceRange range) {
2315 try {
2316 String text = utils.getText3(range);
2317 return TokenUtils.getTokens(text);
2318 } catch (e) {
2319 return [];
2320 }
2321 }
2322
2323 /**
2324 * @return <code>true</code> if there are [Token]s in the given [SourceRange].
2325 */
2326 bool _hasTokens(SourceRange range) => !_getTokens(range).isEmpty;
2327 }
2328
2329 /**
2330 * Utilities to work with [Token]s. 1705 * Utilities to work with [Token]s.
2331 */ 1706 */
2332 class TokenUtils { 1707 class TokenUtils {
2333 /** 1708 /**
2334 * @return the first [KeywordToken] with given [Keyword], may be <code>null</c ode> if 1709 * @return the first [KeywordToken] with given [Keyword], may be <code>null</c ode> if
2335 * not found. 1710 * not found.
2336 */ 1711 */
2337 static KeywordToken findKeywordToken(List<Token> tokens, Keyword keyword) { 1712 static KeywordToken findKeywordToken(List<Token> tokens, Keyword keyword) {
2338 for (Token token in tokens) { 1713 for (Token token in tokens) {
2339 if (token is KeywordToken) { 1714 if (token is KeywordToken) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 return []; 1752 return [];
2378 } 1753 }
2379 } 1754 }
2380 1755
2381 /** 1756 /**
2382 * @return <code>true</code> if given [Token]s contain only single [Token] wit h given 1757 * @return <code>true</code> if given [Token]s contain only single [Token] wit h given
2383 * [TokenType]. 1758 * [TokenType].
2384 */ 1759 */
2385 static bool hasOnly(List<Token> tokens, TokenType type) => tokens.length == 1 && tokens[0].type == type; 1760 static bool hasOnly(List<Token> tokens, TokenType type) => tokens.length == 1 && tokens[0].type == type;
2386 } 1761 }
2387
2388 class URIUtils {
2389 /**
2390 * Computes relative relative path to reference "target" from "base". Uses ".. " if needed, in
2391 * contrast to [URI#relativize].
2392 */
2393 static String computeRelativePath(String base, String target) {
2394 // convert to URI separator
2395 base = base.replaceAll("\\\\", "/");
2396 target = target.replaceAll("\\\\", "/");
2397 if (base.startsWith("/") && target.startsWith("/")) {
2398 base = base.substring(1);
2399 target = target.substring(1);
2400 }
2401 // equal paths - no relative
2402 if (base == target) {
2403 return null;
2404 }
2405 // split paths
2406 List<String> baseParts = base.split("/");
2407 List<String> targetParts = target.split("/");
2408 // prepare maximum possible common root length
2409 int length = baseParts.length < targetParts.length ? baseParts.length : targ etParts.length;
2410 // find common root
2411 int lastCommonRoot = -1;
2412 for (int i = 0; i < length; i++) {
2413 if (baseParts[i] == targetParts[i]) {
2414 lastCommonRoot = i;
2415 } else {
2416 break;
2417 }
2418 }
2419 // append ..
2420 JavaStringBuilder relativePath = new JavaStringBuilder();
2421 for (int i = lastCommonRoot + 1; i < baseParts.length; i++) {
2422 if (baseParts[i].length > 0) {
2423 relativePath.append("../");
2424 }
2425 }
2426 // append target folder names
2427 for (int i = lastCommonRoot + 1; i < targetParts.length - 1; i++) {
2428 String p = targetParts[i];
2429 relativePath.append(p);
2430 relativePath.append("/");
2431 }
2432 // append target file name
2433 relativePath.append(targetParts[targetParts.length - 1]);
2434 // done
2435 return relativePath.toString();
2436 }
2437 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/services/generated/status.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698