| 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; | 5 library services.completion.computer.dart.local; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol.dart' as protocol show Element, Ele
mentKind; | 9 import 'package:analysis_server/src/protocol.dart' as protocol show Element, |
| 10 ElementKind; |
| 10 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind; | 11 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind; |
| 11 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 12 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| 12 import 'package:analyzer/src/generated/ast.dart'; | 13 import 'package:analyzer/src/generated/ast.dart'; |
| 13 import 'package:analyzer/src/generated/scanner.dart'; | 14 import 'package:analyzer/src/generated/scanner.dart'; |
| 14 | 15 |
| 15 /** | 16 /** |
| 16 * A computer for calculating `completion.getSuggestions` request results | 17 * A computer for calculating `completion.getSuggestions` request results |
| 17 * for the local library in which the completion is requested. | 18 * for the local library in which the completion is requested. |
| 18 */ | 19 */ |
| 19 class LocalComputer extends DartCompletionComputer { | 20 class LocalComputer extends DartCompletionComputer { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 49 | 50 |
| 50 static final TypeName NO_RETURN_TYPE = new TypeName( | 51 static final TypeName NO_RETURN_TYPE = new TypeName( |
| 51 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), | 52 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), |
| 52 null); | 53 null); |
| 53 | 54 |
| 54 static final TypeName STACKTRACE_TYPE = new TypeName( | 55 static final TypeName STACKTRACE_TYPE = new TypeName( |
| 55 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, 'StackTrace', 0
)), | 56 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, 'StackTrace', 0
)), |
| 56 null); | 57 null); |
| 57 | 58 |
| 58 final DartCompletionRequest request; | 59 final DartCompletionRequest request; |
| 60 bool typesOnly = false; |
| 59 | 61 |
| 60 _LocalVisitor(this.request); | 62 _LocalVisitor(this.request); |
| 61 | 63 |
| 62 @override | 64 @override |
| 63 visitBlock(Block node) { | 65 visitBlock(Block node) { |
| 64 node.statements.forEach((Statement stmt) { | 66 node.statements.forEach((Statement stmt) { |
| 65 if (stmt.offset < request.offset) { | 67 if (stmt.offset < request.offset) { |
| 66 if (stmt is LabeledStatement) { | 68 if (stmt is LabeledStatement) { |
| 67 stmt.labels.forEach((Label label) { | 69 stmt.labels.forEach((Label label) { |
| 68 // _addSuggestion(label.label, CompletionSuggestionKind.LABEL); | 70 // _addSuggestion(label.label, CompletionSuggestionKind.LABEL); |
| 69 }); | 71 }); |
| 70 } else if (stmt is VariableDeclarationStatement) { | 72 } else if (stmt is VariableDeclarationStatement) { |
| 71 var varList = stmt.variables; | 73 var varList = stmt.variables; |
| 72 if (varList != null) { | 74 if (varList != null) { |
| 73 varList.variables.forEach((VariableDeclaration varDecl) { | 75 varList.variables.forEach((VariableDeclaration varDecl) { |
| 74 if (varDecl.end < request.offset) { | 76 if (varDecl.end < request.offset) { |
| 75 _addLocalVarSuggestion(varDecl.name, varList.type); | 77 _addLocalVarSuggestion(varDecl.name, varList.type); |
| 76 } | 78 } |
| 77 }); | 79 }); |
| 78 } | 80 } |
| 79 } | 81 } |
| 80 } | 82 } |
| 81 }); | 83 }); |
| 82 visitNode(node); | 84 visitNode(node); |
| 83 } | 85 } |
| 84 | 86 |
| 85 @override | 87 @override |
| 88 visitCascadeExpression(CascadeExpression node) { |
| 89 Expression target = node.target; |
| 90 // This computer handles the expression |
| 91 // while InvocationComputer handles the cascade selector |
| 92 if (target != null && request.offset <= target.end) { |
| 93 visitNode(node); |
| 94 } |
| 95 } |
| 96 |
| 97 @override |
| 86 visitCatchClause(CatchClause node) { | 98 visitCatchClause(CatchClause node) { |
| 87 _addParamSuggestion(node.exceptionParameter, node.exceptionType); | 99 _addParamSuggestion(node.exceptionParameter, node.exceptionType); |
| 88 CompletionSuggestion suggestion = | 100 _addParamSuggestion(node.stackTraceParameter, STACKTRACE_TYPE); |
| 89 _addParamSuggestion(node.stackTraceParameter, STACKTRACE_TYPE); | |
| 90 visitNode(node); | 101 visitNode(node); |
| 91 } | 102 } |
| 92 | 103 |
| 93 @override | 104 @override |
| 94 visitClassDeclaration(ClassDeclaration node) { | 105 visitClassDeclaration(ClassDeclaration node) { |
| 95 node.members.forEach((ClassMember classMbr) { | 106 node.members.forEach((ClassMember classMbr) { |
| 96 if (classMbr is FieldDeclaration) { | 107 if (classMbr is FieldDeclaration) { |
| 97 _addFieldSuggestions(node, classMbr); | 108 _addFieldSuggestions(node, classMbr); |
| 98 } else if (classMbr is MethodDeclaration) { | 109 } else if (classMbr is MethodDeclaration) { |
| 99 _addMethodSuggestion(node, classMbr); | 110 _addMethodSuggestion(node, classMbr); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 type = loopVar.type; | 163 type = loopVar.type; |
| 153 } else { | 164 } else { |
| 154 id = node.identifier; | 165 id = node.identifier; |
| 155 type = null; | 166 type = null; |
| 156 } | 167 } |
| 157 _addLocalVarSuggestion(id, type); | 168 _addLocalVarSuggestion(id, type); |
| 158 visitNode(node); | 169 visitNode(node); |
| 159 } | 170 } |
| 160 | 171 |
| 161 @override | 172 @override |
| 162 visitPrefixedIdentifier(PrefixedIdentifier node) { | |
| 163 // InvocationComputer adds suggestions for prefixed elements | |
| 164 // but this computer adds suggestions for the prefix itself | |
| 165 SimpleIdentifier prefix = node.prefix; | |
| 166 if (prefix == null || request.offset <= prefix.end) { | |
| 167 visitNode(node); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 @override | |
| 172 visitForStatement(ForStatement node) { | 173 visitForStatement(ForStatement node) { |
| 173 var varList = node.variables; | 174 var varList = node.variables; |
| 174 if (varList != null) { | 175 if (varList != null) { |
| 175 varList.variables.forEach((VariableDeclaration varDecl) { | 176 varList.variables.forEach((VariableDeclaration varDecl) { |
| 176 _addLocalVarSuggestion(varDecl.name, varList.type); | 177 _addLocalVarSuggestion(varDecl.name, varList.type); |
| 177 }); | 178 }); |
| 178 } | 179 } |
| 179 visitNode(node); | 180 visitNode(node); |
| 180 } | 181 } |
| 181 | 182 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 197 _addParamListSuggestions(node.parameters); | 198 _addParamListSuggestions(node.parameters); |
| 198 visitNode(node); | 199 visitNode(node); |
| 199 } | 200 } |
| 200 | 201 |
| 201 @override | 202 @override |
| 202 visitNode(AstNode node) { | 203 visitNode(AstNode node) { |
| 203 node.parent.accept(this); | 204 node.parent.accept(this); |
| 204 } | 205 } |
| 205 | 206 |
| 206 @override | 207 @override |
| 207 visitCascadeExpression(CascadeExpression node) { | 208 visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 208 Expression target = node.target; | 209 // InvocationComputer adds suggestions for prefixed elements |
| 209 // This computer handles the expression | 210 // but this computer adds suggestions for the prefix itself |
| 210 // while InvocationComputer handles the cascade selector | 211 SimpleIdentifier prefix = node.prefix; |
| 211 if (target != null && request.offset <= target.end) { | 212 if (prefix == null || request.offset <= prefix.end) { |
| 212 visitNode(node); | 213 visitNode(node); |
| 213 } | 214 } |
| 214 } | 215 } |
| 215 | 216 |
| 216 @override | 217 @override |
| 218 visitTypeName(TypeName node) { |
| 219 // If suggesting completions within a TypeName node |
| 220 // then limit suggestions to only types |
| 221 typesOnly = true; |
| 222 return visitNode(node); |
| 223 } |
| 224 |
| 225 @override |
| 217 visitVariableDeclaration(VariableDeclaration node) { | 226 visitVariableDeclaration(VariableDeclaration node) { |
| 218 // Do not add suggestions if editing the name in a var declaration | 227 // Do not add suggestions if editing the name in a var declaration |
| 219 SimpleIdentifier name = node.name; | 228 SimpleIdentifier name = node.name; |
| 220 if (name == null || | 229 if (name == null || |
| 221 name.offset < request.offset || | 230 name.offset < request.offset || |
| 222 request.offset > name.end) { | 231 request.offset > name.end) { |
| 223 visitNode(node); | 232 visitNode(node); |
| 224 } | 233 } |
| 225 } | 234 } |
| 226 | 235 |
| 227 void _addClassSuggestion(ClassDeclaration declaration) { | 236 void _addClassSuggestion(ClassDeclaration declaration) { |
| 228 CompletionSuggestion suggestion = | 237 CompletionSuggestion suggestion = |
| 229 _addSuggestion(declaration.name, CompletionSuggestionKind.CLASS, null, n
ull); | 238 _addSuggestion(declaration.name, CompletionSuggestionKind.CLASS, null, n
ull); |
| 230 if (suggestion != null) { | 239 if (suggestion != null) { |
| 231 suggestion.element = _createElement( | 240 suggestion.element = _createElement( |
| 232 protocol.ElementKind.CLASS, | 241 protocol.ElementKind.CLASS, |
| 233 declaration.name, | 242 declaration.name, |
| 234 NO_RETURN_TYPE, | 243 NO_RETURN_TYPE, |
| 235 declaration.isAbstract, | 244 declaration.isAbstract, |
| 236 _isDeprecated(declaration.metadata)); | 245 _isDeprecated(declaration.metadata)); |
| 237 } | 246 } |
| 238 } | 247 } |
| 239 | 248 |
| 240 void _addFieldSuggestions(ClassDeclaration node, FieldDeclaration fieldDecl) { | 249 void _addFieldSuggestions(ClassDeclaration node, FieldDeclaration fieldDecl) { |
| 250 if (typesOnly) { |
| 251 return; |
| 252 } |
| 241 bool isDeprecated = _isDeprecated(fieldDecl.metadata); | 253 bool isDeprecated = _isDeprecated(fieldDecl.metadata); |
| 242 fieldDecl.fields.variables.forEach((VariableDeclaration varDecl) { | 254 fieldDecl.fields.variables.forEach((VariableDeclaration varDecl) { |
| 243 CompletionSuggestion suggestion = _addSuggestion( | 255 CompletionSuggestion suggestion = _addSuggestion( |
| 244 varDecl.name, | 256 varDecl.name, |
| 245 CompletionSuggestionKind.GETTER, | 257 CompletionSuggestionKind.GETTER, |
| 246 fieldDecl.fields.type, | 258 fieldDecl.fields.type, |
| 247 node); | 259 node); |
| 248 if (suggestion != null) { | 260 if (suggestion != null) { |
| 249 suggestion.element = _createElement( | 261 suggestion.element = _createElement( |
| 250 protocol.ElementKind.GETTER, | 262 protocol.ElementKind.GETTER, |
| 251 varDecl.name, | 263 varDecl.name, |
| 252 fieldDecl.fields.type, | 264 fieldDecl.fields.type, |
| 253 false, | 265 false, |
| 254 isDeprecated || _isDeprecated(varDecl.metadata)); | 266 isDeprecated || _isDeprecated(varDecl.metadata)); |
| 255 } | 267 } |
| 256 }); | 268 }); |
| 257 } | 269 } |
| 258 | 270 |
| 259 void _addFunctionSuggestion(FunctionDeclaration declaration) { | 271 void _addFunctionSuggestion(FunctionDeclaration declaration) { |
| 272 if (typesOnly) { |
| 273 return; |
| 274 } |
| 260 CompletionSuggestion suggestion = _addSuggestion( | 275 CompletionSuggestion suggestion = _addSuggestion( |
| 261 declaration.name, | 276 declaration.name, |
| 262 CompletionSuggestionKind.FUNCTION, | 277 CompletionSuggestionKind.FUNCTION, |
| 263 declaration.returnType, | 278 declaration.returnType, |
| 264 null); | 279 null); |
| 265 if (suggestion != null) { | 280 if (suggestion != null) { |
| 266 suggestion.element = _createElement( | 281 suggestion.element = _createElement( |
| 267 protocol.ElementKind.FUNCTION, | 282 protocol.ElementKind.FUNCTION, |
| 268 declaration.name, | 283 declaration.name, |
| 269 declaration.returnType, | 284 declaration.returnType, |
| 270 false, | 285 false, |
| 271 _isDeprecated(declaration.metadata)); | 286 _isDeprecated(declaration.metadata)); |
| 272 } | 287 } |
| 273 } | 288 } |
| 274 | 289 |
| 275 void _addLocalVarSuggestion(SimpleIdentifier id, TypeName returnType) { | 290 void _addLocalVarSuggestion(SimpleIdentifier id, TypeName returnType) { |
| 291 if (typesOnly) { |
| 292 return; |
| 293 } |
| 276 CompletionSuggestion suggestion = | 294 CompletionSuggestion suggestion = |
| 277 _addSuggestion(id, CompletionSuggestionKind.LOCAL_VARIABLE, returnType,
null); | 295 _addSuggestion(id, CompletionSuggestionKind.LOCAL_VARIABLE, returnType,
null); |
| 278 if (suggestion != null) { | 296 if (suggestion != null) { |
| 279 suggestion.element = _createElement( | 297 suggestion.element = _createElement( |
| 280 protocol.ElementKind.LOCAL_VARIABLE, | 298 protocol.ElementKind.LOCAL_VARIABLE, |
| 281 id, | 299 id, |
| 282 returnType, | 300 returnType, |
| 283 false, | 301 false, |
| 284 false); | 302 false); |
| 285 } | 303 } |
| 286 } | 304 } |
| 287 | 305 |
| 288 void _addMethodSuggestion(ClassDeclaration node, MethodDeclaration classMbr) { | 306 void _addMethodSuggestion(ClassDeclaration node, MethodDeclaration classMbr) { |
| 307 if (typesOnly) { |
| 308 return; |
| 309 } |
| 289 protocol.ElementKind kind; | 310 protocol.ElementKind kind; |
| 290 CompletionSuggestionKind csKind; | 311 CompletionSuggestionKind csKind; |
| 291 if (classMbr.isGetter) { | 312 if (classMbr.isGetter) { |
| 292 kind = protocol.ElementKind.GETTER; | 313 kind = protocol.ElementKind.GETTER; |
| 293 csKind = CompletionSuggestionKind.GETTER; | 314 csKind = CompletionSuggestionKind.GETTER; |
| 294 } else if (classMbr.isSetter) { | 315 } else if (classMbr.isSetter) { |
| 295 kind = protocol.ElementKind.SETTER; | 316 kind = protocol.ElementKind.SETTER; |
| 296 csKind = CompletionSuggestionKind.SETTER; | 317 csKind = CompletionSuggestionKind.SETTER; |
| 297 } else { | 318 } else { |
| 298 kind = protocol.ElementKind.METHOD; | 319 kind = protocol.ElementKind.METHOD; |
| 299 csKind = CompletionSuggestionKind.METHOD; | 320 csKind = CompletionSuggestionKind.METHOD; |
| 300 } | 321 } |
| 301 CompletionSuggestion suggestion = | 322 CompletionSuggestion suggestion = |
| 302 _addSuggestion(classMbr.name, csKind, classMbr.returnType, node); | 323 _addSuggestion(classMbr.name, csKind, classMbr.returnType, node); |
| 303 suggestion.element = _createElement( | 324 suggestion.element = _createElement( |
| 304 kind, | 325 kind, |
| 305 classMbr.name, | 326 classMbr.name, |
| 306 classMbr.returnType, | 327 classMbr.returnType, |
| 307 classMbr.isAbstract, | 328 classMbr.isAbstract, |
| 308 _isDeprecated(classMbr.metadata)); | 329 _isDeprecated(classMbr.metadata)); |
| 309 } | 330 } |
| 310 | 331 |
| 311 void _addParamListSuggestions(FormalParameterList paramList) { | 332 void _addParamListSuggestions(FormalParameterList paramList) { |
| 333 if (typesOnly) { |
| 334 return; |
| 335 } |
| 312 if (paramList != null) { | 336 if (paramList != null) { |
| 313 paramList.parameters.forEach((FormalParameter param) { | 337 paramList.parameters.forEach((FormalParameter param) { |
| 314 NormalFormalParameter normalParam; | 338 NormalFormalParameter normalParam; |
| 315 if (param is DefaultFormalParameter) { | 339 if (param is DefaultFormalParameter) { |
| 316 normalParam = param.parameter; | 340 normalParam = param.parameter; |
| 317 } else if (param is NormalFormalParameter) { | 341 } else if (param is NormalFormalParameter) { |
| 318 normalParam = param; | 342 normalParam = param; |
| 319 } | 343 } |
| 320 TypeName type = null; | 344 TypeName type = null; |
| 321 if (normalParam is FieldFormalParameter) { | 345 if (normalParam is FieldFormalParameter) { |
| 322 type = normalParam.type; | 346 type = normalParam.type; |
| 323 } else if (normalParam is FunctionTypedFormalParameter) { | 347 } else if (normalParam is FunctionTypedFormalParameter) { |
| 324 type = normalParam.returnType; | 348 type = normalParam.returnType; |
| 325 } else if (normalParam is SimpleFormalParameter) { | 349 } else if (normalParam is SimpleFormalParameter) { |
| 326 type = normalParam.type; | 350 type = normalParam.type; |
| 327 } | 351 } |
| 328 _addParamSuggestion(param.identifier, type); | 352 _addParamSuggestion(param.identifier, type); |
| 329 }); | 353 }); |
| 330 } | 354 } |
| 331 } | 355 } |
| 332 | 356 |
| 333 CompletionSuggestion _addParamSuggestion(SimpleIdentifier identifier, | 357 void _addParamSuggestion(SimpleIdentifier identifier, TypeName type) { |
| 334 TypeName type) { | 358 if (typesOnly) { |
| 359 return; |
| 360 } |
| 335 CompletionSuggestion suggestion = | 361 CompletionSuggestion suggestion = |
| 336 _addSuggestion(identifier, CompletionSuggestionKind.PARAMETER, type, nul
l); | 362 _addSuggestion(identifier, CompletionSuggestionKind.PARAMETER, type, nul
l); |
| 337 if (suggestion != null) { | 363 if (suggestion != null) { |
| 338 suggestion.element = | 364 suggestion.element = |
| 339 _createElement(protocol.ElementKind.PARAMETER, identifier, type, false
, false); | 365 _createElement(protocol.ElementKind.PARAMETER, identifier, type, false
, false); |
| 340 } | 366 } |
| 341 return suggestion; | |
| 342 } | 367 } |
| 343 | 368 |
| 344 CompletionSuggestion _addSuggestion(SimpleIdentifier id, | 369 CompletionSuggestion _addSuggestion(SimpleIdentifier id, |
| 345 CompletionSuggestionKind kind, TypeName typeName, ClassDeclaration classDe
cl) { | 370 CompletionSuggestionKind kind, TypeName typeName, ClassDeclaration classDe
cl) { |
| 346 if (id != null) { | 371 if (id != null) { |
| 347 String completion = id.name; | 372 String completion = id.name; |
| 348 if (completion != null && completion.length > 0) { | 373 if (completion != null && completion.length > 0) { |
| 349 CompletionSuggestion suggestion = new CompletionSuggestion( | 374 CompletionSuggestion suggestion = new CompletionSuggestion( |
| 350 kind, | 375 kind, |
| 351 CompletionRelevance.DEFAULT, | 376 CompletionRelevance.DEFAULT, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 373 } | 398 } |
| 374 } | 399 } |
| 375 request.suggestions.add(suggestion); | 400 request.suggestions.add(suggestion); |
| 376 return suggestion; | 401 return suggestion; |
| 377 } | 402 } |
| 378 } | 403 } |
| 379 return null; | 404 return null; |
| 380 } | 405 } |
| 381 | 406 |
| 382 void _addTopLevelVarSuggestions(VariableDeclarationList varList) { | 407 void _addTopLevelVarSuggestions(VariableDeclarationList varList) { |
| 408 if (typesOnly) { |
| 409 return; |
| 410 } |
| 383 if (varList != null) { | 411 if (varList != null) { |
| 384 bool isDeprecated = _isDeprecated(varList.metadata); | 412 bool isDeprecated = _isDeprecated(varList.metadata); |
| 385 varList.variables.forEach((VariableDeclaration varDecl) { | 413 varList.variables.forEach((VariableDeclaration varDecl) { |
| 386 CompletionSuggestion suggestion = _addSuggestion( | 414 CompletionSuggestion suggestion = _addSuggestion( |
| 387 varDecl.name, | 415 varDecl.name, |
| 388 CompletionSuggestionKind.TOP_LEVEL_VARIABLE, | 416 CompletionSuggestionKind.TOP_LEVEL_VARIABLE, |
| 389 varList.type, | 417 varList.type, |
| 390 null); | 418 null); |
| 391 if (suggestion != null) { | 419 if (suggestion != null) { |
| 392 suggestion.element = _createElement( | 420 suggestion.element = _createElement( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 if (name == null || name.length <= 0) { | 471 if (name == null || name.length <= 0) { |
| 444 return DYNAMIC; | 472 return DYNAMIC; |
| 445 } | 473 } |
| 446 TypeArgumentList typeArgs = type.typeArguments; | 474 TypeArgumentList typeArgs = type.typeArguments; |
| 447 if (typeArgs != null) { | 475 if (typeArgs != null) { |
| 448 //TODO (danrubel) include type arguments | 476 //TODO (danrubel) include type arguments |
| 449 } | 477 } |
| 450 return name; | 478 return name; |
| 451 } | 479 } |
| 452 } | 480 } |
| OLD | NEW |