| 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.invocation; | 5 library services.completion.computer.dart.invocation; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 9 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| 10 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; | 10 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
; |
| 11 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/scanner.dart'; | 13 import 'package:analyzer/src/generated/scanner.dart'; |
| 14 | 14 |
| 15 import '../../protocol_server.dart' show CompletionSuggestionKind; | 15 import '../../protocol_server.dart' show CompletionSuggestionKind; |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * A computer for calculating invocation / access suggestions | 18 * A computer for calculating invocation / access suggestions |
| 19 * `completion.getSuggestions` request results. | 19 * `completion.getSuggestions` request results. |
| 20 */ | 20 */ |
| 21 class InvocationComputer extends DartCompletionComputer { | 21 class InvocationComputer extends DartCompletionComputer { |
| 22 SuggestionBuilder builder; |
| 22 | 23 |
| 23 @override | 24 @override |
| 24 bool computeFast(DartCompletionRequest request) { | 25 bool computeFast(DartCompletionRequest request) { |
| 25 // TODO: implement computeFast | 26 builder = request.node.accept(new _InvocationAstVisitor(request)); |
| 27 if (builder != null) { |
| 28 return builder.computeFast(request.node); |
| 29 } |
| 30 return true; |
| 31 } |
| 32 |
| 33 @override |
| 34 Future<bool> computeFull(DartCompletionRequest request) { |
| 35 if (builder != null) { |
| 36 return builder.computeFull(request.node); |
| 37 } |
| 38 return new Future.value(false); |
| 39 } |
| 40 } |
| 41 |
| 42 class _ExpressionSuggestionBuilder implements SuggestionBuilder { |
| 43 final DartCompletionRequest request; |
| 44 |
| 45 _ExpressionSuggestionBuilder(this.request); |
| 46 |
| 47 @override |
| 48 bool computeFast(AstNode node) { |
| 26 return false; | 49 return false; |
| 27 } | 50 } |
| 28 | 51 |
| 29 @override | 52 @override |
| 30 Future<bool> computeFull(DartCompletionRequest request) { | 53 Future<bool> computeFull(AstNode node) { |
| 31 return request.node.accept(new _InvocationAstVisitor(request)); | 54 if (node is SimpleIdentifier) { |
| 32 } | 55 node = node.parent; |
| 33 } | |
| 34 | |
| 35 /** | |
| 36 * An [AstNode] vistor for determining the appropriate invocation/access | |
| 37 * suggestions based upon the node in which the completion is requested. | |
| 38 */ | |
| 39 class _InvocationAstVisitor extends GeneralizingAstVisitor<Future<bool>> { | |
| 40 final DartCompletionRequest request; | |
| 41 | |
| 42 _InvocationAstVisitor(this.request); | |
| 43 | |
| 44 @override | |
| 45 Future<bool> visitConstructorName(ConstructorName node) { | |
| 46 // SimpleIdentifier PrefixedIdentifier TypeName ConstructorName | |
| 47 Token period = node.period; | |
| 48 if (period != null && period.end <= request.offset) { | |
| 49 return _addNamedConstructorSuggestions(node); | |
| 50 } | 56 } |
| 51 return super.visitConstructorName(node); | 57 if (node is MethodInvocation) { |
| 52 } | 58 node = node.realTarget; |
| 53 | 59 } else if (node is PropertyAccess) { |
| 54 @override | 60 node = node.realTarget; |
| 55 Future<bool> visitMethodInvocation(MethodInvocation node) { | |
| 56 Token period = node.period; | |
| 57 if (period == null || period.offset < request.offset) { | |
| 58 _addExpressionSuggestions(node.target); | |
| 59 } | 61 } |
| 60 return new Future.value(false); | 62 if (node is Expression) { |
| 61 } | 63 DartType type = node.bestType; |
| 62 | |
| 63 @override | |
| 64 Future<bool> visitNode(AstNode node) { | |
| 65 return new Future.value(false); | |
| 66 } | |
| 67 | |
| 68 @override | |
| 69 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) { | |
| 70 if (request.offset > node.period.offset) { | |
| 71 SimpleIdentifier prefix = node.prefix; | |
| 72 if (prefix != null) { | |
| 73 return _addElementSuggestions(prefix.bestElement); | |
| 74 } | |
| 75 } | |
| 76 return super.visitPrefixedIdentifier(node); | |
| 77 } | |
| 78 | |
| 79 @override | |
| 80 Future<bool> visitPropertyAccess(PropertyAccess node) { | |
| 81 Token operator = node.operator; | |
| 82 if (operator != null && operator.offset < request.offset) { | |
| 83 return _addExpressionSuggestions(node.realTarget); | |
| 84 } | |
| 85 return super.visitPropertyAccess(node); | |
| 86 } | |
| 87 | |
| 88 @override | |
| 89 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) { | |
| 90 return node.parent.accept(this); | |
| 91 } | |
| 92 | |
| 93 /** | |
| 94 * Add invocation / access suggestions for the given element. | |
| 95 */ | |
| 96 Future<bool> _addElementSuggestions(Element element) { | |
| 97 if (element != null) { | |
| 98 return element.accept(new _InvocationElementVisitor(request)); | |
| 99 } | |
| 100 return new Future.value(false); | |
| 101 } | |
| 102 | |
| 103 /** | |
| 104 * Add invocation / access suggestions for the given expression. | |
| 105 */ | |
| 106 Future<bool> _addExpressionSuggestions(Expression target) { | |
| 107 if (target != null) { | |
| 108 DartType type = target.bestType; | |
| 109 if (type != null) { | 64 if (type != null) { |
| 110 ClassElementSuggestionBuilder.suggestionsFor(request, type.element); | 65 ClassElementSuggestionBuilder.suggestionsFor(request, type.element); |
| 111 return new Future.value(true); | 66 return new Future.value(true); |
| 112 } | 67 } |
| 113 } | 68 } |
| 114 return new Future.value(false); | 69 return new Future.value(false); |
| 115 } | 70 } |
| 116 | |
| 117 Future<bool> _addNamedConstructorSuggestions(ConstructorName node) { | |
| 118 TypeName typeName = node.type; | |
| 119 if (typeName != null) { | |
| 120 DartType type = typeName.type; | |
| 121 if (type != null) { | |
| 122 NamedConstructorSuggestionBuilder.suggestionsFor(request, type.element); | |
| 123 return new Future.value(true); | |
| 124 } | |
| 125 } | |
| 126 return new Future.value(false); | |
| 127 } | |
| 128 } | 71 } |
| 129 | 72 |
| 130 /** | 73 /** |
| 74 * An [AstNode] vistor for determining which suggestion builder |
| 75 * should be used to build invocation/access suggestions. |
| 76 */ |
| 77 class _InvocationAstVisitor extends GeneralizingAstVisitor<SuggestionBuilder> { |
| 78 final DartCompletionRequest request; |
| 79 |
| 80 _InvocationAstVisitor(this.request); |
| 81 |
| 82 @override |
| 83 SuggestionBuilder visitMethodInvocation(MethodInvocation node) { |
| 84 Token period = node.period; |
| 85 if (period == null || period.offset < request.offset) { |
| 86 return new _ExpressionSuggestionBuilder(request); |
| 87 } |
| 88 return null; |
| 89 } |
| 90 |
| 91 @override |
| 92 SuggestionBuilder visitNode(AstNode node) { |
| 93 return null; |
| 94 } |
| 95 |
| 96 @override |
| 97 SuggestionBuilder visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 98 // some PrefixedIdentifier nodes are transformed into |
| 99 // ConstructorName nodes during the resolution process. |
| 100 Token period = node.period; |
| 101 if (request.offset > period.offset) { |
| 102 SimpleIdentifier prefix = node.prefix; |
| 103 if (prefix != null) { |
| 104 return new _PrefixedIdentifierSuggestionBuilder(request); |
| 105 } |
| 106 } |
| 107 return null; |
| 108 } |
| 109 |
| 110 @override |
| 111 SuggestionBuilder visitPropertyAccess(PropertyAccess node) { |
| 112 Token operator = node.operator; |
| 113 if (operator != null && operator.offset < request.offset) { |
| 114 return new _ExpressionSuggestionBuilder(request); |
| 115 } |
| 116 return null; |
| 117 } |
| 118 |
| 119 @override |
| 120 SuggestionBuilder visitSimpleIdentifier(SimpleIdentifier node) { |
| 121 return node.parent.accept(this); |
| 122 } |
| 123 } |
| 124 |
| 125 /** |
| 131 * An [Element] visitor for determining the appropriate invocation/access | 126 * An [Element] visitor for determining the appropriate invocation/access |
| 132 * suggestions based upon the element for which the completion is requested. | 127 * suggestions based upon the element for which the completion is requested. |
| 133 */ | 128 */ |
| 134 class _InvocationElementVisitor extends GeneralizingElementVisitor<Future<bool>> | 129 class _PrefixedIdentifierSuggestionBuilder extends |
| 135 { | 130 GeneralizingElementVisitor<Future<bool>> implements SuggestionBuilder { |
| 131 |
| 136 final DartCompletionRequest request; | 132 final DartCompletionRequest request; |
| 137 | 133 |
| 138 _InvocationElementVisitor(this.request); | 134 _PrefixedIdentifierSuggestionBuilder(this.request); |
| 135 |
| 136 @override |
| 137 bool computeFast(AstNode node) { |
| 138 return false; |
| 139 } |
| 140 |
| 141 @override |
| 142 Future<bool> computeFull(AstNode node) { |
| 143 if (node is SimpleIdentifier) { |
| 144 node = node.parent; |
| 145 } |
| 146 if (node is ConstructorName) { |
| 147 // some PrefixedIdentifier nodes are transformed into |
| 148 // ConstructorName nodes during the resolution process. |
| 149 return new NamedConstructorSuggestionBuilder(request).computeFull(node); |
| 150 } |
| 151 if (node is PrefixedIdentifier) { |
| 152 SimpleIdentifier prefix = node.prefix; |
| 153 if (prefix != null) { |
| 154 Element element = prefix.bestElement; |
| 155 if (element != null) { |
| 156 return element.accept(this); |
| 157 } |
| 158 } |
| 159 } |
| 160 return new Future.value(false); |
| 161 } |
| 139 | 162 |
| 140 @override | 163 @override |
| 141 Future<bool> visitClassElement(ClassElement element) { | 164 Future<bool> visitClassElement(ClassElement element) { |
| 142 if (element != null) { | 165 if (element != null) { |
| 143 InterfaceType type = element.type; | 166 InterfaceType type = element.type; |
| 144 if (type != null) { | 167 if (type != null) { |
| 145 ClassElementSuggestionBuilder.suggestionsFor( | 168 ClassElementSuggestionBuilder.suggestionsFor( |
| 146 request, | 169 request, |
| 147 type.element, | 170 type.element, |
| 148 staticOnly: true); | 171 staticOnly: true); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 | 220 |
| 198 @override | 221 @override |
| 199 Future<bool> visitVariableElement(VariableElement element) { | 222 Future<bool> visitVariableElement(VariableElement element) { |
| 200 DartType type = element.type; | 223 DartType type = element.type; |
| 201 if (type != null) { | 224 if (type != null) { |
| 202 ClassElementSuggestionBuilder.suggestionsFor(request, type.element); | 225 ClassElementSuggestionBuilder.suggestionsFor(request, type.element); |
| 203 } | 226 } |
| 204 return new Future.value(true); | 227 return new Future.value(true); |
| 205 } | 228 } |
| 206 } | 229 } |
| OLD | NEW |