Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Unified Diff: pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart

Issue 1471173003: hook new DartCompletionContributor API into existing framework (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merge Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
deleted file mode 100644
index 0da2c8c1652cc8e69e924c34257f9c77ab7840cd..0000000000000000000000000000000000000000
--- a/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library services.completion.contributor.dart.keyword;
-
-import 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-
-const ASYNC = 'async';
-const AWAIT = 'await';
-
-/**
- * A contributor for calculating `completion.getSuggestions` request results
- * for the local library in which the completion is requested.
- */
-class KeywordContributor extends DartCompletionContributor {
- @override
- bool computeFast(DartCompletionRequest request) {
- if (!request.target.isCommentText) {
- request.target.containingNode.accept(new _KeywordVisitor(request));
- }
- return true;
- }
-
- @override
- Future<bool> computeFull(DartCompletionRequest request) {
- return new Future.value(false);
- }
-}
-
-/**
- * A visitor for generating keyword suggestions.
- */
-class _KeywordVisitor extends GeneralizingAstVisitor {
- final DartCompletionRequest request;
- final Object entity;
-
- _KeywordVisitor(DartCompletionRequest request)
- : this.request = request,
- this.entity = request.target.entity;
-
- @override
- visitArgumentList(ArgumentList node) {
- if (entity == node.rightParenthesis ||
- (entity is SimpleIdentifier && node.arguments.contains(entity))) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitBlock(Block node) {
- if (entity is ExpressionStatement) {
- Expression expression = (entity as ExpressionStatement).expression;
- if (expression is SimpleIdentifier) {
- Token token = expression.token;
- Token previous = token.previous;
- if (previous.isSynthetic) {
- previous = previous.previous;
- }
- Token next = token.next;
- if (next.isSynthetic) {
- next = next.next;
- }
- if (previous.lexeme == ')' && next.lexeme == '{') {
- _addSuggestion2(ASYNC);
- }
- }
- }
- _addStatementKeywords(node);
- if (_inCatchClause(node)) {
- _addSuggestion(Keyword.RETHROW, DART_RELEVANCE_KEYWORD - 1);
- }
- }
-
- @override
- visitClassDeclaration(ClassDeclaration node) {
- // Don't suggest class name
- if (entity == node.name) {
- return;
- }
- if (entity == node.rightBracket) {
- _addClassBodyKeywords();
- } else if (entity is ClassMember) {
- _addClassBodyKeywords();
- int index = node.members.indexOf(entity);
- ClassMember previous = index > 0 ? node.members[index - 1] : null;
- if (previous is MethodDeclaration && previous.body is EmptyFunctionBody) {
- _addSuggestion2(ASYNC);
- }
- } else {
- _addClassDeclarationKeywords(node);
- }
- }
-
- @override
- visitCompilationUnit(CompilationUnit node) {
- var previousMember = null;
- for (var member in node.childEntities) {
- if (entity == member) {
- break;
- }
- previousMember = member;
- }
- if (previousMember is ClassDeclaration) {
- if (previousMember.leftBracket == null ||
- previousMember.leftBracket.isSynthetic) {
- // If the prior member is an unfinished class declaration
- // then the user is probably finishing that
- _addClassDeclarationKeywords(previousMember);
- return;
- }
- }
- if (previousMember is ImportDirective) {
- if (previousMember.semicolon == null ||
- previousMember.semicolon.isSynthetic) {
- // If the prior member is an unfinished import directive
- // then the user is probably finishing that
- _addImportDirectiveKeywords(previousMember);
- return;
- }
- }
- if (previousMember == null || previousMember is Directive) {
- if (previousMember == null &&
- !node.directives.any((d) => d is LibraryDirective)) {
- _addSuggestions([Keyword.LIBRARY], DART_RELEVANCE_HIGH);
- }
- _addSuggestions(
- [Keyword.IMPORT, Keyword.EXPORT, Keyword.PART], DART_RELEVANCE_HIGH);
- }
- if (entity == null || entity is Declaration) {
- if (previousMember is FunctionDeclaration &&
- previousMember.functionExpression is FunctionExpression &&
- previousMember.functionExpression.body is EmptyFunctionBody) {
- _addSuggestion2(ASYNC, relevance: DART_RELEVANCE_HIGH);
- }
- _addCompilationUnitKeywords();
- }
- }
-
- @override
- visitExpression(Expression node) {
- _addExpressionKeywords(node);
- }
-
- @override
- visitExpressionFunctionBody(ExpressionFunctionBody node) {
- if (entity == node.expression) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitForEachStatement(ForEachStatement node) {
- if (entity == node.inKeyword) {
- Token previous = node.inKeyword.previous;
- if (previous is SyntheticStringToken && previous.lexeme == 'in') {
- previous = previous.previous;
- }
- if (previous != null && previous.type == TokenType.EQ) {
- _addSuggestions([
- Keyword.CONST,
- Keyword.FALSE,
- Keyword.NEW,
- Keyword.NULL,
- Keyword.TRUE
- ]);
- } else {
- _addSuggestion(Keyword.IN, DART_RELEVANCE_HIGH);
- }
- }
- }
-
- @override
- visitFormalParameterList(FormalParameterList node) {
- AstNode constructorDeclaration =
- node.getAncestor((p) => p is ConstructorDeclaration);
- if (constructorDeclaration != null) {
- _addSuggestions([Keyword.THIS]);
- }
- }
-
- @override
- visitForStatement(ForStatement node) {
- // Handle the degenerate case while typing - for (int x i^)
- if (node.condition == entity && entity is SimpleIdentifier) {
- Token entityToken = (entity as SimpleIdentifier).beginToken;
- if (entityToken.previous.isSynthetic &&
- entityToken.previous.type == TokenType.SEMICOLON) {
- _addSuggestion(Keyword.IN, DART_RELEVANCE_HIGH);
- }
- }
- }
-
- @override
- visitFunctionExpression(FunctionExpression node) {
- if (entity == node.body) {
- if (!node.body.isAsynchronous) {
- _addSuggestion2(ASYNC, relevance: DART_RELEVANCE_HIGH);
- }
- if (node.body is EmptyFunctionBody &&
- node.parent is FunctionDeclaration &&
- node.parent.parent is CompilationUnit) {
- _addCompilationUnitKeywords();
- }
- }
- }
-
- @override
- visitIfStatement(IfStatement node) {
- if (entity == node.thenStatement) {
- _addStatementKeywords(node);
- } else if (entity == node.condition) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitImportDirective(ImportDirective node) {
- if (entity == node.asKeyword) {
- if (node.deferredKeyword == null) {
- _addSuggestion(Keyword.DEFERRED, DART_RELEVANCE_HIGH);
- }
- }
- // Handle degenerate case where import statement does not have a semicolon
- // and the cursor is in the uri string
- if ((entity == node.semicolon &&
- node.uri != null &&
- node.uri.offset + 1 != request.offset) ||
- node.combinators.contains(entity)) {
- _addImportDirectiveKeywords(node);
- }
- }
-
- @override
- visitInstanceCreationExpression(InstanceCreationExpression node) {
- if (entity == node.constructorName) {
- // no keywords in 'new ^' expression
- } else {
- super.visitInstanceCreationExpression(node);
- }
- }
-
- @override
- visitIsExpression(IsExpression node) {
- if (entity == node.isOperator) {
- _addSuggestion(Keyword.IS, DART_RELEVANCE_HIGH);
- } else {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitLibraryIdentifier(LibraryIdentifier node) {
- // no suggestions
- }
-
- @override
- visitMethodDeclaration(MethodDeclaration node) {
- if (entity == node.body) {
- if (node.body is EmptyFunctionBody) {
- _addClassBodyKeywords();
- _addSuggestion2(ASYNC);
- } else {
- _addSuggestion2(ASYNC, relevance: DART_RELEVANCE_HIGH);
- }
- }
- }
-
- @override
- visitMethodInvocation(MethodInvocation node) {
- if (entity == node.methodName) {
- // no keywords in '.' expression
- } else {
- super.visitMethodInvocation(node);
- }
- }
-
- @override
- visitNamedExpression(NamedExpression node) {
- if (entity is SimpleIdentifier && entity == node.expression) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitNode(AstNode node) {
- // ignored
- }
-
- @override
- visitPrefixedIdentifier(PrefixedIdentifier node) {
- if (entity != node.identifier) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitPropertyAccess(PropertyAccess node) {
- // suggestions before '.' but not after
- if (entity != node.propertyName) {
- super.visitPropertyAccess(node);
- }
- }
-
- @override
- visitReturnStatement(ReturnStatement node) {
- if (entity == node.expression) {
- _addExpressionKeywords(node);
- }
- }
-
- @override
- visitStringLiteral(StringLiteral node) {
- // ignored
- }
-
- @override
- visitSwitchStatement(SwitchStatement node) {
- if (entity == node.expression) {
- _addExpressionKeywords(node);
- } else if (entity == node.rightBracket) {
- if (node.members.isEmpty) {
- _addSuggestions([Keyword.CASE, Keyword.DEFAULT], DART_RELEVANCE_HIGH);
- } else {
- _addSuggestions([Keyword.CASE, Keyword.DEFAULT]);
- _addStatementKeywords(node);
- }
- }
- if (node.members.contains(entity)) {
- if (entity == node.members.first) {
- _addSuggestions([Keyword.CASE, Keyword.DEFAULT], DART_RELEVANCE_HIGH);
- } else {
- _addSuggestions([Keyword.CASE, Keyword.DEFAULT]);
- _addStatementKeywords(node);
- }
- }
- }
-
- @override
- visitVariableDeclaration(VariableDeclaration node) {
- if (entity == node.initializer) {
- _addExpressionKeywords(node);
- }
- }
-
- void _addClassBodyKeywords() {
- _addSuggestions([
- Keyword.CONST,
- Keyword.DYNAMIC,
- Keyword.FACTORY,
- Keyword.FINAL,
- Keyword.GET,
- Keyword.OPERATOR,
- Keyword.SET,
- Keyword.STATIC,
- Keyword.VAR,
- Keyword.VOID
- ]);
- }
-
- void _addClassDeclarationKeywords(ClassDeclaration node) {
- // Very simplistic suggestion because analyzer will warn if
- // the extends / with / implements keywords are out of order
- if (node.extendsClause == null) {
- _addSuggestion(Keyword.EXTENDS, DART_RELEVANCE_HIGH);
- } else if (node.withClause == null) {
- _addSuggestion(Keyword.WITH, DART_RELEVANCE_HIGH);
- }
- if (node.implementsClause == null) {
- _addSuggestion(Keyword.IMPLEMENTS, DART_RELEVANCE_HIGH);
- }
- }
-
- void _addCompilationUnitKeywords() {
- _addSuggestions([
- Keyword.ABSTRACT,
- Keyword.CLASS,
- Keyword.CONST,
- Keyword.DYNAMIC,
- Keyword.FINAL,
- Keyword.TYPEDEF,
- Keyword.VAR,
- Keyword.VOID
- ], DART_RELEVANCE_HIGH);
- }
-
- void _addExpressionKeywords(AstNode node) {
- _addSuggestions([
- Keyword.CONST,
- Keyword.FALSE,
- Keyword.NEW,
- Keyword.NULL,
- Keyword.TRUE,
- ]);
- if (_inClassMemberBody(node)) {
- _addSuggestions([Keyword.SUPER, Keyword.THIS,]);
- }
- if (_inAsyncMethodOrFunction(node)) {
- _addSuggestion2(AWAIT);
- }
- }
-
- void _addImportDirectiveKeywords(ImportDirective node) {
- bool hasDeferredKeyword = node.deferredKeyword != null;
- bool hasAsKeyword = node.asKeyword != null;
- if (!hasAsKeyword) {
- _addSuggestion(Keyword.AS, DART_RELEVANCE_HIGH);
- }
- if (!hasDeferredKeyword) {
- if (!hasAsKeyword) {
- _addSuggestion2('deferred as', relevance: DART_RELEVANCE_HIGH);
- } else if (entity == node.asKeyword) {
- _addSuggestion(Keyword.DEFERRED, DART_RELEVANCE_HIGH);
- }
- }
- if (!hasDeferredKeyword || hasAsKeyword) {
- if (node.combinators.isEmpty) {
- _addSuggestion2('show', relevance: DART_RELEVANCE_HIGH);
- _addSuggestion2('hide', relevance: DART_RELEVANCE_HIGH);
- }
- }
- }
-
- void _addStatementKeywords(AstNode node) {
- if (_inClassMemberBody(node)) {
- _addSuggestions([Keyword.SUPER, Keyword.THIS,]);
- }
- if (_inAsyncMethodOrFunction(node)) {
- _addSuggestion2(AWAIT);
- }
- if (_inLoop(node)) {
- _addSuggestions([Keyword.BREAK, Keyword.CONTINUE]);
- }
- if (_inSwitch(node)) {
- _addSuggestions([Keyword.BREAK]);
- }
- _addSuggestions([
- Keyword.ASSERT,
- Keyword.CONST,
- Keyword.DO,
- Keyword.FINAL,
- Keyword.FOR,
- Keyword.IF,
- Keyword.NEW,
- Keyword.RETURN,
- Keyword.SWITCH,
- Keyword.THROW,
- Keyword.TRY,
- Keyword.VAR,
- Keyword.VOID,
- Keyword.WHILE
- ]);
- }
-
- void _addSuggestion(Keyword keyword,
- [int relevance = DART_RELEVANCE_KEYWORD]) {
- _addSuggestion2(keyword.syntax, relevance: relevance);
- }
-
- void _addSuggestion2(String completion,
- {int offset, int relevance: DART_RELEVANCE_KEYWORD}) {
- if (offset == null) {
- offset = completion.length;
- }
- request.addSuggestion(new CompletionSuggestion(
- CompletionSuggestionKind.KEYWORD,
- relevance,
- completion,
- offset,
- 0,
- false,
- false));
- }
-
- void _addSuggestions(List<Keyword> keywords,
- [int relevance = DART_RELEVANCE_KEYWORD]) {
- keywords.forEach((Keyword keyword) {
- _addSuggestion(keyword, relevance);
- });
- }
-
- bool _inAsyncMethodOrFunction(AstNode node) {
- FunctionBody body = node.getAncestor((n) => n is FunctionBody);
- return body != null && body.isAsynchronous;
- }
-
- bool _inCatchClause(Block node) =>
- node.getAncestor((p) => p is CatchClause) != null;
-
- bool _inClassMemberBody(AstNode node) {
- while (true) {
- AstNode body = node.getAncestor((n) => n is FunctionBody);
- if (body == null) {
- return false;
- }
- AstNode parent = body.parent;
- if (parent is ConstructorDeclaration || parent is MethodDeclaration) {
- return true;
- }
- node = parent;
- }
- }
-
- bool _inDoLoop(AstNode node) =>
- node.getAncestor((p) => p is DoStatement) != null;
-
- bool _inForLoop(AstNode node) =>
- node.getAncestor((p) => p is ForStatement || p is ForEachStatement) !=
- null;
-
- bool _inLoop(AstNode node) =>
- _inDoLoop(node) || _inForLoop(node) || _inWhileLoop(node);
-
- bool _inSwitch(AstNode node) =>
- node.getAncestor((p) => p is SwitchStatement) != null;
-
- bool _inWhileLoop(AstNode node) =>
- node.getAncestor((p) => p is WhileStatement) != null;
-}

Powered by Google App Engine
This is Rietveld 408576698