| 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.completion.computer.dart.local.Declaration.visitor; | 5 library services.completion.computer.dart.local.Declaration.visitor; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; | 7 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; |
| 8 import 'package:analyzer/src/generated/ast.dart'; | 8 import 'package:analyzer/src/generated/ast.dart'; |
| 9 import 'package:analyzer/src/generated/scanner.dart'; | 9 import 'package:analyzer/src/generated/scanner.dart'; |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * `LocalDeclarationCollector` visits an [AstNode] and its parent recursively | 12 * `LocalDeclarationCollector` visits an [AstNode] and its parent recursively |
| 13 * along with any declarations in those nodes. Setting the [finished] flag | 13 * along with any declarations in those nodes. Consumers typically call [visit] |
| 14 * `true` will prevent further recursion. | 14 * which catches the exception thrown by [finished()]. |
| 15 */ | 15 */ |
| 16 abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor<bool> { | 16 abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor { |
| 17 | 17 |
| 18 static final TypeName STACKTRACE_TYPE = new TypeName( | 18 static final TypeName STACKTRACE_TYPE = new TypeName( |
| 19 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, 'StackTrace', 0
)), | 19 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, 'StackTrace', 0
)), |
| 20 null); | 20 null); |
| 21 | 21 |
| 22 final int offset; | 22 final int offset; |
| 23 bool finished = false; | |
| 24 | 23 |
| 25 LocalDeclarationVisitor(this.offset); | 24 LocalDeclarationVisitor(this.offset); |
| 26 | 25 |
| 27 void declaredClass(ClassDeclaration declaration); | 26 void declaredClass(ClassDeclaration declaration); |
| 28 | 27 |
| 29 void declaredClassTypeAlias(ClassTypeAlias declaration); | 28 void declaredClassTypeAlias(ClassTypeAlias declaration); |
| 30 | 29 |
| 31 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl); | 30 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl); |
| 32 | 31 |
| 33 void declaredFunction(FunctionDeclaration declaration); | 32 void declaredFunction(FunctionDeclaration declaration); |
| 34 | 33 |
| 35 void declaredFunctionTypeAlias(FunctionTypeAlias declaration); | 34 void declaredFunctionTypeAlias(FunctionTypeAlias declaration); |
| 36 | 35 |
| 37 void declaredLabel(Label label, bool isCaseLabel); | 36 void declaredLabel(Label label, bool isCaseLabel); |
| 38 | 37 |
| 39 void declaredLocalVar(SimpleIdentifier name, TypeName type); | 38 void declaredLocalVar(SimpleIdentifier name, TypeName type); |
| 40 | 39 |
| 41 void declaredMethod(MethodDeclaration declaration); | 40 void declaredMethod(MethodDeclaration declaration); |
| 42 | 41 |
| 43 void declaredParam(SimpleIdentifier name, TypeName type); | 42 void declaredParam(SimpleIdentifier name, TypeName type); |
| 44 | 43 |
| 45 void declaredTopLevelVar(VariableDeclarationList varList, | 44 void declaredTopLevelVar(VariableDeclarationList varList, |
| 46 VariableDeclaration varDecl); | 45 VariableDeclaration varDecl); |
| 47 | 46 |
| 47 /** |
| 48 * Throw an exception indicating that [LocalDeclarationVisitor] should |
| 49 * stop visiting. This is caught in [visit] which then exits normally. |
| 50 */ |
| 51 void finished() { |
| 52 throw new _LocalDeclarationVisitorFinished(); |
| 53 } |
| 54 |
| 55 /** |
| 56 * Visit the given [AstNode] and its parent recursively along with any |
| 57 * declarations in those nodes. Return `true` if [finished] is called |
| 58 * while visiting, else `false`. |
| 59 */ |
| 60 bool visit(AstNode node) { |
| 61 try { |
| 62 node.accept(this); |
| 63 return false; |
| 64 } on _LocalDeclarationVisitorFinished { |
| 65 return true; |
| 66 } |
| 67 } |
| 68 |
| 48 @override | 69 @override |
| 49 bool visitBlock(Block node) { | 70 void visitBlock(Block node) { |
| 50 for (Statement stmt in node.statements) { | 71 for (Statement stmt in node.statements) { |
| 51 if (stmt.offset < offset) { | 72 if (stmt.offset < offset) { |
| 52 if (stmt is VariableDeclarationStatement) { | 73 if (stmt is VariableDeclarationStatement) { |
| 53 VariableDeclarationList varList = stmt.variables; | 74 VariableDeclarationList varList = stmt.variables; |
| 54 if (varList != null) { | 75 if (varList != null) { |
| 55 for (VariableDeclaration varDecl in varList.variables) { | 76 for (VariableDeclaration varDecl in varList.variables) { |
| 56 if (varDecl.end < offset) { | 77 if (varDecl.end < offset) { |
| 57 declaredLocalVar(varDecl.name, varList.type); | 78 declaredLocalVar(varDecl.name, varList.type); |
| 58 } | 79 } |
| 59 }; | 80 } |
| 60 } | 81 } |
| 61 } else if (stmt is FunctionDeclarationStatement) { | 82 } else if (stmt is FunctionDeclarationStatement) { |
| 62 FunctionDeclaration declaration = stmt.functionDeclaration; | 83 FunctionDeclaration declaration = stmt.functionDeclaration; |
| 63 if (declaration != null && declaration.offset < offset) { | 84 if (declaration != null && declaration.offset < offset) { |
| 64 SimpleIdentifier id = declaration.name; | 85 SimpleIdentifier id = declaration.name; |
| 65 if (id != null) { | 86 if (id != null) { |
| 66 String name = id.name; | 87 String name = id.name; |
| 67 if (name != null && name.length > 0) { | 88 if (name != null && name.length > 0) { |
| 68 declaredFunction(declaration); | 89 declaredFunction(declaration); |
| 69 } | 90 } |
| 70 } | 91 } |
| 71 } | 92 } |
| 72 } | 93 } |
| 73 } | 94 } |
| 74 }; | 95 } |
| 75 return visitNode(node); | 96 visitNode(node); |
| 76 } | 97 } |
| 77 | 98 |
| 78 @override | 99 @override |
| 79 bool visitCatchClause(CatchClause node) { | 100 void visitCatchClause(CatchClause node) { |
| 80 SimpleIdentifier param = node.exceptionParameter; | 101 SimpleIdentifier param = node.exceptionParameter; |
| 81 if (param != null) { | 102 if (param != null) { |
| 82 declaredParam(param, node.exceptionType); | 103 declaredParam(param, node.exceptionType); |
| 83 } | 104 } |
| 84 param = node.stackTraceParameter; | 105 param = node.stackTraceParameter; |
| 85 if (param != null) { | 106 if (param != null) { |
| 86 declaredParam(param, STACKTRACE_TYPE); | 107 declaredParam(param, STACKTRACE_TYPE); |
| 87 } | 108 } |
| 88 return visitNode(node); | 109 visitNode(node); |
| 89 } | 110 } |
| 90 | 111 |
| 91 @override | 112 @override |
| 92 bool visitClassDeclaration(ClassDeclaration node) { | 113 void visitClassDeclaration(ClassDeclaration node) { |
| 93 _visitClassDeclarationMembers(node); | 114 _visitClassDeclarationMembers(node); |
| 94 visitInheritedTypes(node, (ClassDeclaration classNode) { | 115 visitInheritedTypes(node, (ClassDeclaration classNode) { |
| 95 _visitClassDeclarationMembers(classNode); | 116 _visitClassDeclarationMembers(classNode); |
| 96 }, (String typeName) { | 117 }, (String typeName) { |
| 97 // ignored | 118 // ignored |
| 98 }); | 119 }); |
| 99 return visitNode(node); | 120 visitNode(node); |
| 100 } | 121 } |
| 101 | 122 |
| 102 @override | 123 @override |
| 103 bool visitCompilationUnit(CompilationUnit node) { | 124 void visitCompilationUnit(CompilationUnit node) { |
| 104 node.declarations.forEach((Declaration declaration) { | 125 node.declarations.forEach((Declaration declaration) { |
| 105 if (declaration is ClassDeclaration) { | 126 if (declaration is ClassDeclaration) { |
| 106 declaredClass(declaration); | 127 declaredClass(declaration); |
| 107 } else if (declaration is EnumDeclaration) { | 128 } else if (declaration is EnumDeclaration) { |
| 108 // TODO (danrubel) enum support | 129 // TODO (danrubel) enum support |
| 109 // declaredEnum(........) | 130 // declaredEnum(........) |
| 110 } else if (declaration is FunctionDeclaration) { | 131 } else if (declaration is FunctionDeclaration) { |
| 111 declaredFunction(declaration); | 132 declaredFunction(declaration); |
| 112 } else if (declaration is TopLevelVariableDeclaration) { | 133 } else if (declaration is TopLevelVariableDeclaration) { |
| 113 var varList = declaration.variables; | 134 var varList = declaration.variables; |
| 114 if (varList != null) { | 135 if (varList != null) { |
| 115 varList.variables.forEach((VariableDeclaration varDecl) { | 136 varList.variables.forEach((VariableDeclaration varDecl) { |
| 116 declaredTopLevelVar(varList, varDecl); | 137 declaredTopLevelVar(varList, varDecl); |
| 117 }); | 138 }); |
| 118 } | 139 } |
| 119 } else if (declaration is ClassTypeAlias) { | 140 } else if (declaration is ClassTypeAlias) { |
| 120 declaredClassTypeAlias(declaration); | 141 declaredClassTypeAlias(declaration); |
| 121 } else if (declaration is FunctionTypeAlias) { | 142 } else if (declaration is FunctionTypeAlias) { |
| 122 declaredFunctionTypeAlias(declaration); | 143 declaredFunctionTypeAlias(declaration); |
| 123 } | 144 } |
| 124 }); | 145 }); |
| 125 return finished; | |
| 126 } | 146 } |
| 127 | 147 |
| 128 @override | 148 @override |
| 129 bool visitForEachStatement(ForEachStatement node) { | 149 void visitForEachStatement(ForEachStatement node) { |
| 130 SimpleIdentifier id; | 150 SimpleIdentifier id; |
| 131 TypeName type; | 151 TypeName type; |
| 132 DeclaredIdentifier loopVar = node.loopVariable; | 152 DeclaredIdentifier loopVar = node.loopVariable; |
| 133 if (loopVar != null) { | 153 if (loopVar != null) { |
| 134 id = loopVar.identifier; | 154 id = loopVar.identifier; |
| 135 type = loopVar.type; | 155 type = loopVar.type; |
| 136 } else { | 156 } else { |
| 137 id = node.identifier; | 157 id = node.identifier; |
| 138 type = null; | 158 type = null; |
| 139 } | 159 } |
| 140 declaredLocalVar(id, type); | 160 declaredLocalVar(id, type); |
| 141 return visitNode(node); | 161 visitNode(node); |
| 142 } | 162 } |
| 143 | 163 |
| 144 @override | 164 @override |
| 145 bool visitForStatement(ForStatement node) { | 165 void visitForStatement(ForStatement node) { |
| 146 VariableDeclarationList varList = node.variables; | 166 VariableDeclarationList varList = node.variables; |
| 147 if (varList != null) { | 167 if (varList != null) { |
| 148 varList.variables.forEach((VariableDeclaration varDecl) { | 168 varList.variables.forEach((VariableDeclaration varDecl) { |
| 149 declaredLocalVar(varDecl.name, varList.type); | 169 declaredLocalVar(varDecl.name, varList.type); |
| 150 }); | 170 }); |
| 151 } | 171 } |
| 152 return visitNode(node); | 172 visitNode(node); |
| 153 } | 173 } |
| 154 | 174 |
| 155 @override | 175 @override |
| 156 bool visitFunctionDeclaration(FunctionDeclaration node) { | 176 void visitFunctionDeclaration(FunctionDeclaration node) { |
| 157 // declaredFunction is called by the compilation unit containing it | 177 // declaredFunction is called by the compilation unit containing it |
| 158 return visitNode(node); | 178 visitNode(node); |
| 159 } | 179 } |
| 160 | 180 |
| 161 @override | 181 @override |
| 162 bool visitFunctionExpression(FunctionExpression node) { | 182 void visitFunctionExpression(FunctionExpression node) { |
| 163 _visitParamList(node.parameters); | 183 _visitParamList(node.parameters); |
| 164 return visitNode(node); | 184 visitNode(node); |
| 165 } | 185 } |
| 166 | 186 |
| 167 @override | 187 @override |
| 168 bool visitInterpolationExpression(InterpolationExpression node) { | 188 void visitInterpolationExpression(InterpolationExpression node) { |
| 169 return visitNode(node); | 189 visitNode(node); |
| 170 } | 190 } |
| 171 | 191 |
| 172 @override | 192 @override |
| 173 bool visitSwitchStatement(SwitchStatement node) { | 193 void visitLabeledStatement(LabeledStatement node) { |
| 194 for (Label label in node.labels) { |
| 195 declaredLabel(label, false); |
| 196 } |
| 197 visitNode(node); |
| 198 } |
| 199 |
| 200 @override |
| 201 void visitMethodDeclaration(MethodDeclaration node) { |
| 202 _visitParamList(node.parameters); |
| 203 visitNode(node); |
| 204 } |
| 205 |
| 206 @override |
| 207 void visitNode(AstNode node) { |
| 208 node.parent.accept(this); |
| 209 } |
| 210 |
| 211 @override |
| 212 void visitStringInterpolation(StringInterpolation node) { |
| 213 visitNode(node); |
| 214 } |
| 215 |
| 216 @override |
| 217 void visitSwitchStatement(SwitchStatement node) { |
| 174 for (SwitchMember member in node.members) { | 218 for (SwitchMember member in node.members) { |
| 175 for (Label label in member.labels) { | 219 for (Label label in member.labels) { |
| 176 declaredLabel(label, true); | 220 declaredLabel(label, true); |
| 177 } | 221 } |
| 178 } | 222 } |
| 179 return visitNode(node); | 223 visitNode(node); |
| 180 } | |
| 181 | |
| 182 @override | |
| 183 bool visitLabeledStatement(LabeledStatement node) { | |
| 184 for (Label label in node.labels) { | |
| 185 declaredLabel(label, false); | |
| 186 } | |
| 187 return visitNode(node); | |
| 188 } | |
| 189 | |
| 190 @override | |
| 191 bool visitMethodDeclaration(MethodDeclaration node) { | |
| 192 _visitParamList(node.parameters); | |
| 193 return visitNode(node); | |
| 194 } | |
| 195 | |
| 196 @override | |
| 197 bool visitNode(AstNode node) { | |
| 198 if (finished) { | |
| 199 return true; | |
| 200 } | |
| 201 return node.parent.accept(this); | |
| 202 } | |
| 203 | |
| 204 @override | |
| 205 bool visitStringInterpolation(StringInterpolation node) { | |
| 206 return visitNode(node); | |
| 207 } | 224 } |
| 208 | 225 |
| 209 void _visitClassDeclarationMembers(ClassDeclaration node) { | 226 void _visitClassDeclarationMembers(ClassDeclaration node) { |
| 210 node.members.forEach((ClassMember member) { | 227 node.members.forEach((ClassMember member) { |
| 211 if (member is FieldDeclaration) { | 228 if (member is FieldDeclaration) { |
| 212 member.fields.variables.forEach((VariableDeclaration varDecl) { | 229 member.fields.variables.forEach((VariableDeclaration varDecl) { |
| 213 declaredField(member, varDecl); | 230 declaredField(member, varDecl); |
| 214 }); | 231 }); |
| 215 } else if (member is MethodDeclaration) { | 232 } else if (member is MethodDeclaration) { |
| 216 declaredMethod(member); | 233 declaredMethod(member); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 234 type = normalParam.returnType; | 251 type = normalParam.returnType; |
| 235 } else if (normalParam is SimpleFormalParameter) { | 252 } else if (normalParam is SimpleFormalParameter) { |
| 236 type = normalParam.type; | 253 type = normalParam.type; |
| 237 } | 254 } |
| 238 SimpleIdentifier name = param.identifier; | 255 SimpleIdentifier name = param.identifier; |
| 239 declaredParam(name, type); | 256 declaredParam(name, type); |
| 240 }); | 257 }); |
| 241 } | 258 } |
| 242 } | 259 } |
| 243 } | 260 } |
| 261 |
| 262 /** |
| 263 * Internal exception used to indicate that [LocalDeclarationVisitor] |
| 264 * should stop visiting. |
| 265 */ |
| 266 class _LocalDeclarationVisitorFinished { |
| 267 } |
| OLD | NEW |