| 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.keyword; | 5 library services.completion.computer.dart.keyword; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol.dart'; | 9 import 'package:analysis_server/src/protocol.dart'; |
| 10 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 10 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 return new Future.value(false); | 28 return new Future.value(false); |
| 29 } | 29 } |
| 30 } | 30 } |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * A vistor for generating keyword suggestions. | 33 * A vistor for generating keyword suggestions. |
| 34 */ | 34 */ |
| 35 class _KeywordVisitor extends GeneralizingAstVisitor { | 35 class _KeywordVisitor extends GeneralizingAstVisitor { |
| 36 final DartCompletionRequest request; | 36 final DartCompletionRequest request; |
| 37 | 37 |
| 38 /** |
| 39 * The identifier visited or `null` if not visited. |
| 40 */ |
| 41 SimpleIdentifier identifier; |
| 42 |
| 38 _KeywordVisitor(this.request); | 43 _KeywordVisitor(this.request); |
| 39 | 44 |
| 40 @override | 45 @override |
| 41 visitBlock(Block node) { | 46 visitBlock(Block node) { |
| 42 if (_isOffsetAfterNode(node)) { | 47 _addSuggestions( |
| 43 node.parent.accept(this); | 48 [ |
| 44 } else { | 49 Keyword.ASSERT, |
| 45 _addSuggestions( | 50 Keyword.CASE, |
| 46 [ | 51 Keyword.CONTINUE, |
| 47 Keyword.ASSERT, | 52 Keyword.DO, |
| 48 Keyword.CASE, | 53 Keyword.FACTORY, |
| 49 Keyword.CONTINUE, | 54 Keyword.FINAL, |
| 50 Keyword.DO, | 55 Keyword.FOR, |
| 51 Keyword.FACTORY, | 56 Keyword.IF, |
| 52 Keyword.FINAL, | 57 Keyword.NEW, |
| 53 Keyword.FOR, | 58 Keyword.RETHROW, |
| 54 Keyword.IF, | 59 Keyword.RETURN, |
| 55 Keyword.NEW, | 60 Keyword.SUPER, |
| 56 Keyword.RETHROW, | 61 Keyword.SWITCH, |
| 57 Keyword.RETURN, | 62 Keyword.THIS, |
| 58 Keyword.SUPER, | 63 Keyword.THROW, |
| 59 Keyword.SWITCH, | 64 Keyword.TRY, |
| 60 Keyword.THIS, | 65 Keyword.VAR, |
| 61 Keyword.THROW, | 66 Keyword.VOID, |
| 62 Keyword.TRY, | 67 Keyword.WHILE]); |
| 63 Keyword.VAR, | |
| 64 Keyword.VOID, | |
| 65 Keyword.WHILE]); | |
| 66 } | |
| 67 } | 68 } |
| 68 | 69 |
| 69 @override | 70 @override |
| 70 visitClassDeclaration(ClassDeclaration node) { | 71 visitClassDeclaration(ClassDeclaration node) { |
| 72 // Don't suggest class name |
| 73 if (node.name == identifier) { |
| 74 return; |
| 75 } |
| 71 // Inside the class declaration { } | 76 // Inside the class declaration { } |
| 72 if (request.offset > node.leftBracket.offset) { | 77 if (request.offset > node.leftBracket.offset) { |
| 73 _addSuggestions( | 78 _addSuggestions( |
| 74 [ | 79 [ |
| 75 Keyword.CONST, | 80 Keyword.CONST, |
| 76 Keyword.DYNAMIC, | 81 Keyword.DYNAMIC, |
| 77 Keyword.FACTORY, | 82 Keyword.FACTORY, |
| 78 Keyword.FINAL, | 83 Keyword.FINAL, |
| 79 Keyword.GET, | 84 Keyword.GET, |
| 80 Keyword.OPERATOR, | 85 Keyword.OPERATOR, |
| 81 Keyword.SET, | 86 Keyword.SET, |
| 82 Keyword.STATIC, | 87 Keyword.STATIC, |
| 83 Keyword.VAR, | 88 Keyword.VAR, |
| 84 Keyword.VOID]); | 89 Keyword.VOID]); |
| 85 return; | 90 return; |
| 86 } | 91 } |
| 87 // Very simplistic suggestion because analyzer will warn if | 92 _addClassDeclarationKeywords(node); |
| 88 // the extends / with / implements keywords are out of order | |
| 89 if (node.extendsClause == null) { | |
| 90 _addSuggestion(Keyword.EXTENDS, COMPLETION_RELEVANCE_HIGH); | |
| 91 } else if (node.withClause == null) { | |
| 92 _addSuggestion(Keyword.WITH, COMPLETION_RELEVANCE_HIGH); | |
| 93 } | |
| 94 if (node.implementsClause == null) { | |
| 95 _addSuggestion(Keyword.IMPLEMENTS, COMPLETION_RELEVANCE_HIGH); | |
| 96 } | |
| 97 } | 93 } |
| 98 | 94 |
| 99 @override | 95 @override |
| 100 visitCompilationUnit(CompilationUnit node) { | 96 visitCompilationUnit(CompilationUnit node) { |
| 101 Directive firstDirective; | 97 Directive firstDirective; |
| 102 int endOfDirectives = 0; | 98 int endOfDirectives = 0; |
| 103 if (node.directives.length > 0) { | 99 if (node.directives.length > 0) { |
| 104 firstDirective = node.directives[0]; | 100 firstDirective = node.directives[0]; |
| 105 endOfDirectives = node.directives.last.end - 1; | 101 endOfDirectives = node.directives.last.end - 1; |
| 106 } | 102 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } | 143 } |
| 148 | 144 |
| 149 @override | 145 @override |
| 150 visitNode(AstNode node) { | 146 visitNode(AstNode node) { |
| 151 if (_isOffsetAfterNode(node)) { | 147 if (_isOffsetAfterNode(node)) { |
| 152 node.parent.accept(this); | 148 node.parent.accept(this); |
| 153 } | 149 } |
| 154 } | 150 } |
| 155 | 151 |
| 156 visitSimpleIdentifier(SimpleIdentifier node) { | 152 visitSimpleIdentifier(SimpleIdentifier node) { |
| 157 AstNode parent = node.getAncestor((n) => n is TopLevelVariableDeclaration); | 153 identifier = node; |
| 158 if (parent is TopLevelVariableDeclaration) { | 154 node.parent.accept(this); |
| 159 if (parent.variables != null && | 155 } |
| 160 parent.variables.type != null && | 156 |
| 161 parent.variables.type.name == node) { | 157 void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 162 AstNode unit = node.getAncestor((n) => n is CompilationUnit); | 158 if (identifier != null && node.beginToken == identifier.beginToken) { |
| 163 if (unit is CompilationUnit) { | 159 AstNode unit = node.parent; |
| 164 visitCompilationUnit(unit); | 160 if (unit is CompilationUnit) { |
| 161 CompilationUnitMember previous; |
| 162 for (CompilationUnitMember member in unit.declarations) { |
| 163 if (member == node && previous is ClassDeclaration) { |
| 164 if (previous.endToken.isSynthetic) { |
| 165 // Partial keywords (simple identifirs) that are part of a |
| 166 // class declaration can be parsed |
| 167 // as a TypeName in a TopLevelVariableDeclaration |
| 168 _addClassDeclarationKeywords(previous); |
| 169 return; |
| 170 } |
| 171 } |
| 172 previous = member; |
| 165 } | 173 } |
| 174 // Partial keywords (simple identifiers) can be parsed |
| 175 // as a TypeName in a TopLevelVariableDeclaration |
| 176 unit.accept(this); |
| 166 } | 177 } |
| 167 } | 178 } |
| 168 } | 179 } |
| 169 | 180 |
| 181 void visitTypeName(TypeName node) { |
| 182 node.parent.accept(this); |
| 183 } |
| 184 |
| 185 void visitVariableDeclarationList(VariableDeclarationList node) { |
| 186 node.parent.accept(this); |
| 187 } |
| 188 |
| 189 void _addClassDeclarationKeywords(ClassDeclaration node) { |
| 190 // Very simplistic suggestion because analyzer will warn if |
| 191 // the extends / with / implements keywords are out of order |
| 192 if (node.extendsClause == null) { |
| 193 _addSuggestion(Keyword.EXTENDS, COMPLETION_RELEVANCE_HIGH); |
| 194 } else if (node.withClause == null) { |
| 195 _addSuggestion(Keyword.WITH, COMPLETION_RELEVANCE_HIGH); |
| 196 } |
| 197 if (node.implementsClause == null) { |
| 198 _addSuggestion(Keyword.IMPLEMENTS, COMPLETION_RELEVANCE_HIGH); |
| 199 } |
| 200 } |
| 201 |
| 170 void _addSuggestion(Keyword keyword, [int relevance = | 202 void _addSuggestion(Keyword keyword, [int relevance = |
| 171 COMPLETION_RELEVANCE_DEFAULT]) { | 203 COMPLETION_RELEVANCE_DEFAULT]) { |
| 172 String completion = keyword.syntax; | 204 String completion = keyword.syntax; |
| 173 request.suggestions.add( | 205 request.suggestions.add( |
| 174 new CompletionSuggestion( | 206 new CompletionSuggestion( |
| 175 CompletionSuggestionKind.KEYWORD, | 207 CompletionSuggestionKind.KEYWORD, |
| 176 relevance, | 208 relevance, |
| 177 completion, | 209 completion, |
| 178 completion.length, | 210 completion.length, |
| 179 0, | 211 0, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 193 Token token = node.endToken; | 225 Token token = node.endToken; |
| 194 if (token != null && !token.isSynthetic) { | 226 if (token != null && !token.isSynthetic) { |
| 195 if (token.lexeme == ';' || token.lexeme == '}') { | 227 if (token.lexeme == ';' || token.lexeme == '}') { |
| 196 return true; | 228 return true; |
| 197 } | 229 } |
| 198 } | 230 } |
| 199 } | 231 } |
| 200 return false; | 232 return false; |
| 201 } | 233 } |
| 202 } | 234 } |
| OLD | NEW |