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

Unified Diff: pkg/analysis_services/lib/src/generated/completion.dart

Issue 263213007: New analysis_server snapshot and completion.dart in analysis_services. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months 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_services/lib/src/generated/completion.dart
diff --git a/pkg/analysis_services/lib/src/generated/completion.dart b/pkg/analysis_services/lib/src/generated/completion.dart
new file mode 100644
index 0000000000000000000000000000000000000000..175132526ecb72eda86ab499082b796ac2b1fc37
--- /dev/null
+++ b/pkg/analysis_services/lib/src/generated/completion.dart
@@ -0,0 +1,3770 @@
+// 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.
+
+// This code was auto-generated, is not intended to be edited, and is subject to
+// significant change. Please see the README file for more information.
+
+library services.completion;
+
+import 'dart:collection';
+import 'package:analyzer/src/generated/java_core.dart' hide StringUtils;
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'stubs.dart';
+import 'util.dart';
+
+class AstNodeClassifier_CompletionEngine_typeOf extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ List<DartType> result;
+
+ AstNodeClassifier_CompletionEngine_typeOf(this.CompletionEngine_this, this.result) : super();
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) => visitSimpleIdentifier(node.identifier);
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ Element elem = node.bestElement;
+ if (elem != null && elem.kind == ElementKind.GETTER) {
+ PropertyAccessorElement accessor = elem as PropertyAccessorElement;
+ if (accessor.isSynthetic) {
+ PropertyInducingElement var2 = accessor.variable;
+ result[0] = CompletionEngine_this._typeSearch(var2);
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * The analysis engine for code completion.
+ *
+ * Note: During development package-private methods are used to group element-specific completion
+ * utilities.
+ *
+ * TODO: Recognize when completion is requested in the middle of a multi-character operator.
+ * Re-write the AST as it would be if an identifier were present at the completion point then
+ * restart the analysis.
+ */
+class CompletionEngine {
+ static String _C_DYNAMIC = "dynamic";
+
+ static String _C_FALSE = "false";
+
+ static String _C_NULL = "null";
+
+ static String _C_PARAMNAME = "arg";
+
+ static String _C_TRUE = "true";
+
+ static String _C_VAR = "var";
+
+ static String _C_VOID = "void";
+
+ static bool _isPrivate(Element element) {
+ String name = element.displayName;
+ return Identifier.isPrivateName(name);
+ }
+
+ static bool _isSyntheticIdentifier(Expression expression) => expression is SimpleIdentifier && expression.isSynthetic;
+
+ CompletionRequestor _requestor;
+
+ final CompletionFactory _factory;
+
+ AssistContext _context;
+
+ Filter _filter;
+
+ CompletionState _state;
+
+ List<LibraryElement> _libraries;
+
+ CompletionEngine(CompletionRequestor requestor, this._factory) {
+ this._requestor = requestor;
+ this._state = new CompletionState();
+ }
+
+ /**
+ * Analyze the source unit in the given context to determine completion proposals at the selection
+ * offset of the context.
+ *
+ * @throws Exception
+ */
+ void complete(AssistContext context) {
+ this._context = context;
+ _requestor.beginReporting();
+ AstNode completionNode = context.coveredNode;
+ if (completionNode != null) {
+ _state.context = completionNode;
+ CompletionEngine_TerminalNodeCompleter visitor = new CompletionEngine_TerminalNodeCompleter(this);
+ completionNode.accept(visitor);
+ }
+ _requestor.endReporting();
+ }
+
+ void _analyzeAnnotationName(SimpleIdentifier identifier) {
+ _filter = _createFilter(identifier);
+ CompletionEngine_NameCollector names = _collectTopLevelElementVisibleAt(identifier);
+ for (Element element in names.uniqueElements) {
+ if (element is PropertyAccessorElement) {
+ element = (element as PropertyAccessorElement).variable;
+ }
+ if (element is TopLevelVariableElement) {
+ TopLevelVariableElement variable = element as TopLevelVariableElement;
+ if (_state._isCompileTimeConstantRequired && !variable.isConst) {
+ continue;
+ }
+ _proposeName(element, identifier, names);
+ }
+ if (element is ClassElement) {
+ ClassElement classElement = element as ClassElement;
+ for (ConstructorElement constructor in classElement.constructors) {
+ _pNamedConstructor(classElement, constructor, identifier);
+ }
+ }
+ }
+ }
+
+ void _analyzeConstructorTypeName(SimpleIdentifier identifier) {
+ _filter = _createFilter(identifier);
+ List<Element> types = _findAllTypes(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPORTS);
+ for (Element type in types) {
+ if (type is ClassElement) {
+ _namedConstructorReference(type, identifier);
+ }
+ }
+ List<Element> prefixes = _findAllPrefixes();
+ for (Element prefix in prefixes) {
+ _pName(prefix, identifier);
+ }
+ }
+
+ void _analyzeDeclarationName(VariableDeclaration varDecl) {
+ // We might want to propose multiple names for a declaration based on types someday.
+ // For now, just use whatever is already there.
+ SimpleIdentifier identifier = varDecl.name;
+ _filter = _createFilter(identifier);
+ VariableDeclarationList varList = varDecl.parent as VariableDeclarationList;
+ TypeName type = varList.type;
+ if (identifier.length > 0) {
+ _pName3(identifier.name, ProposalKind.VARIABLE);
+ }
+ if (type == null) {
+ if (varList.keyword == null) {
+ // Interpret as the type name of a typed variable declaration { DivE!; }
+ _analyzeLocalName(identifier);
+ }
+ } else {
+ _pParamName(type.name.name.toLowerCase());
+ }
+ }
+
+ void _analyzeDirectAccess(DartType receiverType, SimpleIdentifier completionNode) {
+ if (receiverType != null) {
+ // Complete this.!y where this is absent
+ Element rcvrTypeElem = receiverType.element;
+ if (receiverType.isDynamic) {
+ rcvrTypeElem = objectClassElement;
+ }
+ if (rcvrTypeElem is ClassElement) {
+ _directAccess(rcvrTypeElem as ClassElement, completionNode);
+ }
+ }
+ }
+
+ void _analyzeImmediateField(SimpleIdentifier fieldName) {
+ _filter = _createFilter(fieldName);
+ ClassDeclaration classDecl = fieldName.getAncestor((node) => node is ClassDeclaration);
+ ClassElement classElement = classDecl.element;
+ for (FieldElement field in classElement.fields) {
+ _pName3(field.displayName, ProposalKind.FIELD);
+ }
+ }
+
+ void _analyzeLiteralReference(BooleanLiteral literal) {
+ // state.setContext(literal);
+ Ident ident = _createIdent(literal.parent);
+ ident.token = literal.literal;
+ _filter = _createFilter(ident);
+ _analyzeLocalName(ident);
+ }
+
+ void _analyzeLocalName(SimpleIdentifier identifier) {
+ // Completion x!
+ _filter = _createFilter(identifier);
+ // TODO Filter out types that have no static members.
+ CompletionEngine_NameCollector names = _collectIdentifiersVisibleAt(identifier);
+ for (Element element in names.uniqueElements) {
+ if (_state._isSourceDeclarationStatic) {
+ if (element is FieldElement) {
+ if (!element.isStatic) {
+ continue;
+ }
+ } else if (element is PropertyAccessorElement) {
+ if (!element.isStatic) {
+ continue;
+ }
+ }
+ }
+ if (_state._isOptionalArgumentRequired) {
+ if (element is! ParameterElement) {
+ continue;
+ }
+ ParameterElement param = element as ParameterElement;
+ if (!param.parameterKind.isOptional) {
+ continue;
+ }
+ }
+ _proposeName(element, identifier, names);
+ }
+ if (_state._areLiteralsAllowed) {
+ _pNull();
+ _pTrue();
+ _pFalse();
+ }
+ }
+
+ void _analyzeNamedParameter(ArgumentList args, SimpleIdentifier identifier) {
+ // Completion x!
+ _filter = _createFilter(identifier);
+ // prepare parameters
+ List<ParameterElement> parameters = _getParameterElements(args);
+ if (parameters == null) {
+ return;
+ }
+ // remember already used names
+ Set<String> usedNames = new Set();
+ for (Expression arg in args.arguments) {
+ if (arg is NamedExpression) {
+ NamedExpression namedExpr = arg;
+ String name = namedExpr.name.label.name;
+ usedNames.add(name);
+ }
+ }
+ // propose named parameters
+ for (ParameterElement parameterElement in parameters) {
+ // should be named
+ if (parameterElement.parameterKind != ParameterKind.NAMED) {
+ continue;
+ }
+ // filter by name
+ if (_filterDisallows(parameterElement)) {
+ continue;
+ }
+ // may be already used
+ String parameterName = parameterElement.name;
+ if (usedNames.contains(parameterName)) {
+ continue;
+ }
+ // OK, add proposal
+ CompletionProposal prop = _createProposal4(ProposalKind.NAMED_ARGUMENT);
+ prop.setCompletion(parameterName);
+ prop.setParameterName(parameterName);
+ prop.setParameterType(parameterElement.type.displayName);
+ prop.setLocation(identifier.offset);
+ prop.setReplacementLength(identifier.length);
+ prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
+ _requestor.accept(prop);
+ }
+ }
+
+ void _analyzeNewParameterName(List<FormalParameter> params, SimpleIdentifier typeIdent, String identifierName) {
+ String typeName = typeIdent.name;
+ _filter = _createFilter(_createIdent(typeIdent));
+ List<String> names = new List<String>();
+ for (FormalParameter node in params) {
+ names.add(node.identifier.name);
+ }
+ // Find name similar to typeName not in names, ditto for identifierName.
+ if (identifierName == null || identifierName.isEmpty) {
+ String candidate = typeName == null || typeName.isEmpty ? _C_PARAMNAME : typeName.toLowerCase();
+ _pParamName(_makeNonconflictingName(candidate, names));
+ } else {
+ _pParamName(_makeNonconflictingName(identifierName, names));
+ if (typeName != null && !typeName.isEmpty) {
+ _pParamName(_makeNonconflictingName(typeName.toLowerCase(), names));
+ }
+ }
+ }
+
+ void _analyzePositionalArgument(ArgumentList args, SimpleIdentifier identifier) {
+ // Show parameter name only if there is nothing to complete, so that if there is only
+ // one match, we won't to force user to choose.
+ if (!StringUtils.isEmpty(identifier.name)) {
+ return;
+ }
+ // prepare parameters
+ List<ParameterElement> parameters = _getParameterElements(args);
+ if (parameters == null) {
+ return;
+ }
+ // show current parameter
+ int argIndex = args.arguments.indexOf(identifier);
+ if (argIndex == -1) {
+ argIndex = 0;
+ }
+ if (argIndex >= 0 && argIndex < parameters.length) {
+ ParameterElement parameter = parameters[argIndex];
+ if (parameter.parameterKind != ParameterKind.NAMED) {
+ String parameterName = parameter.displayName;
+ CompletionProposal prop = _createProposal4(ProposalKind.OPTIONAL_ARGUMENT);
+ prop.setCompletion(parameterName);
+ prop.setParameterName(parameterName);
+ prop.setParameterType(parameter.type.displayName);
+ prop.setLocation(identifier.offset);
+ prop.setReplacementLength(identifier.length);
+ prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
+ _requestor.accept(prop);
+ }
+ }
+ }
+
+ void _analyzePrefixedAccess(Expression receiver, SimpleIdentifier completionNode) {
+ if (receiver is ThisExpression && !_state._isThisAllowed) {
+ return;
+ }
+ DartType receiverType = _typeOf2(receiver);
+ bool forSuper = receiver is SuperExpression;
+ _analyzePrefixedAccess2(receiverType, forSuper, completionNode);
+ }
+
+ void _analyzePrefixedAccess2(DartType receiverType, bool forSuper, SimpleIdentifier completionNode) {
+ if (receiverType != null) {
+ // Complete x.!y
+ Element rcvrTypeElem = receiverType.element;
+ if (receiverType.isBottom) {
+ receiverType = objectType;
+ }
+ if (receiverType.isDynamic) {
+ receiverType = objectType;
+ }
+ if (receiverType is InterfaceType) {
+ _prefixedAccess(receiverType, forSuper, completionNode);
+ } else if (rcvrTypeElem is TypeParameterElement) {
+ TypeParameterElement typeParamElem = rcvrTypeElem;
+ _analyzePrefixedAccess2(typeParamElem.bound, false, completionNode);
+ }
+ }
+ }
+
+ void _analyzeReceiver(SimpleIdentifier identifier) {
+ // Completion x!.y
+ _filter = _createFilter(identifier);
+ CompletionEngine_NameCollector names = _collectIdentifiersVisibleAt(identifier);
+ for (Element element in names.uniqueElements) {
+ _proposeName(element, identifier, names);
+ }
+ }
+
+ void _analyzeSuperConstructorInvocation(SuperConstructorInvocation node) {
+ ClassDeclaration enclosingClassNode = node.getAncestor((node) => node is ClassDeclaration);
+ if (enclosingClassNode != null) {
+ ClassElement enclosingClassElement = enclosingClassNode.element;
+ if (enclosingClassElement != null) {
+ ClassElement superClassElement = enclosingClassElement.supertype.element;
+ _constructorReference(superClassElement, node.constructorName);
+ }
+ }
+ }
+
+ void _analyzeTypeName(SimpleIdentifier identifier, SimpleIdentifier nameIdent) {
+ _filter = _createFilter(identifier);
+ String name = nameIdent == null ? "" : nameIdent.name;
+ List<Element> types = _findAllTypes(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPORTS);
+ for (Element type in types) {
+ if (_state._isForMixin) {
+ if (type is! ClassElement) {
+ continue;
+ }
+ ClassElement classElement = type as ClassElement;
+ if (!classElement.isValidMixin) {
+ continue;
+ }
+ }
+ if (type.displayName == name) {
+ continue;
+ }
+ _pName(type, nameIdent);
+ }
+ if (!_state._isForMixin) {
+ ClassDeclaration classDecl = identifier.getAncestor((node) => node is ClassDeclaration);
+ if (classDecl != null) {
+ ClassElement classElement = classDecl.element;
+ for (TypeParameterElement param in classElement.typeParameters) {
+ _pName(param, nameIdent);
+ }
+ }
+ }
+ List<Element> prefixes = _findAllPrefixes();
+ for (Element prefix in prefixes) {
+ _pName(prefix, nameIdent);
+ }
+ if (_state._isDynamicAllowed) {
+ _pDynamic();
+ }
+ if (_state._isVarAllowed) {
+ _pVar();
+ }
+ if (_state._isVoidAllowed) {
+ _pVoid();
+ }
+ }
+
+ void _constructorReference(ClassElement classElement, SimpleIdentifier identifier) {
+ // Complete identifier when it refers to a constructor defined in classElement.
+ _filter = _createFilter(identifier);
+ for (ConstructorElement cons in classElement.constructors) {
+ if (_state._isCompileTimeConstantRequired == cons.isConst && _filterAllows(cons)) {
+ _pExecutable2(cons, identifier, false);
+ }
+ }
+ }
+
+ void _directAccess(ClassElement classElement, SimpleIdentifier identifier) {
+ _filter = _createFilter(identifier);
+ CompletionEngine_NameCollector names = _createNameCollector();
+ names.addLocalNames(identifier);
+ names._addNamesDefinedByHierarchy(classElement, false);
+ names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPORTS);
+ _proposeNames(names, identifier);
+ }
+
+ void _dispatchPrefixAnalysis(InstanceCreationExpression node) {
+ // prepare ClassElement
+ ClassElement classElement;
+ {
+ Element typeElement = _typeOf2(node).element;
+ if (typeElement is! ClassElement) {
+ return;
+ }
+ classElement = typeElement as ClassElement;
+ }
+ // prepare constructor name
+ Identifier typeName = node.constructorName.type.name;
+ SimpleIdentifier identifier = null;
+ if (typeName is SimpleIdentifier) {
+ identifier = typeName;
+ } else if (typeName is PrefixedIdentifier) {
+ identifier = typeName.identifier;
+ }
+ if (identifier == null) {
+ identifier = _createIdent(node);
+ }
+ // analyze constructor name
+ _analyzeConstructorTypeName(identifier);
+ _constructorReference(classElement, identifier);
+ }
+
+ void _dispatchPrefixAnalysis2(MethodInvocation node) {
+ // This might be a library prefix on a top-level function
+ Expression expr = node.realTarget;
+ if (expr is SimpleIdentifier) {
+ SimpleIdentifier ident = expr;
+ if (ident.bestElement is PrefixElement) {
+ _prefixedAccess2(ident, node.methodName);
+ return;
+ } else if (ident.bestElement is ClassElement) {
+ _state._areInstanceReferencesProhibited = true;
+ _state._areStaticReferencesProhibited = false;
+ } else {
+ _state._areInstanceReferencesProhibited = false;
+ _state._areStaticReferencesProhibited = true;
+ }
+ }
+ if (expr == null) {
+ _analyzeLocalName(_createIdent(node));
+ } else {
+ _analyzePrefixedAccess(expr, node.methodName);
+ }
+ }
+
+ void _dispatchPrefixAnalysis3(PrefixedIdentifier node, SimpleIdentifier identifier) {
+ SimpleIdentifier receiverName = node.prefix;
+ Element receiver = receiverName.bestElement;
+ if (receiver == null) {
+ _prefixedAccess2(receiverName, identifier);
+ return;
+ }
+ while (true) {
+ if (receiver.kind == ElementKind.PREFIX || receiver.kind == ElementKind.IMPORT) {
+ // Complete lib_prefix.name
+ _prefixedAccess2(receiverName, identifier);
+ } else {
+ {
+ DartType receiverType;
+ DartType propType = _typeOf2(receiverName);
+ if (propType == null || propType.isDynamic) {
+ receiverType = _typeOf(receiver);
+ } else {
+ DartType declType = _typeOf(receiver);
+ if (propType.isMoreSpecificThan(declType)) {
+ receiverType = propType;
+ } else {
+ receiverType = declType;
+ }
+ }
+ _analyzePrefixedAccess2(receiverType, false, identifier);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ void _fieldReference(ClassElement classElement, SimpleIdentifier identifier) {
+ // Complete identifier when it refers to a constructor defined in classElement.
+ _filter = _createFilter(identifier);
+ for (FieldElement cons in classElement.fields) {
+ if (_filterAllows(cons)) {
+ _pField(cons, identifier, classElement);
+ }
+ }
+ }
+
+ void _namedConstructorReference(ClassElement classElement, SimpleIdentifier identifier) {
+ // Complete identifier when it refers to a named constructor defined in classElement.
+ if (_filter == null) {
+ _filter = _createFilter(identifier);
+ }
+ for (ConstructorElement cons in classElement.constructors) {
+ if (!_isVisible(cons)) {
+ continue;
+ }
+ if (_state._isCompileTimeConstantRequired && !cons.isConst) {
+ continue;
+ }
+ _pNamedConstructor(classElement, cons, identifier);
+ }
+ }
+
+ void _namespacePubReference(NamespaceDirective node, Set<String> packageUris) {
+ // no import URI or package:
+ String prefix = _filter._prefix;
+ List<String> prefixStrings = prefix.split(":");
+ if (!prefix.isEmpty && !"package:".startsWith(prefixStrings[0])) {
+ return;
+ }
+ // if no URI yet, propose package:
+ if (prefix.isEmpty) {
+ _pImportUriWithScheme(node, "package:");
+ return;
+ }
+ // check "packages" folder for package libraries that are not added to AnalysisContext
+ {
+ Source contextSource = _context.source;
+ if (contextSource is FileBasedSource) {
+ FileBasedSource contextFileSource = contextSource;
+ String contextFilePath = contextFileSource.fullName;
+ JavaFile contextFile = new JavaFile(contextFilePath);
+ JavaFile contextFolder = contextFile.getParentFile();
+ JavaFile contextPackages = new JavaFile.relative(contextFolder, "packages");
+ if (contextPackages.isDirectory()) {
+ for (JavaFile packageFolder in contextPackages.listFiles()) {
+ String packageName = packageFolder.getName();
+ String packageLibName = "${packageName}.dart";
+ JavaFile packageFile = new JavaFile.relative(packageFolder, packageLibName);
+ if (packageFile.exists() && packageFile.isFile()) {
+ packageUris.add("package:${packageName}/${packageLibName}");
+ }
+ }
+ }
+ }
+ }
+ // add known package: URIs
+ for (String uri in packageUris) {
+ if (_filterDisallows2(uri)) {
+ continue;
+ }
+ CompletionProposal prop = _createProposal4(ProposalKind.IMPORT);
+ prop.setCompletion(uri);
+ // put "lib" before "lib/src"
+ if (!uri.contains("/src/")) {
+ prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
+ }
+ // done
+ _requestor.accept(prop);
+ }
+ }
+
+ void _namespaceReference(NamespaceDirective node, SimpleStringLiteral literal) {
+ String lit = literal.literal.lexeme;
+ if (!lit.isEmpty) {
+ lit = lit.substring(1, Math.max(lit.length - 1, 0));
+ }
+ _filter = _createFilter(new Ident.con2(node, lit, literal.offset + 1));
+ Set<String> packageUris = new Set();
+ List<LibraryElement> libraries = new List<LibraryElement>();
+ List<LibraryElement> librariesInLib = new List<LibraryElement>();
+ String currentLibraryName = currentLibrary.source.fullName;
+ AnalysisContext ac = analysisContext;
+ List<Source> sources = ac.librarySources;
+ for (Source s in sources) {
+ String sName = s.fullName;
+ // skip current library
+ if (currentLibraryName == sName) {
+ continue;
+ }
+ // ".pub-cache/..../unittest-0.8.8/lib/unittest.dart" -> "package:unittest/unittest.dart"
+ {
+ Uri uri = ac.sourceFactory.restoreUri(s);
+ if (uri != null) {
+ String uriString = uri.toString();
+ if (uriString.startsWith("package:")) {
+ packageUris.add(uriString);
+ }
+ }
+ }
+ LibraryElement lib = ac.getLibraryElement(s);
+ if (lib == null) {
+ continue;
+ } else if (_isUnitInLibFolder(lib.definingCompilationUnit)) {
+ librariesInLib.add(lib);
+ } else {
+ libraries.add(lib);
+ }
+ }
+ _namespaceSdkReference(node);
+ _namespacePubReference(node, packageUris);
+ }
+
+ void _namespaceSdkReference(NamespaceDirective node) {
+ String prefix = _filter._prefix;
+ List<String> prefixStrings = prefix.split(":");
+ if (!prefix.isEmpty && !"dart:".startsWith(prefixStrings[0])) {
+ return;
+ }
+ if (prefix.isEmpty) {
+ _pImportUriWithScheme(node, "dart:");
+ return;
+ }
+ // add DartSdk libraries
+ DartSdk dartSdk = analysisContext.sourceFactory.dartSdk;
+ for (SdkLibrary library in dartSdk.sdkLibraries) {
+ String name = library.shortName;
+ // ignore internal
+ if (library.isInternal) {
+ continue;
+ }
+ // ignore implementation
+ if (library.isImplementation) {
+ continue;
+ }
+ // standard libraries name name starting with "dart:"
+ name = StringUtils.removeStart(name, "dart:");
+ // ignore private libraries
+ if (Identifier.isPrivateName(name)) {
+ continue;
+ }
+ // add with "dart:" prefix
+ _pName3("dart:${name}", ProposalKind.IMPORT);
+ }
+ }
+
+ void _operatorAccess(Expression expr, SimpleIdentifier identifier) {
+ _state._requiresOperators();
+ _analyzePrefixedAccess(expr, identifier);
+ }
+
+ void _prefixedAccess(InterfaceType type, bool forSuper, SimpleIdentifier identifier) {
+ // Complete identifier when it refers to field or method in classElement.
+ _filter = _createFilter(identifier);
+ CompletionEngine_NameCollector names = _createNameCollector();
+ if (_state._areInstanceReferencesProhibited) {
+ names._addNamesDefinedByType2(type);
+ } else {
+ names._addNamesDefinedByHierarchy2(type, forSuper);
+ }
+ _proposeNames(names, identifier);
+ }
+
+ void _prefixedAccess2(SimpleIdentifier prefixName, SimpleIdentifier identifier) {
+ if (_filter == null) {
+ _filter = _createFilter(identifier);
+ }
+ CompletionEngine_NameCollector names = _createNameCollector();
+ List<ImportElement> prefixImports = _importsWithName(prefixName);
+ // Library prefixes do not have a unique AST representation so we need to fudge state vars.
+ bool litsAllowed = _state._areLiteralsAllowed;
+ _state._areLiteralsAllowed = false;
+ names._addTopLevelNames(prefixImports, TopLevelNamesKind.DECLARED_AND_EXPORTS);
+ _state._areLiteralsAllowed = litsAllowed;
+ _proposeNames(names, identifier);
+ }
+
+ List<InterfaceType> _allSubtypes(ClassElement classElement) {
+ // TODO(scheglov) translate it
+ return [];
+ }
+
+ CompletionEngine_NameCollector _collectIdentifiersVisibleAt(AstNode ident) {
+ CompletionEngine_NameCollector names = _createNameCollector();
+ ScopedNameFinder finder = new ScopedNameFinder(_completionLocation());
+ ident.accept(finder);
+ names.addAll(finder.locals.values);
+ Declaration decl = finder.declaration;
+ if (decl != null && decl.parent is ClassDeclaration) {
+ ClassElement classElement = (decl.parent as ClassDeclaration).element;
+ names._addNamesDefinedByHierarchy(classElement, false);
+ }
+ names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPORTS);
+ return names;
+ }
+
+ CompletionEngine_NameCollector _collectTopLevelElementVisibleAt(AstNode ident) {
+ CompletionEngine_NameCollector names = _createNameCollector();
+ names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPORTS);
+ return names;
+ }
+
+ int _completionLocation() => _context.selectionOffset;
+
+ int _completionTokenOffset() => _completionLocation() - _filter._prefix.length;
+
+ List<FormalParameter> _copyWithout(NodeList oldList, AstNode deletion) {
+ List<FormalParameter> newList = new List<FormalParameter>();
+ oldList.accept(new GeneralizingAstVisitor_CompletionEngine_copyWithout(deletion, newList));
+ return newList;
+ }
+
+ Filter _createFilter(SimpleIdentifier ident) => new Filter.con1(ident, _context.selectionOffset);
+
+ Ident _createIdent(AstNode node) => new Ident.con1(node, _completionLocation());
+
+ CompletionEngine_NameCollector _createNameCollector() => new CompletionEngine_NameCollector(this);
+
+ CompletionProposal _createProposal(Element element) {
+ String completion = element.displayName;
+ return _createProposal3(element, completion);
+ }
+
+ CompletionProposal _createProposal2(Element element, SimpleIdentifier identifier) {
+ // Create a completion proposal for the element: variable, field, class, function.
+ if (_filterDisallows(element)) {
+ return null;
+ }
+ CompletionProposal prop = _createProposal(element);
+ Element container = element.enclosingElement;
+ if (container != null) {
+ prop.setDeclaringType(container.displayName);
+ }
+ DartType type = _typeOf(element);
+ if (type != null) {
+ prop.setReturnType(type.name);
+ }
+ if (identifier != null) {
+ prop.setReplacementLengthIdentifier(identifier.length);
+ }
+ return prop;
+ }
+
+ CompletionProposal _createProposal3(Element element, String completion) {
+ ProposalKind kind = _proposalKindOf(element);
+ CompletionProposal prop = _createProposal4(kind);
+ prop.setElement(element);
+ prop.setCompletion(completion);
+ prop.setDeprecated(_isDeprecated(element));
+ if (_isPrivate(element)) {
+ prop.setRelevance(CompletionProposal.RELEVANCE_LOW);
+ }
+ if (_filter._isSameCasePrefix(element.name)) {
+ prop.incRelevance();
+ }
+ return prop;
+ }
+
+ CompletionProposal _createProposal4(ProposalKind kind) => _factory.createCompletionProposal(kind, _completionTokenOffset());
+
+ List<LibraryElement> _currentLibraryList() {
+ Set<LibraryElement> libraries = new Set<LibraryElement>();
+ LibraryElement curLib = currentLibrary;
+ libraries.add(curLib);
+ Queue<LibraryElement> queue = new Queue<LibraryElement>();
+ queue.addAll(curLib.importedLibraries);
+ _currentLibraryLister(queue, libraries);
+ return new List.from(libraries);
+ }
+
+ void _currentLibraryLister(Queue<LibraryElement> queue, Set<LibraryElement> libraries) {
+ while (!queue.isEmpty) {
+ LibraryElement sourceLib = queue.removeFirst();
+ libraries.add(sourceLib);
+ List<LibraryElement> expLibs = sourceLib.exportedLibraries;
+ for (LibraryElement lib in expLibs) {
+ if (!libraries.contains(lib)) {
+ queue.add(lib);
+ }
+ }
+ }
+ }
+
+ bool _filterAllows(Element element) => _filter._match(element);
+
+ bool _filterDisallows(Element element) => !_filter._match(element);
+
+ bool _filterDisallows2(String name) => !_filter._match2(name);
+
+ List<Element> _findAllNotTypes(List<Element> elements) {
+ elements = [];
+ for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
+ Element element = I.next();
+ ElementKind kind = element.kind;
+ if (kind == ElementKind.FUNCTION || kind == ElementKind.TOP_LEVEL_VARIABLE || kind == ElementKind.GETTER || kind == ElementKind.SETTER) {
+ continue;
+ }
+ I.remove();
+ }
+ return new List.from(elements);
+ }
+
+ List<Element> _findAllPrefixes() {
+ LibraryElement lib = _context.compilationUnitElement.enclosingElement;
+ return lib.prefixes;
+ }
+
+ List<Element> _findAllTypes(LibraryElement library, TopLevelNamesKind topKind) {
+ List<Element> elements = _findTopLevelElements(library, topKind);
+ return _findAllTypes2(elements);
+ }
+
+ List<Element> _findAllTypes2(List<Element> elements) {
+ elements = [];
+ for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
+ Element element = I.next();
+ ElementKind kind = element.kind;
+ if (kind == ElementKind.CLASS || kind == ElementKind.FUNCTION_TYPE_ALIAS) {
+ continue;
+ }
+ I.remove();
+ }
+ return new List.from(elements);
+ }
+
+ List<Element> _findTopLevelElements(LibraryElement library, TopLevelNamesKind topKind) {
+ List<Element> elements = [];
+ if (topKind == TopLevelNamesKind.DECLARED_AND_IMPORTS) {
+ elements.addAll(CorrectionUtils.getTopLevelElements(library));
+ for (ImportElement imp in library.imports) {
+ elements.addAll(CorrectionUtils.getImportNamespace(imp).values);
+ }
+ _removeNotMatchingFilter(elements);
+ }
+ if (topKind == TopLevelNamesKind.DECLARED_AND_EXPORTS) {
+ elements.addAll(CorrectionUtils.getExportNamespace2(library).values);
+ _removeNotMatchingFilter(elements);
+ }
+ return elements;
+ }
+
+ AnalysisContext get analysisContext => _context.compilationUnitElement.context;
+
+ LibraryElement get currentLibrary => _context.compilationUnitElement.enclosingElement;
+
+ FunctionType _getFunctionType(Element element) {
+ if (element is ExecutableElement) {
+ ExecutableElement executableElement = element;
+ return executableElement.type;
+ }
+ if (element is VariableElement) {
+ VariableElement variableElement = element;
+ DartType type = variableElement.type;
+ if (type is FunctionType) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ ClassElement get objectClassElement => typeProvider.objectType.element;
+
+ InterfaceType get objectType => typeProvider.objectType;
+
+ List<ParameterElement> _getParameterElements(ArgumentList args) {
+ List<ParameterElement> parameters = null;
+ AstNode argsParent = args.parent;
+ if (argsParent is MethodInvocation) {
+ MethodInvocation invocation = argsParent;
+ Element nameElement = invocation.methodName.staticElement;
+ FunctionType functionType = _getFunctionType(nameElement);
+ if (functionType != null) {
+ parameters = functionType.parameters;
+ }
+ }
+ if (argsParent is InstanceCreationExpression) {
+ InstanceCreationExpression creation = argsParent;
+ ConstructorElement element = creation.staticElement;
+ if (element != null) {
+ parameters = element.parameters;
+ }
+ }
+ if (argsParent is Annotation) {
+ Annotation annotation = argsParent;
+ Element element = annotation.element;
+ if (element is ConstructorElement) {
+ parameters = element.parameters;
+ }
+ }
+ return parameters;
+ }
+
+ TypeProvider get typeProvider {
+ AnalysisContext analysisContext = _context.compilationUnitElement.context;
+ try {
+ return (analysisContext as InternalAnalysisContext).typeProvider;
+ } on AnalysisException catch (exception) {
+ // TODO(brianwilkerson) Figure out the right thing to do if the core cannot be resolved.
+ return null;
+ }
+ }
+
+ bool get hasErrorBeforeCompletionLocation {
+ List<AnalysisError> errors = _context.errors;
+ if (errors == null || errors.length == 0) {
+ return false;
+ }
+ return errors[0].offset <= _completionLocation();
+ }
+
+ List<ImportElement> _importsWithName(SimpleIdentifier libName) {
+ String name = libName.name;
+ List<ImportElement> imports = [];
+ for (ImportElement imp in currentLibrary.imports) {
+ PrefixElement prefix = imp.prefix;
+ if (prefix != null) {
+ String impName = prefix.displayName;
+ if (name == impName) {
+ imports.add(imp);
+ }
+ }
+ }
+ return new List.from(imports);
+ }
+
+ bool _isCompletingKeyword(Token keyword) {
+ if (keyword == null) {
+ return false;
+ }
+ int completionLoc = _context.selectionOffset;
+ if (completionLoc >= keyword.offset && completionLoc <= keyword.end) {
+ return true;
+ }
+ return false;
+ }
+
+ bool _isCompletionAfter(int loc) => loc <= _completionLocation();
+
+ bool _isCompletionBefore(int loc) => _completionLocation() <= loc;
+
+ bool _isCompletionBetween(int firstLoc, int secondLoc) => _isCompletionAfter(firstLoc) && _isCompletionBefore(secondLoc);
+
+ bool _isDeprecated(Element element) => element != null && element.isDeprecated;
+
+ bool _isInCurrentLibrary(Element element) {
+ LibraryElement libElement = currentLibrary;
+ return identical(element.library, libElement);
+ }
+
+ bool _isUnitInLibFolder(CompilationUnitElement cu) {
+ String pathString = cu.source.fullName;
+ if (pathString.indexOf("/lib/") == -1) {
+ return false;
+ }
+ return true;
+ }
+
+ bool _isVisible(Element element) => !_isPrivate(element) || _isInCurrentLibrary(element);
+
+ String _makeNonconflictingName(String candidate, List<String> names) {
+ String possibility = candidate;
+ int count = 0;
+ loop: while (true) {
+ String name = count == 0 ? possibility : "${possibility}${count}";
+ for (String conflict in names) {
+ if (name == conflict) {
+ count += 1;
+ continue loop;
+ }
+ }
+ return name;
+ }
+ }
+
+ void _pArgumentList(CompletionProposal proposal, int offset, int len) {
+ // prepare parameters
+ List<String> parameterNames = proposal.parameterNames;
+ if (parameterNames.length == 0) {
+ return;
+ }
+ // fill arguments proposal
+ CompletionProposal prop = _createProposal4(ProposalKind.ARGUMENT_LIST);
+ prop.setElement(proposal.element);
+ prop.setCompletion(proposal.completion).setReturnType(proposal.returnType);
+ prop.setParameterNames(parameterNames);
+ prop.setParameterTypes(proposal.parameterTypes);
+ prop.setParameterStyle(proposal.positionalParameterCount, proposal.hasNamed, proposal.hasPositional);
+ prop.setReplacementLength(0).setLocation(_completionLocation());
+ prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
+ _requestor.accept(prop);
+ }
+
+ void _pDynamic() {
+ _pWord(_C_DYNAMIC, ProposalKind.VARIABLE);
+ }
+
+ void _pExecutable(Element element, FunctionType functionType, SimpleIdentifier identifier, bool isPotentialMatch) {
+ // Create a completion proposal for the element: function, method, getter, setter, constructor.
+ String name = element.displayName;
+ if (name.isEmpty) {
+ return;
+ }
+ if (_filterDisallows(element)) {
+ return;
+ }
+ if (!_isVisible(element)) {
+ return;
+ }
+ // May be we are in argument of function type parameter, propose function reference.
+ if (_state._targetParameter != null) {
+ DartType parameterType = _state._targetParameter.type;
+ if (parameterType is FunctionType) {
+ if (functionType.isAssignableTo(parameterType)) {
+ _pName2(name, element, CompletionProposal.RELEVANCE_HIGH, ProposalKind.METHOD_NAME);
+ }
+ }
+ }
+ CompletionProposal prop = _createProposal(element);
+ prop.setPotentialMatch(isPotentialMatch);
+ if (isPotentialMatch) {
+ prop.setRelevance(CompletionProposal.RELEVANCE_LOW);
+ }
+ _setParameterInfo(functionType, prop);
+ prop.setCompletion(name).setReturnType(functionType.returnType.displayName);
+ // If there is already argument list, then update only method name.
+ if (identifier.parent is MethodInvocation && (identifier.parent as MethodInvocation).argumentList != null) {
+ prop.setKind(ProposalKind.METHOD_NAME);
+ }
+ Element container = element.enclosingElement;
+ if (container != null) {
+ prop.setDeclaringType(container.displayName);
+ }
+ _requestor.accept(prop);
+ }
+
+ void _pExecutable2(ExecutableElement element, SimpleIdentifier identifier, bool isPotentialMatch) {
+ _pExecutable(element, element.type, identifier, isPotentialMatch);
+ }
+
+ void _pExecutable3(VariableElement element, SimpleIdentifier identifier) {
+ // Create a completion proposal for the element: top-level variable.
+ String name = element.displayName;
+ if (name.isEmpty || _filterDisallows(element)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal(element);
+ if (element.type != null) {
+ prop.setReturnType(element.type.name);
+ }
+ Element container = element.enclosingElement;
+ if (container != null) {
+ prop.setDeclaringType(container.displayName);
+ }
+ if (identifier != null) {
+ prop.setReplacementLengthIdentifier(identifier.length);
+ }
+ _requestor.accept(prop);
+ }
+
+ void _pFalse() {
+ _pWord(_C_FALSE, ProposalKind.VARIABLE);
+ }
+
+ void _pField(FieldElement element, SimpleIdentifier identifier, ClassElement classElement) {
+ // Create a completion proposal for the element: field only.
+ if (_filterDisallows(element)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal(element);
+ Element container = element.enclosingElement;
+ prop.setDeclaringType(container.displayName);
+ _requestor.accept(prop);
+ }
+
+ /**
+ * Proposes URI with the given scheme for the given [NamespaceDirective].
+ */
+ void _pImportUriWithScheme(NamespaceDirective node, String uriScheme) {
+ String newUri = "${uriScheme}${new String.fromCharCode(CompletionProposal.CURSOR_MARKER)}";
+ if (node.uri.isSynthetic) {
+ newUri = "'${newUri}'";
+ if (node.semicolon == null || node.semicolon.isSynthetic) {
+ newUri += ";";
+ }
+ }
+ if (_context.selectionOffset == node.keyword.end) {
+ newUri = " ${newUri}";
+ }
+ _pName3(newUri, ProposalKind.IMPORT);
+ }
+
+ void _pKeyword(Token keyword) {
+ _filter = new Filter.con2(keyword.lexeme, keyword.offset, _completionLocation());
+ // This isn't as useful as it might seem. It only works in the case that completion
+ // is requested on an existing recognizable keyword.
+ // TODO: Add keyword proposal kind
+ CompletionProposal prop = _createProposal4(ProposalKind.LIBRARY_PREFIX);
+ prop.setCompletion(keyword.lexeme);
+ _requestor.accept(prop);
+ }
+
+ void _pName(Element element, SimpleIdentifier identifier) {
+ CompletionProposal prop = _createProposal2(element, identifier);
+ if (prop != null) {
+ _requestor.accept(prop);
+ }
+ }
+
+ void _pName2(String name, Element element, int relevance, ProposalKind kind) {
+ if (_filterDisallows2(name)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal4(kind);
+ prop.setRelevance(relevance);
+ prop.setCompletion(name);
+ prop.setElement(element);
+ _requestor.accept(prop);
+ }
+
+ void _pName3(String name, ProposalKind kind) {
+ if (_filterDisallows2(name)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal4(kind);
+ prop.setCompletion(name);
+ _requestor.accept(prop);
+ }
+
+ void _pNamedConstructor(ClassElement classElement, ConstructorElement element, SimpleIdentifier identifier) {
+ // Create a completion proposal for the named constructor.
+ String name = classElement.displayName;
+ if (!element.displayName.isEmpty) {
+ name += ".${element.displayName}";
+ }
+ if (_filterDisallows2(name)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal3(element, name);
+ _setParameterInfo(element.type, prop);
+ prop.setReturnType(element.type.returnType.name);
+ Element container = element.enclosingElement;
+ prop.setDeclaringType(container.displayName);
+ if (identifier != null) {
+ prop.setReplacementLengthIdentifier(identifier.length);
+ }
+ _requestor.accept(prop);
+ }
+
+ void _pNull() {
+ _pWord(_C_NULL, ProposalKind.VARIABLE);
+ }
+
+ void _pParamName(String name) {
+ if (_filterDisallows2(name)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal4(ProposalKind.PARAMETER);
+ prop.setCompletion(name);
+ _requestor.accept(prop);
+ }
+
+ ProposalKind _proposalKindOf(Element element) {
+ ProposalKind kind;
+ while (true) {
+ if (element.kind == ElementKind.CONSTRUCTOR) {
+ kind = ProposalKind.CONSTRUCTOR;
+ } else if (element.kind == ElementKind.FUNCTION) {
+ kind = ProposalKind.FUNCTION;
+ } else if (element.kind == ElementKind.METHOD) {
+ kind = ProposalKind.METHOD;
+ } else if (element.kind == ElementKind.GETTER) {
+ kind = ProposalKind.GETTER;
+ } else if (element.kind == ElementKind.SETTER) {
+ kind = ProposalKind.SETTER;
+ } else if (element.kind == ElementKind.CLASS) {
+ kind = ProposalKind.CLASS;
+ } else if (element.kind == ElementKind.FIELD) {
+ kind = ProposalKind.FIELD;
+ } else if (element.kind == ElementKind.IMPORT) {
+ kind = ProposalKind.IMPORT;
+ } else if (element.kind == ElementKind.PARAMETER) {
+ kind = ProposalKind.PARAMETER;
+ } else if (element.kind == ElementKind.PREFIX) {
+ kind = ProposalKind.LIBRARY_PREFIX;
+ } else if (element.kind == ElementKind.FUNCTION_TYPE_ALIAS) {
+ kind = ProposalKind.CLASS_ALIAS;
+ } else if (element.kind == ElementKind.TYPE_PARAMETER) {
+ kind = ProposalKind.TYPE_PARAMETER;
+ } else if (element.kind == ElementKind.LOCAL_VARIABLE || element.kind == ElementKind.TOP_LEVEL_VARIABLE) {
+ kind = ProposalKind.VARIABLE;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ break;
+ }
+ return kind;
+ }
+
+ void _proposeCombinator(Combinator node, SimpleIdentifier identifier) {
+ _filter = _createFilter(identifier);
+ NamespaceDirective directive = node.parent as NamespaceDirective;
+ LibraryElement libraryElement = directive.uriElement;
+ if (libraryElement != null) {
+ // prepare Elements with unique names
+ CompletionEngine_NameCollector nameCollector = _createNameCollector();
+ Iterable<Element> elements = CorrectionUtils.getExportNamespace2(libraryElement).values;
+ for (Element element in elements) {
+ if (_filterDisallows(element)) {
+ continue;
+ }
+ nameCollector._mergeName(element);
+ }
+ // propose each Element
+ for (Element element in nameCollector.uniqueElements) {
+ CompletionProposal proposal = _createProposal(element);
+ if (proposal.kind == ProposalKind.FUNCTION) {
+ proposal.setKind(ProposalKind.METHOD_NAME);
+ }
+ _requestor.accept(proposal);
+ }
+ }
+ }
+
+ void _proposeName(Element element, SimpleIdentifier identifier, CompletionEngine_NameCollector names) {
+ while (true) {
+ if (element.kind == ElementKind.FUNCTION || element.kind == ElementKind.GETTER || element.kind == ElementKind.METHOD || element.kind == ElementKind.SETTER) {
+ ExecutableElement candidate = element as ExecutableElement;
+ _pExecutable2(candidate, identifier, names._isPotentialMatch(candidate));
+ } else if (element.kind == ElementKind.LOCAL_VARIABLE || element.kind == ElementKind.PARAMETER || element.kind == ElementKind.TOP_LEVEL_VARIABLE) {
+ FunctionType functionType = _getFunctionType(element);
+ if (functionType != null) {
+ _pExecutable(element, functionType, identifier, names._isPotentialMatch(element));
+ } else {
+ VariableElement var2 = element as VariableElement;
+ _pExecutable3(var2, identifier);
+ }
+ } else if (element.kind == ElementKind.CLASS) {
+ _pName(element, identifier);
+ } else {
+ }
+ break;
+ }
+ }
+
+ void _proposeNames(CompletionEngine_NameCollector names, SimpleIdentifier identifier) {
+ for (Element element in names.uniqueElements) {
+ _proposeName(element, identifier, names);
+ }
+ }
+
+ void _pTrue() {
+ _pWord(_C_TRUE, ProposalKind.VARIABLE);
+ }
+
+ void _pVar() {
+ _pWord(_C_VAR, ProposalKind.VARIABLE);
+ }
+
+ void _pVoid() {
+ _pWord(_C_VOID, ProposalKind.VARIABLE);
+ }
+
+ void _pWord(String word, ProposalKind kind) {
+ if (_filterDisallows2(word)) {
+ return;
+ }
+ CompletionProposal prop = _createProposal4(kind);
+ prop.setCompletion(word);
+ _requestor.accept(prop);
+ }
+
+ void _removeNotMatchingFilter(List<Element> elements) {
+ if (_filter == null) {
+ return;
+ }
+ _filter._makePattern();
+ _filter._removeNotMatching(elements);
+ }
+
+ void _setParameterInfo(FunctionType functionType, CompletionProposal prop) {
+ List<String> params = new List<String>();
+ List<String> types = new List<String>();
+ bool named = false, positional = false;
+ int posCount = 0;
+ for (ParameterElement param in functionType.parameters) {
+ if (!param.isSynthetic) {
+ while (true) {
+ if (param.parameterKind == ParameterKind.REQUIRED) {
+ posCount += 1;
+ } else if (param.parameterKind == ParameterKind.NAMED) {
+ named = true;
+ } else if (param.parameterKind == ParameterKind.POSITIONAL) {
+ positional = true;
+ }
+ break;
+ }
+ params.add(param.displayName);
+ types.add(param.type.toString());
+ }
+ }
+ prop.setParameterNames(new List.from(params));
+ prop.setParameterTypes(new List.from(types));
+ prop.setParameterStyle(posCount, named, positional);
+ }
+
+ SimpleIdentifier _typeDeclarationName(AstNode node) {
+ AstNode parent = node;
+ while (parent != null) {
+ if (parent is ClassDeclaration) {
+ return (parent as ClassDeclaration).name;
+ }
+ if (parent is ClassTypeAlias) {
+ return (parent as ClassTypeAlias).name;
+ }
+ if (parent is FunctionTypeAlias) {
+ return (parent as FunctionTypeAlias).name;
+ }
+ parent = parent.parent;
+ }
+ return null;
+ }
+
+ DartType _typeOf(Element receiver) {
+ DartType receiverType;
+ while (true) {
+ if (receiver.kind == ElementKind.FIELD || receiver.kind == ElementKind.PARAMETER || receiver.kind == ElementKind.LOCAL_VARIABLE || receiver.kind == ElementKind.TOP_LEVEL_VARIABLE) {
+ {
+ VariableElement receiverElement = receiver as VariableElement;
+ receiverType = receiverElement.type;
+ break;
+ }
+ } else if (receiver.kind == ElementKind.GETTER) {
+ PropertyAccessorElement accessor = receiver as PropertyAccessorElement;
+ if (accessor.isSynthetic) {
+ PropertyInducingElement inducer = accessor.variable;
+ DartType inducerType = inducer.type;
+ if (inducerType == null || inducerType.isDynamic) {
+ receiverType = _typeSearch(inducer);
+ if (receiverType != null) {
+ break;
+ }
+ }
+ }
+ FunctionType accType = accessor.type;
+ receiverType = accType == null ? null : accType.returnType;
+ } else if (receiver.kind == ElementKind.CONSTRUCTOR || receiver.kind == ElementKind.FUNCTION || receiver.kind == ElementKind.METHOD || receiver.kind == ElementKind.SETTER) {
+ {
+ ExecutableElement receiverElement = receiver as ExecutableElement;
+ FunctionType funType = receiverElement.type;
+ receiverType = funType == null ? null : funType.returnType;
+ break;
+ }
+ } else if (receiver.kind == ElementKind.CLASS) {
+ {
+ ClassElement receiverElement = receiver as ClassElement;
+ receiverType = receiverElement.type;
+ break;
+ }
+ } else if (receiver.kind == ElementKind.DYNAMIC) {
+ {
+ receiverType = DynamicTypeImpl.instance;
+ break;
+ }
+ } else if (receiver.kind == ElementKind.FUNCTION_TYPE_ALIAS) {
+ {
+ FunctionTypeAliasElement receiverElement = receiver as FunctionTypeAliasElement;
+ FunctionType funType = receiverElement.type;
+ receiverType = funType == null ? null : funType.returnType;
+ break;
+ }
+ } else {
+ {
+ receiverType = null;
+ break;
+ }
+ }
+ break;
+ }
+ return receiverType;
+ }
+
+ DartType _typeOf2(Expression expr) {
+ DartType type = expr.bestType;
+ if (type.isDynamic) {
+ List<DartType> result = new List<DartType>(1);
+ CompletionEngine_AstNodeClassifier visitor = new AstNodeClassifier_CompletionEngine_typeOf(this, result);
+ expr.accept(visitor);
+ if (result[0] != null) {
+ return result[0];
+ }
+ }
+ return type;
+ }
+
+ DartType _typeOfContainingClass(AstNode node) {
+ AstNode parent = node;
+ while (parent != null) {
+ if (parent is ClassDeclaration) {
+ return (parent as ClassDeclaration).element.type;
+ }
+ parent = parent.parent;
+ }
+ return DynamicTypeImpl.instance;
+ }
+
+ DartType _typeSearch(PropertyInducingElement varElement) {
+ // TODO(scheglov) translate it
+ return null;
+ }
+}
+
+abstract class CompletionEngine_AstNodeClassifier extends GeneralizingAstVisitor<Object> {
+ @override
+ Object visitNode(AstNode node) => null;
+}
+
+class CompletionEngine_CommentReferenceCompleter extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ final SimpleIdentifier _identifier;
+
+ CompletionEngine_NameCollector _names;
+
+ Set<Element> _enclosingElements = new Set();
+
+ CompletionEngine_CommentReferenceCompleter(this.CompletionEngine_this, this._identifier) {
+ CompletionEngine_this._filter = CompletionEngine_this._createFilter(_identifier);
+ _names = CompletionEngine_this._collectTopLevelElementVisibleAt(_identifier);
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ ClassElement classElement = node.element;
+ _names._addNamesDefinedByHierarchy(classElement, false);
+ _enclosingElements.add(classElement);
+ return null;
+ }
+
+ @override
+ Object visitComment(Comment node) {
+ node.parent.accept(this);
+ // propose names
+ for (Element element in _names.uniqueElements) {
+ CompletionProposal proposal = CompletionEngine_this._createProposal2(element, _identifier);
+ if (proposal != null) {
+ // we don't want to add arguments, just names
+ if (element is MethodElement || element is FunctionElement) {
+ proposal.setKind(ProposalKind.METHOD_NAME);
+ }
+ // elevate priority for local elements
+ if (_enclosingElements.contains(element.enclosingElement)) {
+ proposal.setRelevance(CompletionProposal.RELEVANCE_HIGH);
+ }
+ // propose
+ CompletionEngine_this._requestor.accept(proposal);
+ }
+ }
+ // done
+ return null;
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ _visitExecutableDeclaration(node);
+ // pass through
+ return node.parent.accept(this);
+ }
+
+ @override
+ Object visitFunctionDeclaration(FunctionDeclaration node) {
+ _visitExecutableDeclaration(node);
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ FunctionTypeAliasElement element = node.element;
+ _names._mergeNames(element.parameters);
+ _enclosingElements.add(element);
+ return null;
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ _visitExecutableDeclaration(node);
+ // pass through
+ return node.parent.accept(this);
+ }
+
+ void _visitExecutableDeclaration(Declaration node) {
+ ExecutableElement element = node.element as ExecutableElement;
+ _names._mergeNames(element.parameters);
+ _enclosingElements.add(element);
+ }
+}
+
+/**
+ * An IdentifierCompleter is used to classify the parent of the completion node when it has
+ * previously been determined that the completion node is a SimpleIdentifier.
+ */
+class CompletionEngine_IdentifierCompleter extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ SimpleIdentifier _completionNode;
+
+ CompletionEngine_IdentifierCompleter(this.CompletionEngine_this, SimpleIdentifier node) {
+ _completionNode = node;
+ }
+
+ @override
+ Object visitAnnotation(Annotation node) {
+ if (_completionNode is SimpleIdentifier) {
+ CompletionEngine_this._analyzeAnnotationName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitArgumentList(ArgumentList node) {
+ if (_completionNode is SimpleIdentifier) {
+ if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, node.rightParenthesis.offset)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ CompletionEngine_this._analyzePositionalArgument(node, _completionNode);
+ CompletionEngine_this._analyzeNamedParameter(node, _completionNode);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitAssignmentExpression(AssignmentExpression node) {
+ if (_completionNode is SimpleIdentifier) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitBinaryExpression(BinaryExpression node) {
+ if (identical(node.leftOperand, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ } else if (identical(node.rightOperand, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitCombinator(Combinator node) {
+ CompletionEngine_this._proposeCombinator(node, _completionNode);
+ return null;
+ }
+
+ @override
+ Object visitCommentReference(CommentReference node) {
+ AstNode comment = node.parent;
+ CompletionEngine_CommentReferenceCompleter visitor = new CompletionEngine_CommentReferenceCompleter(CompletionEngine_this, _completionNode);
+ return comment.accept(visitor);
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ if (identical(node.returnType, _completionNode)) {
+ CompletionEngine_this._filter = CompletionEngine_this._createFilter(_completionNode);
+ CompletionEngine_this._pName3(_completionNode.name, ProposalKind.CONSTRUCTOR);
+ }
+ return null;
+ }
+
+ @override
+ Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ // { A() : this.!x = 1; }
+ if (identical(node.fieldName, _completionNode)) {
+ ClassElement classElement = (node.parent as ConstructorDeclaration).element.enclosingElement;
+ CompletionEngine_this._fieldReference(classElement, node.fieldName);
+ }
+ return null;
+ }
+
+ @override
+ Object visitConstructorName(ConstructorName node) {
+ if (identical(node.name, _completionNode)) {
+ // { new A.!c(); }
+ TypeName typeName = node.type;
+ if (typeName != null) {
+ DartType type = typeName.type;
+ Element typeElement = type.element;
+ if (typeElement is ClassElement) {
+ ClassElement classElement = typeElement;
+ CompletionEngine_this._constructorReference(classElement, node.name);
+ }
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitDoStatement(DoStatement node) {
+ if (identical(node.condition, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitExpression(Expression node) {
+ SimpleIdentifier ident;
+ if (_completionNode is SimpleIdentifier) {
+ ident = _completionNode;
+ } else {
+ ident = CompletionEngine_this._createIdent(node);
+ }
+ CompletionEngine_this._analyzeLocalName(ident);
+ return null;
+ }
+
+ @override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ if (identical(_completionNode, node.expression)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitExpressionStatement(ExpressionStatement node) {
+ SimpleIdentifier ident;
+ if (_completionNode is SimpleIdentifier) {
+ ident = _completionNode;
+ } else {
+ ident = CompletionEngine_this._createIdent(node);
+ }
+ CompletionEngine_this._analyzeLocalName(ident);
+ return null;
+ }
+
+ @override
+ Object visitFieldFormalParameter(FieldFormalParameter node) {
+ if (identical(_completionNode, node.identifier)) {
+ CompletionEngine_this._analyzeImmediateField(node.identifier);
+ }
+ return null;
+ }
+
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ if (identical(node.iterator, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ if (identical(node.name, _completionNode)) {
+ if (node.returnType == null) {
+ // This may be an incomplete class type alias
+ CompletionEngine_this._state._includesUndefinedTypes();
+ CompletionEngine_this._analyzeTypeName(node.name, CompletionEngine_this._typeDeclarationName(node));
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitIfStatement(IfStatement node) {
+ if (identical(node.condition, _completionNode)) {
+ // { if (!) }
+ CompletionEngine_this._analyzeLocalName(new Ident.con3(node, _completionNode.token));
+ }
+ return null;
+ }
+
+ @override
+ Object visitInterpolationExpression(InterpolationExpression node) {
+ if (node.expression is SimpleIdentifier) {
+ SimpleIdentifier ident = node.expression as SimpleIdentifier;
+ CompletionEngine_this._analyzeLocalName(ident);
+ }
+ return null;
+ }
+
+ @override
+ Object visitLibraryIdentifier(LibraryIdentifier node) => null;
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ if (identical(_completionNode, node.name)) {
+ if (node.returnType == null) {
+ // class Foo {const F!(); }
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitMethodInvocation(MethodInvocation node) {
+ if (identical(node.methodName, _completionNode)) {
+ // { x.!y() }
+ Expression expr = node.realTarget;
+ DartType receiverType;
+ if (expr == null) {
+ receiverType = CompletionEngine_this._typeOfContainingClass(node);
+ CompletionEngine_this._analyzeDirectAccess(receiverType, node.methodName);
+ } else {
+ CompletionEngine_this._dispatchPrefixAnalysis2(node);
+ }
+ } else if (identical(node.target, _completionNode)) {
+ // { x!.y() } -- only reached when node.getTarget() is a simple identifier.
+ if (_completionNode is SimpleIdentifier) {
+ SimpleIdentifier ident = _completionNode;
+ CompletionEngine_this._analyzeReceiver(ident);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitParenthesizedExpression(ParenthesizedExpression node) {
+ // Incomplete closure: foo((Str!)); We check if "()" is argument for function typed parameter.
+ if (node.parent is ArgumentList) {
+ ParameterElement parameterElement = node.bestParameterElement;
+ if (parameterElement != null && parameterElement.type is FunctionType) {
+ Ident ident = CompletionEngine_this._createIdent(_completionNode);
+ CompletionEngine_this._analyzeTypeName(_completionNode, ident);
+ }
+ }
+ return super.visitParenthesizedExpression(node);
+ }
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (identical(node.prefix, _completionNode)) {
+ // { x!.y }
+ CompletionEngine_this._analyzeLocalName(node.prefix);
+ } else {
+ // { v.! }
+ CompletionEngine_this._dispatchPrefixAnalysis3(node, node.identifier);
+ }
+ return null;
+ }
+
+ @override
+ Object visitPropertyAccess(PropertyAccess node) {
+ if (node.target != null && node.target.length == 0) {
+ return null;
+ }
+ // { o.!hashCode }
+ if (identical(node.propertyName, _completionNode)) {
+ CompletionEngine_this._analyzePrefixedAccess(node.realTarget, node.propertyName);
+ }
+ return null;
+ }
+
+ @override
+ Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
+ // { A.Fac() : this.!b(); }
+ if (identical(node.constructorName, _completionNode)) {
+ ClassElement classElement = node.staticElement.enclosingElement;
+ CompletionEngine_this._constructorReference(classElement, node.constructorName);
+ }
+ return null;
+ }
+
+ @override
+ Object visitReturnStatement(ReturnStatement node) {
+ if (_completionNode is SimpleIdentifier) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ if (identical(node.identifier, _completionNode)) {
+ if (node.keyword == null && node.type == null) {
+ Ident ident = CompletionEngine_this._createIdent(node);
+ CompletionEngine_this._analyzeTypeName(node.identifier, ident);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ CompletionEngine_this._analyzeSuperConstructorInvocation(node);
+ return null;
+ }
+
+ @override
+ Object visitSwitchCase(SwitchCase node) {
+ if (identical(_completionNode, node.expression)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSwitchStatement(SwitchStatement node) {
+ if (identical(node.expression, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTypeName(TypeName node) {
+ AstNode parent = node.parent;
+ if (parent != null) {
+ CompletionEngine_TypeNameCompleter visitor = new CompletionEngine_TypeNameCompleter(CompletionEngine_this, _completionNode, node);
+ return parent.accept(visitor);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTypeParameter(TypeParameter node) {
+ // { X<!Y> }
+ if (CompletionEngine_this._isCompletionBetween(node.offset, node.end)) {
+ CompletionEngine_this._analyzeTypeName(_completionNode, CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ if (identical(node.name, _completionNode)) {
+ CompletionEngine_this._analyzeDeclarationName(node);
+ } else if (identical(node.initializer, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(node.initializer as SimpleIdentifier);
+ }
+ return null;
+ }
+
+ @override
+ Object visitWhileStatement(WhileStatement node) {
+ if (identical(node.condition, _completionNode)) {
+ CompletionEngine_this._analyzeLocalName(_completionNode);
+ }
+ return null;
+ }
+}
+
+class CompletionEngine_NameCollector {
+ final CompletionEngine CompletionEngine_this;
+
+ Map<String, List<Element>> _uniqueNames = new Map<String, List<Element>>();
+
+ Set<Element> _potentialMatches;
+
+ CompletionEngine_NameCollector(this.CompletionEngine_this);
+
+ void addAll(Iterable<SimpleIdentifier> values) {
+ for (SimpleIdentifier id in values) {
+ _mergeName(id.bestElement);
+ }
+ }
+
+ void addLocalNames(SimpleIdentifier identifier) {
+ AstNode node = identifier;
+ Declaration decl;
+ while ((decl = node.getAncestor((node) => node is Declaration)) != null) {
+ Element declElement = decl.element;
+ if (declElement is ExecutableElement) {
+ _addNamesDefinedByExecutable(declElement);
+ } else {
+ return;
+ }
+ node = decl.parent;
+ }
+ }
+
+ void _addNamesDefinedByExecutable(ExecutableElement execElement) {
+ _mergeNames(execElement.parameters);
+ _mergeNames(execElement.localVariables);
+ _mergeNames(execElement.functions);
+ }
+
+ void _addNamesDefinedByHierarchy(ClassElement classElement, bool forSuper) {
+ _addNamesDefinedByHierarchy2(classElement.type, forSuper);
+ }
+
+ void _addNamesDefinedByHierarchy2(InterfaceType type, bool forSuper) {
+ List<InterfaceType> superTypes = type.element.allSupertypes;
+ if (!forSuper) {
+ superTypes = ArrayUtils.add(superTypes, 0, type);
+ }
+ _addNamesDefinedByTypes(superTypes);
+ // Collect names defined by subtypes separately so they can be identified later.
+ CompletionEngine_NameCollector potentialMatchCollector = CompletionEngine_this._createNameCollector();
+ if (!type.isObject) {
+ potentialMatchCollector._addNamesDefinedByTypes(CompletionEngine_this._allSubtypes(type.element));
+ }
+ _potentialMatches = new Set<Element>();
+ for (List<Element> matches in potentialMatchCollector._uniqueNames.values) {
+ for (Element match in matches) {
+ _mergeName(match);
+ _potentialMatches.add(match);
+ }
+ }
+ }
+
+ void _addNamesDefinedByType(ClassElement classElement) {
+ _addNamesDefinedByType2(classElement.type);
+ }
+
+ void _addNamesDefinedByType2(InterfaceType type) {
+ if (_inPrivateLibrary(type)) {
+ return;
+ }
+ List<PropertyAccessorElement> accessors = type.accessors;
+ _mergeNames(accessors);
+ List<MethodElement> methods = type.methods;
+ _mergeNames(methods);
+ _mergeNames(type.element.typeParameters);
+ _filterStaticRefs(accessors);
+ _filterStaticRefs(methods);
+ }
+
+ void _addNamesDefinedByTypes(List<InterfaceType> types) {
+ for (InterfaceType type in types) {
+ _addNamesDefinedByType2(type);
+ }
+ }
+
+ void _addTopLevelNames(List<ImportElement> imports, TopLevelNamesKind topKind) {
+ for (ImportElement imp in imports) {
+ Iterable<Element> elementsCollection = CorrectionUtils.getImportNamespace(imp).values;
+ List<Element> elements = [];
+ _addTopLevelNames4(elements);
+ }
+ }
+
+ void _addTopLevelNames2(LibraryElement library, TopLevelNamesKind topKind) {
+ List<Element> elements = CompletionEngine_this._findTopLevelElements(library, topKind);
+ _addTopLevelNames4(elements);
+ }
+
+ void _addTopLevelNames3(List<LibraryElement> libraries, TopLevelNamesKind topKind) {
+ for (LibraryElement library in libraries) {
+ _addTopLevelNames2(library, topKind);
+ }
+ }
+
+ Iterable<List<Element>> get names => _uniqueNames.values;
+
+ Iterable<Element> get uniqueElements {
+ List<Element> uniqueElements = [];
+ for (List<Element> uniques in _uniqueNames.values) {
+ Element element = uniques[0];
+ uniqueElements.add(element);
+ }
+ return uniqueElements;
+ }
+
+ bool _isPotentialMatch(Element element) => _potentialMatches != null && _potentialMatches.contains(element);
+
+ void _remove(Element element) {
+ String name = element.displayName;
+ List<Element> list = _uniqueNames[name];
+ if (list == null) {
+ return;
+ }
+ list.remove(element);
+ if (list.isEmpty) {
+ _uniqueNames.remove(name);
+ }
+ }
+
+ void _addTopLevelNames4(List<Element> elements) {
+ _mergeNames(CompletionEngine_this._findAllTypes2(elements));
+ if (!CompletionEngine_this._state._areClassesRequired) {
+ _mergeNames(CompletionEngine_this._findAllNotTypes(elements));
+ _mergeNames(CompletionEngine_this._findAllPrefixes());
+ }
+ }
+
+ void _filterStaticRefs(List<ExecutableElement> elements) {
+ for (ExecutableElement execElem in elements) {
+ if (CompletionEngine_this._state._areInstanceReferencesProhibited && !execElem.isStatic) {
+ _remove(execElem);
+ } else if (CompletionEngine_this._state._areStaticReferencesProhibited && execElem.isStatic) {
+ _remove(execElem);
+ } else if (!CompletionEngine_this._state._areOperatorsAllowed && execElem.isOperator) {
+ _remove(execElem);
+ } else if (CompletionEngine_this._state._areMethodsProhibited && !execElem.isOperator) {
+ _remove(execElem);
+ }
+ }
+ }
+
+ bool _inPrivateLibrary(InterfaceType type) {
+ LibraryElement lib = type.element.library;
+ if (!lib.name.startsWith("_")) {
+ return false;
+ }
+ // allow completion in the same library
+ if (identical(lib, CompletionEngine_this.currentLibrary)) {
+ return false;
+ }
+ // eliminate types defined in private libraries
+ return true;
+ }
+
+ void _mergeName(Element element) {
+ if (element == null) {
+ return;
+ }
+ // ignore private
+ String name = element.displayName;
+ if (Identifier.isPrivateName(name)) {
+ if (!CompletionEngine_this._isInCurrentLibrary(element)) {
+ return;
+ }
+ }
+ // add to other Element(s) with such name
+ List<Element> dups = _uniqueNames[name];
+ if (dups == null) {
+ dups = new List<Element>();
+ _uniqueNames[name] = dups;
+ }
+ dups.add(element);
+ }
+
+ void _mergeNames(List<Element> elements) {
+ for (Element element in elements) {
+ _mergeName(element);
+ }
+ }
+}
+
+/**
+ * An StringCompleter is used to classify the parent of the completion node when it has previously
+ * been determined that the completion node is a SimpleStringLiteral.
+ */
+class CompletionEngine_StringCompleter extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ SimpleStringLiteral _completionNode;
+
+ CompletionEngine_StringCompleter(this.CompletionEngine_this, SimpleStringLiteral node) {
+ _completionNode = node;
+ }
+
+ @override
+ Object visitNamespaceDirective(NamespaceDirective node) {
+ if (identical(_completionNode, node.uri)) {
+ CompletionEngine_this._namespaceReference(node, _completionNode);
+ }
+ return null;
+ }
+}
+
+/**
+ * A TerminalNodeCompleter is used to classify the completion node when nothing else is known
+ * about it.
+ */
+class CompletionEngine_TerminalNodeCompleter extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ CompletionEngine_TerminalNodeCompleter(this.CompletionEngine_this);
+
+ @override
+ Object visitArgumentList(ArgumentList node) {
+ if (node.arguments.isEmpty && CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, node.rightParenthesis.offset)) {
+ if (node.parent is MethodInvocation) {
+ // or node.getParent().accept(this); ?
+ MethodInvocation invokeNode = node.parent as MethodInvocation;
+ SimpleIdentifier methodName = invokeNode.methodName;
+ ProposalCollector proposalRequestor = new ProposalCollector(CompletionEngine_this._requestor);
+ try {
+ CompletionEngine_this._requestor = proposalRequestor;
+ CompletionEngine_this._dispatchPrefixAnalysis2(invokeNode);
+ } finally {
+ CompletionEngine_this._requestor = proposalRequestor.requestor;
+ }
+ int offset = methodName.offset;
+ int len = node.rightParenthesis.end - offset;
+ String name = methodName.name;
+ for (CompletionProposal proposal in proposalRequestor.proposals) {
+ if (proposal.completion == name) {
+ CompletionEngine_this._pArgumentList(proposal, offset, len);
+ }
+ }
+ } else if (node.parent is InstanceCreationExpression) {
+ InstanceCreationExpression invokeNode = node.parent as InstanceCreationExpression;
+ ConstructorName methodName = invokeNode.constructorName;
+ ProposalCollector proposalRequestor = new ProposalCollector(CompletionEngine_this._requestor);
+ try {
+ CompletionEngine_this._requestor = proposalRequestor;
+ CompletionEngine_this._dispatchPrefixAnalysis(invokeNode);
+ } finally {
+ CompletionEngine_this._requestor = proposalRequestor.requestor;
+ }
+ int offset = methodName.offset;
+ int len = node.rightParenthesis.end - offset;
+ for (CompletionProposal proposal in proposalRequestor.proposals) {
+ if (proposal.element == invokeNode.staticElement) {
+ CompletionEngine_this._pArgumentList(proposal, offset, len);
+ }
+ }
+ } else if (node.parent is Annotation) {
+ Annotation annotation = node.parent as Annotation;
+ Element annotationElement = annotation.element;
+ if (annotationElement is ConstructorElement) {
+ ConstructorElement constructorElement = annotationElement;
+ // we don't need any filter
+ CompletionEngine_this._filter = new Filter.con2("", -1, 0);
+ // fill parameters for "pArgumentList"
+ CompletionProposal prop = CompletionEngine_this._createProposal(constructorElement);
+ CompletionEngine_this._setParameterInfo(constructorElement.type, prop);
+ prop.setCompletion(constructorElement.enclosingElement.name);
+ // propose the whole parameters list
+ CompletionEngine_this._pArgumentList(prop, 0, 0);
+ }
+ }
+ }
+ if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, node.rightParenthesis.offset)) {
+ Ident ident = CompletionEngine_this._createIdent(node);
+ CompletionEngine_this._analyzeLocalName(ident);
+ CompletionEngine_this._analyzePositionalArgument(node, ident);
+ CompletionEngine_this._analyzeNamedParameter(node, ident);
+ }
+ return null;
+ }
+
+ @override
+ Object visitAsExpression(AsExpression node) {
+ if (CompletionEngine_this._isCompletionAfter(node.asOperator.end)) {
+ CompletionEngine_this._state._isDynamicAllowed = false;
+ CompletionEngine_this._state._isVoidAllowed = false;
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitAssertStatement(AssertStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitBlock(Block node) {
+ if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.rightBracket.offset)) {
+ // { {! stmt; !} }
+ CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitBooleanLiteral(BooleanLiteral node) {
+ CompletionEngine_this._analyzeLiteralReference(node);
+ return null;
+ }
+
+ @override
+ Object visitBreakStatement(BreakStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.onKeyword)) {
+ CompletionEngine_this._pKeyword(node.onKeyword);
+ } else if (CompletionEngine_this._isCompletingKeyword(node.catchKeyword)) {
+ CompletionEngine_this._pKeyword(node.catchKeyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.classKeyword)) {
+ CompletionEngine_this._pKeyword(node.classKeyword);
+ } else if (CompletionEngine_this._isCompletingKeyword(node.abstractKeyword)) {
+ CompletionEngine_this._pKeyword(node.abstractKeyword);
+ } else if (!node.leftBracket.isSynthetic) {
+ if (CompletionEngine_this._isCompletionAfter(node.leftBracket.end)) {
+ if (node.rightBracket.isSynthetic || CompletionEngine_this._isCompletionBefore(node.rightBracket.offset)) {
+ if (!CompletionEngine_this.hasErrorBeforeCompletionLocation) {
+ CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(node));
+ }
+ }
+ }
+ }
+ // TODO { abstract ! class ! A ! extends B implements C, D ! {}}
+ return null;
+ }
+
+ @override
+ Object visitClassTypeAlias(ClassTypeAlias node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ // TODO { typedef ! A ! = ! B ! with C, D !; }
+ return null;
+ }
+
+ @override
+ Object visitCombinator(Combinator node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitCompilationUnit(CompilationUnit node) => null;
+
+ @override
+ Object visitConstructorName(ConstructorName node) {
+ // { new A.!c(); }
+ TypeName typeName = node.type;
+ if (typeName != null) {
+ DartType type = typeName.type;
+ Element typeElement = type.element;
+ if (typeElement is ClassElement) {
+ ClassElement classElement = typeElement;
+ CompletionEngine_this._constructorReference(classElement, node.name);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitContinueStatement(ContinueStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitDirective(Directive node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitDoStatement(DoStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.doKeyword)) {
+ CompletionEngine_this._pKeyword(node.doKeyword);
+ } else if (CompletionEngine_this._isCompletingKeyword(node.whileKeyword)) {
+ CompletionEngine_this._pKeyword(node.whileKeyword);
+ } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, node.rightParenthesis.offset)) {
+ CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_this._createIdent(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitDoubleLiteral(DoubleLiteral node) => null;
+
+ @override
+ Object visitExportDirective(ExportDirective node) {
+ visitNamespaceDirective(node);
+ return null;
+ }
+
+ @override
+ Object visitExpression(Expression node) {
+ CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(node));
+ return null;
+ }
+
+ @override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ if (node.expression != null && node.semicolon != null) {
+ if (CompletionEngine_this._isCompletionBetween(node.expression.end, node.semicolon.offset)) {
+ CompletionEngine_this._operatorAccess(node.expression, CompletionEngine_this._createIdent(node));
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitExpressionStatement(ExpressionStatement node) {
+ CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(node));
+ return null;
+ }
+
+ @override
+ Object visitExtendsClause(ExtendsClause node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ } else if (node.superclass == null) {
+ // { X extends ! }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ } else {
+ // { X extends ! Y }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.forKeyword)) {
+ CompletionEngine_this._pKeyword(node.forKeyword);
+ } else if (CompletionEngine_this._isCompletingKeyword(node.inKeyword)) {
+ CompletionEngine_this._pKeyword(node.inKeyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitFormalParameterList(FormalParameterList node) {
+ if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, node.rightParenthesis.offset)) {
+ NodeList<FormalParameter> params = node.parameters;
+ if (!params.isEmpty) {
+ FormalParameter last = params[params.length - 1];
+ if (CompletionEngine_this._isCompletionBetween(last.end, node.rightParenthesis.offset)) {
+ List<FormalParameter> newParams = CompletionEngine_this._copyWithout(params, last);
+ CompletionEngine_this._analyzeNewParameterName(newParams, last.identifier, null);
+ } else {
+ Ident ident = CompletionEngine_this._createIdent(node);
+ CompletionEngine_this._analyzeTypeName(ident, ident);
+ }
+ } else {
+ Ident ident = CompletionEngine_this._createIdent(node);
+ CompletionEngine_this._analyzeTypeName(ident, ident);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitForStatement(ForStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.forKeyword)) {
+ CompletionEngine_this._pKeyword(node.forKeyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitIfStatement(IfStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.ifKeyword)) {
+ CompletionEngine_this._pKeyword(node.ifKeyword);
+ } else if (CompletionEngine_this._isCompletingKeyword(node.elseKeyword)) {
+ CompletionEngine_this._pKeyword(node.elseKeyword);
+ } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, node.rightParenthesis.offset)) {
+ CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_this._createIdent(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitImplementsClause(ImplementsClause node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ } else if (node.interfaces.isEmpty) {
+ // { X implements ! }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ } else {
+ // { X implements ! Y }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitImportDirective(ImportDirective node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.asToken)) {
+ CompletionEngine_this._pKeyword(node.asToken);
+ } else {
+ visitNamespaceDirective(node);
+ }
+ return null;
+ }
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ Ident ident = new Ident.con3(node, node.keyword);
+ CompletionEngine_this._analyzeLocalName(ident);
+ } else {
+ Ident ident = CompletionEngine_this._createIdent(node);
+ CompletionEngine_this._analyzeConstructorTypeName(ident);
+ }
+ return null;
+ }
+
+ @override
+ Object visitIsExpression(IsExpression node) {
+ Ident ident;
+ Token isToken = node.isOperator;
+ int isTokenEnd = isToken.end;
+ if (isTokenEnd == CompletionEngine_this._completionLocation()) {
+ Expression expression = node.expression;
+ int offset = isToken.offset;
+ // { target.is! } possible name completion, parsed as "target.{synthetic} is!"
+ if (expression is PrefixedIdentifier) {
+ PrefixedIdentifier prefIdent = expression;
+ if (prefIdent.identifier.isSynthetic) {
+ CompletionEngine_this._analyzePrefixedAccess(prefIdent.prefix, new Ident.con2(node, "is", offset));
+ } else {
+ CompletionEngine_this._pKeyword(isToken);
+ }
+ return null;
+ }
+ // { expr is! }
+ if (!CompletionEngine._isSyntheticIdentifier(expression)) {
+ CompletionEngine_this._pKeyword(node.isOperator);
+ return null;
+ }
+ // { is! } possible name completion
+ ident = new Ident.con2(node, "is", offset);
+ } else if (CompletionEngine_this._isCompletionAfter(isTokenEnd)) {
+ CompletionEngine_this._state._isDynamicAllowed = false;
+ CompletionEngine_this._state._isVoidAllowed = false;
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), null);
+ return null;
+ } else {
+ ident = CompletionEngine_this._createIdent(node);
+ }
+ CompletionEngine_this._analyzeLocalName(ident);
+ return null;
+ }
+
+ @override
+ Object visitLibraryIdentifier(LibraryIdentifier node) => null;
+
+ @override
+ Object visitMethodInvocation(MethodInvocation node) {
+ Token period = node.period;
+ if (period != null && CompletionEngine_this._isCompletionAfter(period.end)) {
+ // { x.!y() }
+ CompletionEngine_this._dispatchPrefixAnalysis2(node);
+ }
+ return null;
+ }
+
+ @override
+ Object visitNamespaceDirective(NamespaceDirective node) {
+ StringLiteral uri = node.uri;
+ if (uri != null && uri.isSynthetic && node.keyword.end <= CompletionEngine_this._context.selectionOffset) {
+ uri.accept(this);
+ }
+ return super.visitNamespaceDirective(node);
+ }
+
+ @override
+ Object visitPartOfDirective(PartOfDirective node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.ofToken)) {
+ CompletionEngine_this._pKeyword(node.ofToken);
+ } else {
+ visitDirective(node);
+ }
+ return null;
+ }
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (CompletionEngine_this._isCompletionAfter(node.period.end)) {
+ if (CompletionEngine_this._isCompletionBefore(node.identifier.offset)) {
+ // { x.! } or { x.! y } Note missing/implied semicolon before y; this looks like an
+ // obscure case but it occurs frequently when editing existing code.
+ CompletionEngine_this._dispatchPrefixAnalysis3(node, node.identifier);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitPropertyAccess(PropertyAccess node) {
+ if (node.target != null && node.target.length == 0) {
+ return null;
+ }
+ Expression target = node.realTarget;
+ // The "1 + str.!.length" is parsed as "(1 + str).!.length",
+ // but actually user wants "1 + (str.!).length".
+ // So, if completion inside of period-period ".!." then it is not really a cascade completion.
+ Token operator = node.operator;
+ if (operator.type == TokenType.PERIOD_PERIOD) {
+ int completionLocation = CompletionEngine_this._completionLocation();
+ if (completionLocation > operator.offset && completionLocation < operator.end) {
+ while (target is BinaryExpression) {
+ target = (target as BinaryExpression).rightOperand;
+ }
+ }
+ }
+ // do prefixed completion
+ CompletionEngine_this._analyzePrefixedAccess(target, node.propertyName);
+ return null;
+ }
+
+ @override
+ Object visitReturnStatement(ReturnStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ return null;
+ }
+ Expression expression = node.expression;
+ // return !
+ if (expression is SimpleIdentifier) {
+ SimpleIdentifier identifier = expression;
+ CompletionEngine_this._analyzeLocalName(identifier);
+ return null;
+ }
+ // return expression ! ;
+ Token semicolon = node.semicolon;
+ if (expression != null && semicolon != null && CompletionEngine_this._isCompletionBetween(expression.end, semicolon.offset)) {
+ CompletionEngine_this._operatorAccess(expression, CompletionEngine_this._createIdent(node));
+ return null;
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ if (node.keyword != null && CompletionEngine_this._isCompletionBefore(node.keyword.end)) {
+ // f() { g(var! z) }
+ Token token = node.keyword;
+ Ident ident = new Ident.con3(node, token);
+ CompletionEngine_this._analyzeTypeName(ident, ident);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ AstNode parent = node.parent;
+ if (parent != null) {
+ CompletionEngine_IdentifierCompleter visitor = new CompletionEngine_IdentifierCompleter(CompletionEngine_this, node);
+ return parent.accept(visitor);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleStringLiteral(SimpleStringLiteral node) {
+ AstNode parent = node.parent;
+ if (parent is Directive) {
+ CompletionEngine_StringCompleter visitor = new CompletionEngine_StringCompleter(CompletionEngine_this, node);
+ return parent.accept(visitor);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ CompletionEngine_this._analyzeSuperConstructorInvocation(node);
+ return null;
+ }
+
+ @override
+ Object visitSwitchMember(SwitchMember node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSwitchStatement(SwitchStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTryStatement(TryStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.tryKeyword)) {
+ CompletionEngine_this._pKeyword(node.tryKeyword);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTypeArgumentList(TypeArgumentList node) {
+ if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.rightBracket.offset)) {
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTypeParameter(TypeParameter node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ } else if (node.name.name.isEmpty && CompletionEngine_this._isCompletionBefore(node.keyword.offset)) {
+ // { < ! extends X> }
+ CompletionEngine_this._analyzeTypeName(node.name, CompletionEngine_this._typeDeclarationName(node));
+ }
+ // { <! X ! extends ! Y !> }
+ return null;
+ }
+
+ @override
+ Object visitTypeParameterList(TypeParameterList node) {
+ // { <X extends A,! B,! > }
+ if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.rightBracket.offset)) {
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ if (CompletionEngine_this._isCompletionAfter(node.equals.end)) {
+ // { var x =! ...}
+ CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ CompletionEngine_this._analyzeTypeName(new Ident.con3(node, node.keyword), null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitWhileStatement(WhileStatement node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
+ CompletionEngine_this._pKeyword(node.keyword);
+ } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, node.rightParenthesis.offset)) {
+ CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_this._createIdent(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitWithClause(WithClause node) {
+ if (CompletionEngine_this._isCompletingKeyword(node.withKeyword)) {
+ CompletionEngine_this._pKeyword(node.withKeyword);
+ } else if (node.mixinTypes.isEmpty) {
+ // { X with ! }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ } else {
+ // { X with ! Y }
+ CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent(node), CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+}
+
+/**
+ * A TypeNameCompleter is used to classify the parent of a SimpleIdentifier after it has been
+ * identified as a TypeName by the IdentifierCompleter.
+ */
+class CompletionEngine_TypeNameCompleter extends CompletionEngine_AstNodeClassifier {
+ final CompletionEngine CompletionEngine_this;
+
+ final SimpleIdentifier _identifier;
+
+ final TypeName _typeName;
+
+ CompletionEngine_TypeNameCompleter(this.CompletionEngine_this, this._identifier, this._typeName);
+
+ @override
+ Object visitAsExpression(AsExpression node) {
+ if (identical(node.type, _typeName)) {
+ CompletionEngine_this._state._isDynamicAllowed = false;
+ CompletionEngine_this._state._isVoidAllowed = false;
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ if (identical(node.exceptionType, _typeName)) {
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitClassTypeAlias(ClassTypeAlias node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ return null;
+ }
+
+ @override
+ Object visitConstructorName(ConstructorName node) {
+ if (identical(_typeName, node.type)) {
+ if (node.period != null) {
+ if (CompletionEngine_this._isCompletionAfter(node.period.end)) {
+ // Is this branch reachable? Probably only in IdentifierCompleter.
+ "".toString();
+ } else {
+ // { new Cla!ss.cons() }
+ Element element = _identifier.bestElement;
+ if (element is ClassElement) {
+ CompletionEngine_this._namedConstructorReference(element, _identifier);
+ }
+ }
+ } else {
+ // { new ! } { new Na!me(); } { new js!on. }
+ CompletionEngine_this._analyzeConstructorTypeName(_identifier);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitExtendsClause(ExtendsClause node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ return null;
+ }
+
+ @override
+ Object visitImplementsClause(ImplementsClause node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ return null;
+ }
+
+ @override
+ Object visitIsExpression(IsExpression node) {
+ if (identical(_typeName, node.type)) {
+ Token isToken = node.isOperator;
+ if (CompletionEngine_this._completionLocation() == isToken.end) {
+ Expression expression = node.expression;
+ int offset = isToken.offset;
+ // { target.is! } possible name completion, parsed as "target.{synthetic} is!"
+ if (expression is PrefixedIdentifier) {
+ PrefixedIdentifier prefIdent = expression;
+ if (prefIdent.identifier.isSynthetic) {
+ CompletionEngine_this._analyzePrefixedAccess(prefIdent.prefix, new Ident.con2(node, "is", offset));
+ } else {
+ CompletionEngine_this._pKeyword(node.isOperator);
+ }
+ return null;
+ }
+ // { expr is! }
+ if (!CompletionEngine._isSyntheticIdentifier(expression)) {
+ CompletionEngine_this._pKeyword(node.isOperator);
+ return null;
+ }
+ // { is! } possible name completion
+ CompletionEngine_this._analyzeLocalName(new Ident.con2(node, "is", offset));
+ } else {
+ CompletionEngine_this._analyzeTypeName(node.type.name as SimpleIdentifier, null);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ if (identical(node.returnType, _typeName)) {
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ return null;
+ }
+
+ @override
+ Object visitTypeArgumentList(TypeArgumentList node) {
+ if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.rightBracket.offset)) {
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitTypeParameter(TypeParameter node) {
+ if (identical(node.bound, _typeName)) {
+ // { X<A extends !Y> }
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ if (node.parent is Statement) {
+ CompletionEngine_this._analyzeLocalName(_identifier);
+ } else {
+ CompletionEngine_this._analyzeTypeName(_identifier, null);
+ }
+ return null;
+ }
+
+ @override
+ Object visitWithClause(WithClause node) {
+ CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._typeDeclarationName(node));
+ return null;
+ }
+}
+
+/**
+ * The factory class used to create completion proposals.
+ */
+class CompletionFactory {
+ /**
+ * Create a completion proposal of the given kind.
+ */
+ CompletionProposal createCompletionProposal(ProposalKind kind, int insertionPoint) {
+ CompletionProposalImpl prop = new CompletionProposalImpl();
+ prop.setKind(kind);
+ prop.setLocation(insertionPoint);
+ return prop;
+ }
+}
+
+abstract class CompletionProposal {
+ static final int RELEVANCE_LOW = 0;
+
+ static final int RELEVANCE_DEFAULT = 10;
+
+ static final int RELEVANCE_HIGH = 20;
+
+ /**
+ * This character is used to specify location of the cursor after completion.
+ */
+ static final int CURSOR_MARKER = 0x2758;
+
+ void applyPartitionOffset(int partitionOffset);
+
+ String get completion;
+
+ String get declaringType;
+
+ Element get element;
+
+ ProposalKind get kind;
+
+ int get location;
+
+ String get parameterName;
+
+ List<String> get parameterNames;
+
+ String get parameterType;
+
+ List<String> get parameterTypes;
+
+ int get positionalParameterCount;
+
+ int get relevance;
+
+ int get replacementLength;
+
+ int get replacementLengthIdentifier;
+
+ String get returnType;
+
+ bool get hasNamed;
+
+ bool get hasPositional;
+
+ CompletionProposal incRelevance();
+
+ bool get isDeprecated;
+
+ bool get isPotentialMatch;
+
+ CompletionProposal setCompletion(String x);
+
+ CompletionProposal setDeclaringType(String name);
+
+ CompletionProposal setDeprecated(bool deprecated);
+
+ CompletionProposal setElement(Element element);
+
+ CompletionProposal setKind(ProposalKind x);
+
+ CompletionProposal setLocation(int x);
+
+ CompletionProposal setParameterName(String paramName);
+
+ CompletionProposal setParameterNames(List<String> paramNames);
+
+ CompletionProposal setParameterStyle(int count, bool named, bool positional);
+
+ CompletionProposal setParameterType(String paramType);
+
+ CompletionProposal setParameterTypes(List<String> paramTypes);
+
+ CompletionProposal setPotentialMatch(bool isPotentialMatch);
+
+ CompletionProposal setRelevance(int n);
+
+ CompletionProposal setReplacementLength(int x);
+
+ CompletionProposal setReplacementLengthIdentifier(int x);
+
+ CompletionProposal setReturnType(String name);
+}
+
+class CompletionProposalImpl implements CompletionProposal {
+ Element _element;
+
+ String _completion = "";
+
+ String _returnType = "";
+
+ String _declaringType = "";
+
+ List<String> _parameterNames = StringUtilities.EMPTY_ARRAY;
+
+ List<String> _parameterTypes = StringUtilities.EMPTY_ARRAY;
+
+ String _parameterName;
+
+ String _parameterType;
+
+ ProposalKind _kind = ProposalKind.NONE;
+
+ int _location = 0;
+
+ int _replacementLength = 0;
+
+ int _replacementLength2 = 0;
+
+ int _positionalParameterCount = 0;
+
+ bool _named = false;
+
+ bool _positional = false;
+
+ bool _deprecated = false;
+
+ bool _potential = false;
+
+ int _relevance = CompletionProposal.RELEVANCE_DEFAULT;
+
+ @override
+ void applyPartitionOffset(int partitionOffset) {
+ _location += partitionOffset;
+ }
+
+ @override
+ String get completion => _completion;
+
+ @override
+ String get declaringType => _declaringType;
+
+ @override
+ Element get element => _element;
+
+ @override
+ ProposalKind get kind => _kind;
+
+ @override
+ int get location => _location;
+
+ @override
+ String get parameterName => _parameterName;
+
+ @override
+ List<String> get parameterNames => _parameterNames;
+
+ @override
+ String get parameterType => _parameterType;
+
+ @override
+ List<String> get parameterTypes => _parameterTypes;
+
+ @override
+ int get positionalParameterCount => _positionalParameterCount;
+
+ @override
+ int get relevance => _relevance;
+
+ @override
+ int get replacementLength => _replacementLength;
+
+ @override
+ int get replacementLengthIdentifier => _replacementLength2;
+
+ @override
+ String get returnType => _returnType;
+
+ @override
+ bool get hasNamed => _named;
+
+ @override
+ bool get hasPositional => _positional;
+
+ @override
+ CompletionProposal incRelevance() {
+ _relevance++;
+ return this;
+ }
+
+ @override
+ bool get isDeprecated => _deprecated;
+
+ @override
+ bool get isPotentialMatch => _potential;
+
+ @override
+ CompletionProposal setCompletion(String x) {
+ _completion = x;
+ if (_replacementLength == 0) {
+ setReplacementLength(x.length);
+ }
+ return this;
+ }
+
+ @override
+ CompletionProposal setDeclaringType(String name) {
+ _declaringType = name;
+ return this;
+ }
+
+ @override
+ CompletionProposal setDeprecated(bool deprecated) {
+ this._deprecated = deprecated;
+ return this;
+ }
+
+ @override
+ CompletionProposal setElement(Element element) {
+ this._element = element;
+ return this;
+ }
+
+ @override
+ CompletionProposal setKind(ProposalKind x) {
+ _kind = x;
+ return this;
+ }
+
+ @override
+ CompletionProposal setLocation(int x) {
+ _location = x;
+ return this;
+ }
+
+ @override
+ CompletionProposal setParameterName(String parameterName) {
+ this._parameterName = parameterName;
+ return this;
+ }
+
+ @override
+ CompletionProposal setParameterNames(List<String> paramNames) {
+ _parameterNames = paramNames;
+ return this;
+ }
+
+ @override
+ CompletionProposal setParameterStyle(int count, bool named, bool positional) {
+ this._named = named;
+ this._positional = positional;
+ this._positionalParameterCount = count;
+ return this;
+ }
+
+ @override
+ CompletionProposal setParameterType(String parameterType) {
+ this._parameterType = parameterType;
+ return this;
+ }
+
+ @override
+ CompletionProposal setParameterTypes(List<String> paramTypes) {
+ _parameterTypes = paramTypes;
+ return this;
+ }
+
+ @override
+ CompletionProposal setPotentialMatch(bool isPotentialMatch) {
+ _potential = isPotentialMatch;
+ return this;
+ }
+
+ @override
+ CompletionProposal setRelevance(int n) {
+ _relevance = n;
+ return this;
+ }
+
+ @override
+ CompletionProposal setReplacementLength(int x) {
+ _replacementLength = x;
+ return this;
+ }
+
+ @override
+ CompletionProposal setReplacementLengthIdentifier(int x) {
+ _replacementLength2 = x;
+ return this;
+ }
+
+ @override
+ CompletionProposal setReturnType(String name) {
+ _returnType = name;
+ return this;
+ }
+}
+
+/**
+ * A pathway for reporting completion proposals back to the client.
+ */
+abstract class CompletionRequestor {
+ /**
+ * Record the given completion proposal for eventual presentation to the user.
+ */
+ accept(CompletionProposal proposal);
+
+ void beginReporting();
+
+ void endReporting();
+}
+
+/**
+ */
+class CompletionState {
+ bool _isForMixin = false;
+
+ bool _isVoidAllowed = false;
+
+ bool _isDynamicAllowed = false;
+
+ bool _isSourceDeclarationStatic = false;
+
+ bool _isThisAllowed = true;
+
+ bool _isVarAllowed = false;
+
+ bool _areLiteralsAllowed = false;
+
+ bool _areLiteralsProhibited = false;
+
+ bool _areOperatorsAllowed = false;
+
+ bool _areStaticReferencesProhibited = false;
+
+ bool _areInstanceReferencesProhibited = false;
+
+ bool _areUndefinedTypesProhibited = false;
+
+ bool _isCompileTimeConstantRequired = false;
+
+ bool _isOptionalArgumentRequired = false;
+
+ bool _areMethodsProhibited = false;
+
+ bool _areClassesRequired = false;
+
+ ParameterElement _targetParameter;
+
+ void mustBeInstantiableType() {
+ _areClassesRequired = true;
+ _prohibitsLiterals();
+ }
+
+ void _includesLiterals() {
+ if (!_areLiteralsProhibited) {
+ _areLiteralsAllowed = true;
+ }
+ }
+
+ void _includesOperators() {
+ _areOperatorsAllowed = true;
+ }
+
+ void _includesUndefinedDeclarationTypes() {
+ if (!_areUndefinedTypesProhibited) {
+ _isVoidAllowed = true;
+ _isDynamicAllowed = true;
+ }
+ }
+
+ void _includesUndefinedTypes() {
+ _isVarAllowed = true;
+ _isDynamicAllowed = true;
+ }
+
+ void _mustBeMixin() {
+ _isForMixin = true;
+ }
+
+ void _prohibitsInstanceReferences() {
+ _areInstanceReferencesProhibited = true;
+ }
+
+ void _prohibitsLiterals() {
+ _areLiteralsAllowed = false;
+ _areLiteralsProhibited = true;
+ }
+
+ void _prohibitsStaticReferences() {
+ _areStaticReferencesProhibited = true;
+ }
+
+ void _prohibitThis() {
+ _isThisAllowed = false;
+ }
+
+ void _prohibitsUndefinedTypes() {
+ _areUndefinedTypesProhibited = true;
+ }
+
+ void _requiresConst(bool isConst) {
+ _isCompileTimeConstantRequired = isConst;
+ }
+
+ void _requiresOperators() {
+ _includesOperators();
+ _areMethodsProhibited = true;
+ }
+
+ void _requiresOptionalArgument() {
+ _isOptionalArgumentRequired = true;
+ _prohibitsLiterals();
+ }
+
+ void set context(AstNode base) {
+ base.accept(new ContextAnalyzer(this, base));
+ }
+
+ void _sourceDeclarationIsStatic(bool state) {
+ _isSourceDeclarationStatic = state;
+ if (state) {
+ if (!_areStaticReferencesProhibited) {
+ _prohibitsInstanceReferences();
+ }
+ }
+ }
+}
+
+/**
+ */
+class ContextAnalyzer extends GeneralizingAstVisitor<Object> {
+ final CompletionState _state;
+
+ final AstNode _completionNode;
+
+ AstNode _child;
+
+ bool _inExpression = false;
+
+ bool _inIdentifier = false;
+
+ bool _inTypeName = false;
+
+ bool _maybeInvocationArgument = true;
+
+ ContextAnalyzer(this._state, this._completionNode);
+
+ @override
+ Object visitAnnotation(Annotation node) {
+ _state._requiresConst(true);
+ return super.visitAnnotation(node);
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ if (identical(node.exceptionType, _child)) {
+ _state._prohibitsLiterals();
+ }
+ return null;
+ }
+
+ @override
+ Object visitCompilationUnitMember(CompilationUnitMember node) {
+ if (node is! ClassDeclaration) {
+ _state._prohibitThis();
+ }
+ return super.visitCompilationUnitMember(node);
+ }
+
+ @override
+ Object visitConstructorInitializer(ConstructorInitializer node) {
+ _state._prohibitThis();
+ return super.visitConstructorInitializer(node);
+ }
+
+ @override
+ Object visitDirective(Directive node) {
+ _state._prohibitsLiterals();
+ return super.visitDirective(node);
+ }
+
+ @override
+ Object visitDoStatement(DoStatement node) {
+ if (identical(_child, node.condition)) {
+ _state._includesLiterals();
+ }
+ return super.visitDoStatement(node);
+ }
+
+ @override
+ Object visitExpression(Expression node) {
+ _inExpression = true;
+ _state._includesLiterals();
+ _mayBeSetParameterElement(node);
+ return super.visitExpression(node);
+ }
+
+ @override
+ Object visitFieldDeclaration(FieldDeclaration node) {
+ _state._prohibitThis();
+ return super.visitFieldDeclaration(node);
+ }
+
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ if (identical(_child, node.iterator)) {
+ _state._includesLiterals();
+ }
+ return super.visitForEachStatement(node);
+ }
+
+ @override
+ Object visitFunctionExpression(FunctionExpression node) {
+ if (node.parent is Declaration) {
+ // Function expressions that are part of a declaration are not to be treated as expressions.
+ return visitNode(node);
+ } else {
+ return visitExpression(node);
+ }
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ if (_inTypeName || node.returnType == null) {
+ // This may be an incomplete class type alias
+ _state._includesUndefinedDeclarationTypes();
+ }
+ return super.visitFunctionTypeAlias(node);
+ }
+
+ @override
+ Object visitIdentifier(Identifier node) {
+ _mayBeSetParameterElement(node);
+ // Identifiers cannot safely be generalized to expressions, so just walk up one level.
+ // LibraryIdentifier is never an expression. PrefixedIdentifier may be an expression, but
+ // not in a catch-clause or a declaration. SimpleIdentifier may be an expression, but not
+ // in a constructor name, label, or where PrefixedIdentifier is not.
+ return visitNode(node);
+ }
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ _state._requiresConst(node.isConst);
+ if (identical(_completionNode.parent.parent, _child)) {
+ _state.mustBeInstantiableType();
+ }
+ return super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ _state._sourceDeclarationIsStatic(node.isStatic);
+ if (identical(_child, node.returnType)) {
+ _state._includesUndefinedDeclarationTypes();
+ }
+ if (node.isStatic) {
+ _state._prohibitThis();
+ }
+ return super.visitMethodDeclaration(node);
+ }
+
+ @override
+ Object visitNode(AstNode node) {
+ // Walk UP the tree, not down.
+ AstNode parent = node.parent;
+ _updateIfShouldGetTargetParameter(node, parent);
+ if (parent != null) {
+ _child = node;
+ parent.accept(this);
+ }
+ return null;
+ }
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (identical(node, _completionNode) || identical(node.identifier, _completionNode)) {
+ SimpleIdentifier prefix = node.prefix;
+ if (_isClassLiteral(prefix)) {
+ _state._prohibitsInstanceReferences();
+ } else {
+ _state._prohibitsStaticReferences();
+ }
+ }
+ return super.visitPrefixedIdentifier(node);
+ }
+
+ @override
+ Object visitPropertyAccess(PropertyAccess node) {
+ if (identical(node, _completionNode) || identical(node.propertyName, _completionNode)) {
+ Expression target = node.realTarget;
+ if (_isClassLiteral(target)) {
+ _state._prohibitsInstanceReferences();
+ } else {
+ _state._prohibitsStaticReferences();
+ }
+ }
+ return super.visitPropertyAccess(node);
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ _state._includesUndefinedTypes();
+ return super.visitSimpleFormalParameter(node);
+ }
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ _inIdentifier = true;
+ return super.visitSimpleIdentifier(node);
+ }
+
+ @override
+ Object visitSwitchStatement(SwitchStatement node) {
+ if (identical(_child, node.expression)) {
+ _state._includesLiterals();
+ }
+ return super.visitSwitchStatement(node);
+ }
+
+ @override
+ Object visitTypeArgumentList(TypeArgumentList node) {
+ _state._prohibitsUndefinedTypes();
+ return super.visitTypeArgumentList(node);
+ }
+
+ @override
+ Object visitTypeName(TypeName node) {
+ _inTypeName = true;
+ return super.visitTypeName(node);
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ if (identical(node.name, _completionNode)) {
+ _state._prohibitsLiterals();
+ }
+ return super.visitVariableDeclaration(node);
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ _state._includesUndefinedDeclarationTypes();
+ return super.visitVariableDeclarationList(node);
+ }
+
+ @override
+ Object visitWhileStatement(WhileStatement node) {
+ if (identical(_child, node.condition)) {
+ _state._includesLiterals();
+ }
+ return super.visitWhileStatement(node);
+ }
+
+ @override
+ Object visitWithClause(WithClause node) {
+ _state._mustBeMixin();
+ return super.visitWithClause(node);
+ }
+
+ bool _isClassLiteral(Expression expression) => expression is Identifier && expression.staticElement is ClassElement;
+
+ void _mayBeSetParameterElement(Expression node) {
+ if (!_maybeInvocationArgument) {
+ return;
+ }
+ if (node.parent is ArgumentList) {
+ if (_state._targetParameter == null) {
+ _state._targetParameter = node.bestParameterElement;
+ }
+ }
+ }
+
+ void _updateIfShouldGetTargetParameter(AstNode node, AstNode parent) {
+ if (!_maybeInvocationArgument) {
+ return;
+ }
+ // prefix.node
+ if (parent is PrefixedIdentifier) {
+ if (identical(parent.identifier, node)) {
+ return;
+ }
+ }
+ // something unknown
+ _maybeInvocationArgument = false;
+ }
+}
+
+class Filter {
+ String _prefix;
+
+ String _originalPrefix;
+
+ RegExp _pattern;
+
+ Filter.con1(SimpleIdentifier ident, int loc) : this.con2(ident.name, ident.offset, loc);
+
+ Filter.con2(String name, int pos, int loc) {
+ int len = loc - pos;
+ if (len > 0) {
+ if (len <= name.length) {
+ _prefix = name.substring(0, len);
+ } else {
+ _prefix = name;
+ }
+ } else {
+ _prefix = "";
+ }
+ _originalPrefix = _prefix;
+ _prefix = _prefix.toLowerCase();
+ }
+
+ /**
+ * @return `true` if the given name starts with the same prefix as used for filter.
+ */
+ bool _isSameCasePrefix(String name) => name.startsWith(_originalPrefix);
+
+ String _makePattern() {
+ // TODO(scheglov) translate it
+ return null;
+ }
+
+ bool _match(Element elem) => _match2(elem.displayName);
+
+ bool _match2(String name) {
+ // Return true if the filter passes.
+ if (name.toLowerCase().startsWith(_prefix)) {
+ return true;
+ }
+ return _matchPattern(name);
+ }
+
+ void _removeNotMatching(List<Element> elements) {
+ for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
+ Element element = I.next();
+ if (!_match(element)) {
+ I.remove();
+ }
+ }
+ }
+
+ bool _matchPattern(String name) {
+ // TODO(scheglov) translate it
+ return false;
+ }
+}
+
+class GeneralizingAstVisitor_CompletionEngine_copyWithout extends GeneralizingAstVisitor<Object> {
+ AstNode deletion;
+
+ List<FormalParameter> newList;
+
+ GeneralizingAstVisitor_CompletionEngine_copyWithout(this.deletion, this.newList) : super();
+
+ @override
+ Object visitNode(AstNode node) {
+ if (!identical(node, deletion)) {
+ newList.add(node as FormalParameter);
+ }
+ return null;
+ }
+}
+
+/**
+ * An [Ident] is a wrapper for a String that provides type equivalence with SimpleIdentifier.
+ */
+class Ident extends EphemeralIdentifier {
+ String _name;
+
+ Ident.con1(AstNode parent, int offset) : super(parent, offset);
+
+ Ident.con2(AstNode parent, String name, int offset) : super(parent, offset) {
+ this._name = name;
+ }
+
+ Ident.con3(AstNode parent, Token name) : super(parent, name.offset) {
+ this._name = name.lexeme;
+ }
+
+ @override
+ String get name {
+ if (_name != null) {
+ return _name;
+ }
+ String n = super.name;
+ if (n != null) {
+ return n;
+ }
+ return "";
+ }
+}
+
+class ProposalCollector implements CompletionRequestor {
+ final CompletionRequestor requestor;
+
+ List<CompletionProposal> _proposals;
+
+ ProposalCollector(this.requestor) {
+ this._proposals = new List<CompletionProposal>();
+ }
+
+ @override
+ accept(CompletionProposal proposal) {
+ _proposals.add(proposal);
+ }
+
+ @override
+ void beginReporting() {
+ requestor.beginReporting();
+ }
+
+ @override
+ void endReporting() {
+ requestor.endReporting();
+ }
+
+ List<CompletionProposal> get proposals => _proposals;
+}
+
+/**
+ * The various kinds of completion proposals. Each specifies the kind of completion to be created,
+ * corresponding to different syntactical elements.
+ */
+class ProposalKind extends Enum<ProposalKind> {
+ static const ProposalKind NONE = const ProposalKind('NONE', 0);
+
+ static const ProposalKind CLASS = const ProposalKind('CLASS', 1);
+
+ static const ProposalKind CLASS_ALIAS = const ProposalKind('CLASS_ALIAS', 2);
+
+ static const ProposalKind CONSTRUCTOR = const ProposalKind('CONSTRUCTOR', 3);
+
+ static const ProposalKind FIELD = const ProposalKind('FIELD', 4);
+
+ static const ProposalKind FUNCTION = const ProposalKind('FUNCTION', 5);
+
+ static const ProposalKind FUNCTION_ALIAS = const ProposalKind('FUNCTION_ALIAS', 6);
+
+ static const ProposalKind GETTER = const ProposalKind('GETTER', 7);
+
+ static const ProposalKind IMPORT = const ProposalKind('IMPORT', 8);
+
+ static const ProposalKind LIBRARY_PREFIX = const ProposalKind('LIBRARY_PREFIX', 9);
+
+ static const ProposalKind METHOD = const ProposalKind('METHOD', 10);
+
+ static const ProposalKind METHOD_NAME = const ProposalKind('METHOD_NAME', 11);
+
+ static const ProposalKind PARAMETER = const ProposalKind('PARAMETER', 12);
+
+ static const ProposalKind SETTER = const ProposalKind('SETTER', 13);
+
+ static const ProposalKind VARIABLE = const ProposalKind('VARIABLE', 14);
+
+ static const ProposalKind TYPE_PARAMETER = const ProposalKind('TYPE_PARAMETER', 15);
+
+ static const ProposalKind ARGUMENT_LIST = const ProposalKind('ARGUMENT_LIST', 16);
+
+ static const ProposalKind OPTIONAL_ARGUMENT = const ProposalKind('OPTIONAL_ARGUMENT', 17);
+
+ static const ProposalKind NAMED_ARGUMENT = const ProposalKind('NAMED_ARGUMENT', 18);
+
+ static const List<ProposalKind> values = const [
+ NONE,
+ CLASS,
+ CLASS_ALIAS,
+ CONSTRUCTOR,
+ FIELD,
+ FUNCTION,
+ FUNCTION_ALIAS,
+ GETTER,
+ IMPORT,
+ LIBRARY_PREFIX,
+ METHOD,
+ METHOD_NAME,
+ PARAMETER,
+ SETTER,
+ VARIABLE,
+ TYPE_PARAMETER,
+ ARGUMENT_LIST,
+ OPTIONAL_ARGUMENT,
+ NAMED_ARGUMENT];
+
+ const ProposalKind(String name, int ordinal) : super(name, ordinal);
+}
+
+class SearchFilter_CompletionEngine_allSubtypes implements SearchFilter {
+ ClassElement classElement;
+
+ SearchFilter_CompletionEngine_allSubtypes(this.classElement);
+
+ @override
+ bool passes(SearchMatch match) {
+ Element element = match.element;
+ if (element is ClassElement) {
+ ClassElement clElem = element;
+ while (clElem != null) {
+ InterfaceType ifType = clElem.supertype;
+ if (ifType == null) {
+ return false;
+ }
+ clElem = ifType.element;
+ if (identical(clElem, classElement)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+class TopLevelNamesKind extends Enum<TopLevelNamesKind> {
+ static const TopLevelNamesKind DECLARED_AND_IMPORTS = const TopLevelNamesKind('DECLARED_AND_IMPORTS', 0);
+
+ static const TopLevelNamesKind DECLARED_AND_EXPORTS = const TopLevelNamesKind('DECLARED_AND_EXPORTS', 1);
+
+ static const List<TopLevelNamesKind> values = const [DECLARED_AND_IMPORTS, DECLARED_AND_EXPORTS];
+
+ const TopLevelNamesKind(String name, int ordinal) : super(name, ordinal);
+}
« no previous file with comments | « pkg/analysis_services/lib/src/generated/change.dart ('k') | pkg/analysis_services/lib/src/generated/proposal.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698