| 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 computer.navigation; | 5 library computer.navigation; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/protocol_server.dart' as protocol; | 7 import 'package:analysis_server/src/protocol_server.dart' as protocol; |
| 8 import 'package:analyzer/src/generated/ast.dart'; | 8 import 'package:analyzer/src/generated/ast.dart'; |
| 9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
| 10 import 'package:analyzer/src/generated/scanner.dart'; | 10 import 'package:analyzer/src/generated/scanner.dart'; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 if (element is FieldFormalParameterElement) { | 33 if (element is FieldFormalParameterElement) { |
| 34 element = (element as FieldFormalParameterElement).field; | 34 element = (element as FieldFormalParameterElement).field; |
| 35 } | 35 } |
| 36 if (element == null || element == DynamicElementImpl.instance) { | 36 if (element == null || element == DynamicElementImpl.instance) { |
| 37 return; | 37 return; |
| 38 } | 38 } |
| 39 protocol.Element target = protocol.newElement_fromEngine(element); | 39 protocol.Element target = protocol.newElement_fromEngine(element); |
| 40 _regions.add(new protocol.NavigationRegion(offset, length, [target])); | 40 _regions.add(new protocol.NavigationRegion(offset, length, [target])); |
| 41 } | 41 } |
| 42 | 42 |
| 43 void _addRegionForNode(AstNode node, Element element) { | |
| 44 int offset = node.offset; | |
| 45 int length = node.length; | |
| 46 _addRegion(offset, length, element); | |
| 47 } | |
| 48 | |
| 49 void _addRegionForToken(Token token, Element element) { | |
| 50 int offset = token.offset; | |
| 51 int length = token.length; | |
| 52 _addRegion(offset, length, element); | |
| 53 } | |
| 54 | |
| 55 void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) { | 43 void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) { |
| 56 int offset = a.offset; | 44 int offset = a.offset; |
| 57 int length = b.end - offset; | 45 int length = b.end - offset; |
| 58 _addRegion(offset, length, element); | 46 _addRegion(offset, length, element); |
| 59 } | 47 } |
| 60 | 48 |
| 61 void _addRegion_nodeStart_nodeStart(AstNode a, AstNode b, Element element) { | 49 void _addRegion_nodeStart_nodeStart(AstNode a, AstNode b, Element element, |
| 50 {bool excludeLastChar: false}) { |
| 62 int offset = a.offset; | 51 int offset = a.offset; |
| 63 int length = b.offset - offset; | 52 int length = b.offset - offset; |
| 53 if (excludeLastChar) { |
| 54 length--; |
| 55 } |
| 64 _addRegion(offset, length, element); | 56 _addRegion(offset, length, element); |
| 65 } | 57 } |
| 66 | 58 |
| 67 void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) { | 59 void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) { |
| 68 int offset = a.offset; | 60 int offset = a.offset; |
| 69 int length = b.end - offset; | 61 int length = b.end - offset; |
| 70 _addRegion(offset, length, element); | 62 _addRegion(offset, length, element); |
| 71 } | 63 } |
| 64 |
| 65 void _addRegionForNode(AstNode node, Element element) { |
| 66 int offset = node.offset; |
| 67 int length = node.length; |
| 68 _addRegion(offset, length, element); |
| 69 } |
| 70 |
| 71 void _addRegionForToken(Token token, Element element) { |
| 72 int offset = token.offset; |
| 73 int length = token.length; |
| 74 _addRegion(offset, length, element); |
| 75 } |
| 72 } | 76 } |
| 73 | 77 |
| 74 | 78 |
| 75 class _DartUnitNavigationComputerVisitor extends RecursiveAstVisitor { | 79 class _DartUnitNavigationComputerVisitor extends RecursiveAstVisitor { |
| 76 final DartUnitNavigationComputer computer; | 80 final DartUnitNavigationComputer computer; |
| 77 | 81 |
| 78 _DartUnitNavigationComputerVisitor(this.computer); | 82 _DartUnitNavigationComputerVisitor(this.computer); |
| 79 | 83 |
| 80 @override | 84 @override |
| 81 visitAssignmentExpression(AssignmentExpression node) { | 85 visitAssignmentExpression(AssignmentExpression node) { |
| 86 _safelyVisit(node.leftHandSide); |
| 82 computer._addRegionForToken(node.operator, node.bestElement); | 87 computer._addRegionForToken(node.operator, node.bestElement); |
| 83 return super.visitAssignmentExpression(node); | 88 _safelyVisit(node.rightHandSide); |
| 84 } | 89 } |
| 85 | 90 |
| 86 @override | 91 @override |
| 87 visitBinaryExpression(BinaryExpression node) { | 92 visitBinaryExpression(BinaryExpression node) { |
| 93 _safelyVisit(node.leftOperand); |
| 88 computer._addRegionForToken(node.operator, node.bestElement); | 94 computer._addRegionForToken(node.operator, node.bestElement); |
| 89 return super.visitBinaryExpression(node); | 95 _safelyVisit(node.rightOperand); |
| 90 } | 96 } |
| 91 | 97 |
| 92 @override | 98 @override |
| 99 visitCompilationUnit(CompilationUnit unit) { |
| 100 // prepare top-level nodes sorted by their offsets |
| 101 List<AstNode> nodes = <AstNode>[]; |
| 102 nodes.addAll(unit.directives); |
| 103 nodes.addAll(unit.declarations); |
| 104 nodes.sort((a, b) { |
| 105 return a.offset - b.offset; |
| 106 }); |
| 107 // visit sorted nodes |
| 108 for (AstNode node in nodes) { |
| 109 node.accept(this); |
| 110 } |
| 111 } |
| 112 |
| 113 @override |
| 93 visitConstructorDeclaration(ConstructorDeclaration node) { | 114 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 94 // associate constructor with "T" or "T.name" | 115 // associate constructor with "T" or "T.name" |
| 95 { | 116 { |
| 96 AstNode firstNode = node.returnType; | 117 AstNode firstNode = node.returnType; |
| 97 AstNode lastNode = node.name; | 118 AstNode lastNode = node.name; |
| 98 if (lastNode == null) { | 119 if (lastNode == null) { |
| 99 lastNode = firstNode; | 120 lastNode = firstNode; |
| 100 } | 121 } |
| 101 if (firstNode != null && lastNode != null) { | 122 if (firstNode != null && lastNode != null) { |
| 102 computer._addRegion_nodeStart_nodeEnd( | 123 computer._addRegion_nodeStart_nodeEnd( |
| 103 firstNode, | 124 firstNode, |
| 104 lastNode, | 125 lastNode, |
| 105 node.element); | 126 node.element); |
| 106 } | 127 } |
| 107 } | 128 } |
| 108 return super.visitConstructorDeclaration(node); | 129 super.visitConstructorDeclaration(node); |
| 109 } | 130 } |
| 110 | 131 |
| 111 @override | 132 @override |
| 112 visitExportDirective(ExportDirective node) { | 133 visitExportDirective(ExportDirective node) { |
| 113 ExportElement exportElement = node.element; | 134 ExportElement exportElement = node.element; |
| 114 if (exportElement != null) { | 135 if (exportElement != null) { |
| 115 Element element = exportElement.exportedLibrary; | 136 Element element = exportElement.exportedLibrary; |
| 116 computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element); | 137 computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element); |
| 117 } | 138 } |
| 118 return super.visitExportDirective(node); | 139 super.visitExportDirective(node); |
| 119 } | 140 } |
| 120 | 141 |
| 121 @override | 142 @override |
| 122 visitImportDirective(ImportDirective node) { | 143 visitImportDirective(ImportDirective node) { |
| 123 ImportElement importElement = node.element; | 144 ImportElement importElement = node.element; |
| 124 if (importElement != null) { | 145 if (importElement != null) { |
| 125 Element element = importElement.importedLibrary; | 146 Element element = importElement.importedLibrary; |
| 126 computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element); | 147 computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element); |
| 127 } | 148 } |
| 128 return super.visitImportDirective(node); | 149 super.visitImportDirective(node); |
| 129 } | 150 } |
| 130 | 151 |
| 131 @override | 152 @override |
| 132 visitIndexExpression(IndexExpression node) { | 153 visitIndexExpression(IndexExpression node) { |
| 154 super.visitIndexExpression(node); |
| 133 computer._addRegionForToken(node.rightBracket, node.bestElement); | 155 computer._addRegionForToken(node.rightBracket, node.bestElement); |
| 134 return super.visitIndexExpression(node); | |
| 135 } | 156 } |
| 136 | 157 |
| 137 @override | 158 @override |
| 138 visitInstanceCreationExpression(InstanceCreationExpression node) { | 159 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 139 Element element = node.staticElement; | 160 Element element = node.staticElement; |
| 140 ConstructorName constructorName = node.constructorName; | 161 ConstructorName constructorName = node.constructorName; |
| 141 if (element != null && constructorName != null) { | 162 if (element != null && constructorName != null) { |
| 142 ClassElement classElement = element.enclosingElement; | 163 ClassElement classElement = element.enclosingElement; |
| 143 if (element.isSynthetic) { | 164 if (element.isSynthetic) { |
| 144 element = classElement; | 165 element = classElement; |
| 145 computer._addRegion_nodeStart_nodeStart( | 166 computer._addRegion_nodeStart_nodeStart( |
| 146 node, | 167 node, |
| 147 node.argumentList, | 168 node.argumentList, |
| 148 element); | 169 element); |
| 149 } else { | 170 } else { |
| 150 // add region for "type" first, so that it is found before "new " | 171 // "new ", excluding last character |
| 151 computer._addRegionForNode(constructorName.type, classElement); | |
| 152 // "new " | |
| 153 computer._addRegion_nodeStart_nodeStart( | 172 computer._addRegion_nodeStart_nodeStart( |
| 154 node, | 173 node, |
| 155 constructorName.type, | 174 constructorName.type, |
| 156 element); | 175 element, |
| 176 excludeLastChar: true); |
| 177 // "ClassName" |
| 178 computer._addRegionForNode(constructorName.type, classElement); |
| 157 // optional ".name" | 179 // optional ".name" |
| 158 if (constructorName.period != null) { | 180 if (constructorName.period != null) { |
| 159 computer._addRegion_tokenStart_nodeEnd( | 181 computer._addRegion_tokenStart_nodeEnd( |
| 160 constructorName.period, | 182 constructorName.period, |
| 161 constructorName, | 183 constructorName, |
| 162 element); | 184 element); |
| 163 } | 185 } |
| 164 } | 186 } |
| 165 } | 187 } |
| 166 return super.visitInstanceCreationExpression(node); | 188 _safelyVisit(node.argumentList); |
| 167 } | 189 } |
| 168 | 190 |
| 169 @override | 191 @override |
| 170 visitPartDirective(PartDirective node) { | 192 visitPartDirective(PartDirective node) { |
| 171 computer._addRegion_tokenStart_nodeEnd( | 193 computer._addRegion_tokenStart_nodeEnd( |
| 172 node.keyword, | 194 node.keyword, |
| 173 node.uri, | 195 node.uri, |
| 174 node.element); | 196 node.element); |
| 175 return super.visitPartDirective(node); | 197 super.visitPartDirective(node); |
| 176 } | 198 } |
| 177 | 199 |
| 178 @override | 200 @override |
| 179 visitPartOfDirective(PartOfDirective node) { | 201 visitPartOfDirective(PartOfDirective node) { |
| 180 computer._addRegion_tokenStart_nodeEnd( | 202 computer._addRegion_tokenStart_nodeEnd( |
| 181 node.keyword, | 203 node.keyword, |
| 182 node.libraryName, | 204 node.libraryName, |
| 183 node.element); | 205 node.element); |
| 184 return super.visitPartOfDirective(node); | 206 super.visitPartOfDirective(node); |
| 185 } | 207 } |
| 186 | 208 |
| 187 @override | 209 @override |
| 188 visitPostfixExpression(PostfixExpression node) { | 210 visitPostfixExpression(PostfixExpression node) { |
| 211 super.visitPostfixExpression(node); |
| 189 computer._addRegionForToken(node.operator, node.bestElement); | 212 computer._addRegionForToken(node.operator, node.bestElement); |
| 190 return super.visitPostfixExpression(node); | |
| 191 } | 213 } |
| 192 | 214 |
| 193 @override | 215 @override |
| 194 visitPrefixExpression(PrefixExpression node) { | 216 visitPrefixExpression(PrefixExpression node) { |
| 195 computer._addRegionForToken(node.operator, node.bestElement); | 217 computer._addRegionForToken(node.operator, node.bestElement); |
| 196 return super.visitPrefixExpression(node); | 218 super.visitPrefixExpression(node); |
| 197 } | 219 } |
| 198 | 220 |
| 199 @override | 221 @override |
| 200 visitSimpleIdentifier(SimpleIdentifier node) { | 222 visitSimpleIdentifier(SimpleIdentifier node) { |
| 201 if (node.parent is ConstructorDeclaration) { | 223 if (node.parent is ConstructorDeclaration) { |
| 202 } else { | 224 return; |
| 203 computer._addRegionForNode(node, node.bestElement); | |
| 204 } | 225 } |
| 205 return super.visitSimpleIdentifier(node); | 226 Element element = node.bestElement; |
| 227 computer._addRegionForNode(node, element); |
| 228 } |
| 229 |
| 230 void _safelyVisit(AstNode node) { |
| 231 if (node != null) { |
| 232 node.accept(this); |
| 233 } |
| 206 } | 234 } |
| 207 } | 235 } |
| OLD | NEW |