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

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

Issue 1514263004: extract LabelContributor from local reference contributor (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merge Created 5 years 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/dart/label_contributor.dart
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
new file mode 100644
index 0000000000000000000000000000000000000000..64ed3f89eeb359de63066fae1f20c25bb9b9ffa7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -0,0 +1,286 @@
+// Copyright (c) 2015, 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.local_ref;
+
+import 'dart:async';
+
+import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol
+ show Element, ElementKind;
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'
+ show DartCompletionRequestImpl;
+import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart'
+ show LocalDeclarationVisitor;
+import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+import '../../../protocol_server.dart'
+ show CompletionSuggestion, CompletionSuggestionKind, Location;
+
+const DYNAMIC = 'dynamic';
+
+final TypeName NO_RETURN_TYPE = new TypeName(
+ new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
+
+/**
+ * A contributor for calculating label suggestions.
+ */
+class LabelContributor extends DartCompletionContributor {
+ @override
+ Future<List<CompletionSuggestion>> computeSuggestions(
+ DartCompletionRequest request) async {
+ OpType optype = (request as DartCompletionRequestImpl).opType;
+
+ // Collect suggestions from the specific child [AstNode] that contains
+ // the completion offset and all of its parents recursively.
+ List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
+ if (!optype.isPrefixed) {
+ if (optype.includeStatementLabelSuggestions ||
+ optype.includeCaseLabelSuggestions) {
+ new _LabelVisitor(request, optype.includeStatementLabelSuggestions,
+ optype.includeCaseLabelSuggestions, suggestions)
+ .visit(request.target.containingNode);
+ }
+ }
+ return suggestions;
+ }
+}
+
+/**
+ * A visitor for collecting suggestions for break and continue labels.
+ */
+class _LabelVisitor extends LocalDeclarationVisitor {
+ final DartCompletionRequest request;
+ final List<CompletionSuggestion> suggestions;
+
+ /**
+ * True if statement labels should be included as suggestions.
+ */
+ final bool includeStatementLabels;
+
+ /**
+ * True if case labels should be included as suggestions.
+ */
+ final bool includeCaseLabels;
+
+ _LabelVisitor(DartCompletionRequest request, this.includeStatementLabels,
+ this.includeCaseLabels, this.suggestions)
+ : super(request.offset),
+ request = request;
+
+ @override
+ void declaredClass(ClassDeclaration declaration) {
+ // ignored
+ }
+
+ @override
+ void declaredClassTypeAlias(ClassTypeAlias declaration) {
+ // ignored
+ }
+
+ @override
+ void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+ // ignored
+ }
+
+ @override
+ void declaredFunction(FunctionDeclaration declaration) {
+ // ignored
+ }
+
+ @override
+ void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
+ // ignored
+ }
+
+ @override
+ void declaredLabel(Label label, bool isCaseLabel) {
+ if (isCaseLabel ? includeCaseLabels : includeStatementLabels) {
+ CompletionSuggestion suggestion = _addSuggestion(label.label);
+ if (suggestion != null) {
+ suggestion.element = createLocalElement(
+ request.source, protocol.ElementKind.LABEL, label.label,
+ returnType: NO_RETURN_TYPE);
+ }
+ }
+ }
+
+ @override
+ void declaredLocalVar(SimpleIdentifier name, TypeName type) {
+ // ignored
+ }
+
+ @override
+ void declaredMethod(MethodDeclaration declaration) {
+ // ignored
+ }
+
+ @override
+ void declaredParam(SimpleIdentifier name, TypeName type) {
+ // ignored
+ }
+
+ @override
+ void declaredTopLevelVar(
+ VariableDeclarationList varList, VariableDeclaration varDecl) {
+ // ignored
+ }
+
+ @override
+ void visitFunctionExpression(FunctionExpression node) {
+ // Labels are only accessible within the local function, so stop visiting
+ // once we reach a function boundary.
+ finished();
+ }
+
+ @override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ // Labels are only accessible within the local function, so stop visiting
+ // once we reach a function boundary.
+ finished();
+ }
+
+ CompletionSuggestion _addSuggestion(SimpleIdentifier id) {
+ if (id != null) {
+ String completion = id.name;
+ if (completion != null && completion.length > 0 && completion != '_') {
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ CompletionSuggestionKind.IDENTIFIER,
+ DART_RELEVANCE_DEFAULT,
+ completion,
+ completion.length,
+ 0,
+ false,
+ false);
+ suggestions.add(suggestion);
+ return suggestion;
+ }
+ }
+ return null;
+ }
+}
+
+/**
+* Create a new protocol Element for inclusion in a completion suggestion.
+*/
+protocol.Element createLocalElement(
+ Source source, protocol.ElementKind kind, SimpleIdentifier id,
+ {String parameters,
+ TypeName returnType,
+ bool isAbstract: false,
+ bool isDeprecated: false}) {
+ String name;
+ Location location;
+ if (id != null) {
+ name = id.name;
+ // TODO(danrubel) use lineInfo to determine startLine and startColumn
+ location = new Location(source.fullName, id.offset, id.length, 0, 0);
+ } else {
+ name = '';
+ location = new Location(source.fullName, -1, 0, 1, 0);
+ }
+ int flags = protocol.Element.makeFlags(
+ isAbstract: isAbstract,
+ isDeprecated: isDeprecated,
+ isPrivate: Identifier.isPrivateName(name));
+ return new protocol.Element(kind, name, flags,
+ location: location,
+ parameters: parameters,
+ returnType: nameForType(returnType));
+}
+
+/**
+* Create a new suggestion for the given field.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalFieldSuggestion(
+ Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+ bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
+ TypeName type = fieldDecl.fields.type;
+ return createLocalSuggestion(
+ varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
+ classDecl: fieldDecl.parent,
+ element: createLocalElement(
+ source, protocol.ElementKind.FIELD, varDecl.name,
+ returnType: type, isDeprecated: deprecated));
+}
+
+/**
+* Create a new suggestion based upon the given information.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
+ bool isDeprecated, int defaultRelevance, TypeName returnType,
+ {ClassDeclaration classDecl, protocol.Element element}) {
+ if (id == null) {
+ return null;
+ }
+ String completion = id.name;
+ if (completion == null || completion.length <= 0 || completion == '_') {
+ return null;
+ }
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+ completion,
+ completion.length,
+ 0,
+ isDeprecated,
+ false,
+ returnType: nameForType(returnType),
+ element: element);
+ if (classDecl != null) {
+ SimpleIdentifier classId = classDecl.name;
+ if (classId != null) {
+ String className = classId.name;
+ if (className != null && className.length > 0) {
+ suggestion.declaringType = className;
+ }
+ }
+ }
+ return suggestion;
+}
+
+/**
+* Return `true` if the @deprecated annotation is present
+*/
+bool isDeprecated(AnnotatedNode node) {
+ if (node != null) {
+ NodeList<Annotation> metadata = node.metadata;
+ if (metadata != null) {
+ return metadata.any((Annotation a) {
+ return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+ });
+ }
+ }
+ return false;
+}
+
+/**
+* Return the name for the given type.
+*/
+String nameForType(TypeName type) {
+ if (type == NO_RETURN_TYPE) {
+ return null;
+ }
+ if (type == null) {
+ return DYNAMIC;
+ }
+ Identifier id = type.name;
+ if (id == null) {
+ return DYNAMIC;
+ }
+ String name = id.name;
+ if (name == null || name.length <= 0) {
+ return DYNAMIC;
+ }
+ TypeArgumentList typeArgs = type.typeArguments;
+ if (typeArgs != null) {
+ //TODO (danrubel) include type arguments
+ }
+ return name;
+}

Powered by Google App Engine
This is Rietveld 408576698