blob: a9cd972fefa7da150e2098db60a97ed1a373932f [file] [log] [blame]
// 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.computer.dart.local;
import 'dart:async';
import 'package:analysis_services/completion/completion_computer.dart';
import 'package:analysis_services/completion/completion_suggestion.dart';
import 'package:analyzer/src/generated/ast.dart';
/**
* A computer for calculating `completion.getSuggestions` request results
* for the local library in which the completion is requested.
*/
class LocalComputer extends CompletionComputer {
@override
bool computeFast(CompilationUnit unit, AstNode node,
List<CompletionSuggestion> suggestions) {
// Find the specific child [AstNode] that contains the completion offset
// and collect suggestions starting with that node
if (node != null) {
node.accept(new _LocalVisitor(offset, suggestions));
}
// If the unit is not a part and does not reference any parts
// then work is complete
return !unit.directives.any(
(Directive directive) =>
directive is PartOfDirective || directive is PartDirective);
}
@override
Future<bool> computeFull(CompilationUnit unit, AstNode node,
List<CompletionSuggestion> suggestions) {
// TODO: implement computeFull
// include results from part files that are included in the library
return new Future.value(false);
}
}
/**
* A visitor for collecting suggestions from the most specific child [AstNode]
* that contains the completion offset to the [CompilationUnit].
*/
class _LocalVisitor extends GeneralizingAstVisitor<dynamic> {
final int offset;
final List<CompletionSuggestion> suggestions;
_LocalVisitor(this.offset, this.suggestions);
void addSuggestion(SimpleIdentifier id, CompletionSuggestionKind kind) {
if (id != null) {
String completion = id.name;
if (completion != null && completion.length > 0) {
suggestions.add(
new CompletionSuggestion(
kind,
CompletionRelevance.DEFAULT,
completion,
completion.length,
0,
false,
false));
}
}
}
void addSuggestions(VariableDeclarationList variables,
CompletionSuggestionKind kind) {
variables.variables.forEach((VariableDeclaration varDecl) {
addSuggestion(varDecl.name, kind);
});
}
visitBlock(Block node) {
node.statements.forEach((Statement stmt) {
if (stmt.offset < offset) {
if (stmt is LabeledStatement) {
stmt.labels.forEach((Label label) {
// addSuggestion(label.label, CompletionSuggestionKind.LABEL);
});
} else if (stmt is VariableDeclarationStatement) {
stmt.variables.variables.forEach((VariableDeclaration varDecl) {
if (varDecl.end < offset) {
addSuggestion(
varDecl.name,
CompletionSuggestionKind.LOCAL_VARIABLE);
}
});
}
}
});
visitNode(node);
}
visitCatchClause(CatchClause node) {
addSuggestion(node.exceptionParameter, CompletionSuggestionKind.PARAMETER);
addSuggestion(node.stackTraceParameter, CompletionSuggestionKind.PARAMETER);
visitNode(node);
}
visitClassDeclaration(ClassDeclaration node) {
node.members.forEach((ClassMember classMbr) {
if (classMbr is FieldDeclaration) {
addSuggestions(classMbr.fields, CompletionSuggestionKind.FIELD);
} else if (classMbr is MethodDeclaration) {
addSuggestion(classMbr.name, CompletionSuggestionKind.METHOD_NAME);
}
});
visitNode(node);
}
visitCompilationUnit(CompilationUnit node) {
node.directives.forEach((Directive directive) {
if (directive is ImportDirective) {
addSuggestion(
directive.prefix,
CompletionSuggestionKind.LIBRARY_PREFIX);
}
});
node.declarations.forEach((Declaration declaration) {
if (declaration is ClassDeclaration) {
addSuggestion(declaration.name, CompletionSuggestionKind.CLASS);
} else if (declaration is EnumDeclaration) {
// addSuggestion(d.name, CompletionSuggestionKind.ENUM);
} else if (declaration is FunctionDeclaration) {
addSuggestion(declaration.name, CompletionSuggestionKind.FUNCTION);
} else if (declaration is TopLevelVariableDeclaration) {
addSuggestions(
declaration.variables,
CompletionSuggestionKind.TOP_LEVEL_VARIABLE);
} else if (declaration is ClassTypeAlias) {
addSuggestion(declaration.name, CompletionSuggestionKind.CLASS_ALIAS);
} else if (declaration is FunctionTypeAlias) {
addSuggestion(
declaration.name,
CompletionSuggestionKind.FUNCTION_TYPE_ALIAS);
}
});
}
visitForEachStatement(ForEachStatement node) {
addSuggestion(node.identifier, CompletionSuggestionKind.LOCAL_VARIABLE);
visitNode(node);
}
visitForStatement(ForStatement node) {
addSuggestions(node.variables, CompletionSuggestionKind.LOCAL_VARIABLE);
visitNode(node);
}
visitFunctionDeclaration(FunctionDeclaration node) {
// This is added by the compilation unit containing it
//addSuggestion(node.name, CompletionSuggestionKind.FUNCTION);
visitNode(node);
}
visitFunctionExpression(FunctionExpression node) {
node.parameters.parameters.forEach((FormalParameter param) {
addSuggestion(param.identifier, CompletionSuggestionKind.PARAMETER);
});
visitNode(node);
}
visitMethodDeclaration(MethodDeclaration node) {
node.parameters.parameters.forEach((FormalParameter param) {
if (param.identifier != null) {
addSuggestion(param.identifier, CompletionSuggestionKind.PARAMETER);
}
});
visitNode(node);
}
visitNode(AstNode node) {
node.parent.accept(this);
}
}