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