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

Unified Diff: editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/internal/completion/CompletionEngine.java

Issue 10379012: Code completion improvements. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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: editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/internal/completion/CompletionEngine.java
===================================================================
--- editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/internal/completion/CompletionEngine.java (revision 7347)
+++ editor/tools/plugins/com.google.dart.tools.core/src/com/google/dart/tools/core/internal/completion/CompletionEngine.java (working copy)
@@ -88,6 +88,7 @@
import com.google.dart.tools.core.internal.completion.ScopedNameFinder.ScopedName;
import com.google.dart.tools.core.internal.completion.ast.BlockCompleter;
import com.google.dart.tools.core.internal.completion.ast.FunctionCompleter;
+import com.google.dart.tools.core.internal.completion.ast.IdentifierCompleter;
import com.google.dart.tools.core.internal.completion.ast.MethodInvocationCompleter;
import com.google.dart.tools.core.internal.completion.ast.ParameterCompleter;
import com.google.dart.tools.core.internal.completion.ast.PropertyAccessCompleter;
@@ -102,6 +103,7 @@
import com.google.dart.tools.core.model.CompilationUnit;
import com.google.dart.tools.core.model.DartElement;
import com.google.dart.tools.core.model.DartImport;
+import com.google.dart.tools.core.model.DartLibrary;
import com.google.dart.tools.core.model.DartModelException;
import com.google.dart.tools.core.model.DartProject;
import com.google.dart.tools.core.model.Method;
@@ -112,6 +114,7 @@
import com.google.dart.tools.core.search.SearchException;
import com.google.dart.tools.core.search.SearchFilter;
import com.google.dart.tools.core.search.SearchMatch;
+import com.google.dart.tools.core.search.SearchPattern;
import com.google.dart.tools.core.search.SearchPatternFactory;
import com.google.dart.tools.core.search.SearchScope;
import com.google.dart.tools.core.search.SearchScopeFactory;
@@ -127,6 +130,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@@ -282,7 +286,7 @@
type = element.getType();
}
}
- createCompletionsForQualifiedMemberAccess(methodName, type, false);
+ createCompletionsForQualifiedMemberAccess(methodName, type, true, false);
} else {
// { x!.y } or { x.y(a!) } or { x.y(a, b, C!) }
// TODO Consider using proposeIdentifierPrefixCompletions() here
@@ -290,7 +294,7 @@
DartClass classDef = (DartClass) resolvedMember.getParent();
ClassElement elem = classDef.getElement();
Type type = elem.getType();
- createCompletionsForPropertyAccess(identifier, type, false, false);
+ createCompletionsForPropertyAccess(identifier, type, false, true, false);
}
}
return null;
@@ -300,13 +304,13 @@
public Void visitNewExpression(DartNewExpression node) {
// { new x! }
List<SearchMatch> matches = findTypesWithPrefix(identifier);
- if (matches == null || matches.size() == 0) {
- return null;
- }
+ String prefix = extractFilterPrefix(identifier);
for (SearchMatch match : matches) {
- String prefix = extractFilterPrefix(identifier);
- createTypeCompletionsForConstructor(identifier, match, prefix);
+ createTypeCompletionsForConstructor(identifier, node, match, prefix);
}
+ if (!isCompletionAfterDot) {
+ createCompletionsForIdentifierPrefix(identifier, prefix);
+ }
return null;
}
@@ -324,35 +328,83 @@
Type type = analyzeType(completionNode.getQualifier());
if (type.getKind() == TypeKind.DYNAMIC || type.getKind() == TypeKind.VOID) {
if (completionNode.getQualifier() instanceof DartIdentifier) {
- Element element = ((DartIdentifier) completionNode.getQualifier()).getElement();
+ DartIdentifier qualNode = (DartIdentifier) completionNode.getQualifier();
+ Element element = qualNode.getElement();
if (ElementKind.of(element) == ElementKind.CLASS) {
type = element.getType();
if (type instanceof InterfaceType) {
// { Array.! } or { Array.f! }
- createCompletionsForFactoryInvocation(propertyName, (InterfaceType) type);
- createCompletionsForQualifiedMemberAccess(propertyName, type, false);
+ createCompletionsForFactoryInvocation(
+ propertyName,
+ completionNode,
+ (InterfaceType) type);
+ createCompletionsForQualifiedMemberAccess(propertyName, type, false, false);
}
} else if (ElementKind.of(element) == ElementKind.LIBRARY) {
- // #import('dart:html', prefix: 'html'); class X{ html.!DivElement! div; }
- createCompletionsForLibraryPrefix(propertyName, (LibraryElement) element);
+ if (completionNode.getParent().getParent() instanceof DartNewExpression) {
+ // { new html.! }
+ DartNode prop = completionNode.getParent().getParent();
+ prop.accept(new IdentifierCompletionProposer(propertyName));
+ } else {
+ // #import('dart:html', prefix: 'html'); class X{ html.!DivElement! div; }
+ createCompletionsForLibraryPrefix(propertyName, (LibraryElement) element);
+ }
} else {
- createCompletionsForQualifiedMemberAccess(propertyName, type, false);
+ if (completionNode.getParent().getParent() instanceof DartNewExpression) {
+ // { new html.! }
+ DartNode prop = completionNode.getParent().getParent();
+ prop.accept(new IdentifierCompletionProposer(propertyName));
+ } else {
+ if (ElementKind.of(element) == ElementKind.LIBRARY_PREFIX) {
+ // { html.E! }
+ String prefixToMatch = qualNode.getName();
+ Collection<LibraryUnit> libs = parsedUnit.getLibrary().getLibrariesWithPrefix(
+ prefixToMatch);
+ for (LibraryUnit lib : libs) {
+ createCompletionsForLibraryPrefix(propertyName, lib.getElement());
+ }
+ } else {
+ boolean allowDynamic = false;
+ switch (ElementKind.of(element)) {
+ case CONSTRUCTOR:
+ case FIELD:
+ case METHOD:
+ case VARIABLE:
+ allowDynamic = true;
+ break;
+ }
+ createCompletionsForQualifiedMemberAccess(
+ propertyName,
+ type,
+ allowDynamic,
+ false);
+ }
+ }
}
} else {
- createCompletionsForQualifiedMemberAccess(propertyName, type, false);
+ if (completionNode.getParent() instanceof DartNewExpression) {
+ // { new html.! }
+ DartNewExpression prop = (DartNewExpression) completionNode.getParent();
+ prop.accept(new IdentifierCompletionProposer(completionNode.getName()));
+ } else {
+ createCompletionsForQualifiedMemberAccess(propertyName, type, false, false);
+ }
}
} else {
if (type instanceof InterfaceType) {
DartNode q = completionNode.getQualifier();
if (q instanceof DartTypeNode) {
- createCompletionsForFactoryInvocation(propertyName, (InterfaceType) type);
+ createCompletionsForFactoryInvocation(
+ propertyName,
+ completionNode,
+ (InterfaceType) type);
} else {
- createCompletionsForQualifiedMemberAccess(propertyName, type, false);
+ createCompletionsForQualifiedMemberAccess(propertyName, type, false, false);
}
} else {
// { a.! } or { a.x! }
boolean isInstance = completionNode.getQualifier() instanceof DartThisExpression;
- createCompletionsForQualifiedMemberAccess(propertyName, type, isInstance);
+ createCompletionsForQualifiedMemberAccess(propertyName, type, !isInstance, isInstance);
}
}
} else {
@@ -395,7 +447,7 @@
ClassElement ce = cn.getConstructorType();
if (ce != null) {
// TODO Restrict proposals to constructors
- createCompletionsForMethodInvocation(identifier, ce.getType(), true, false);
+ createCompletionsForMethodInvocation(identifier, ce.getType(), true, false, false);
}
}
return null;
@@ -421,7 +473,7 @@
proposeTypesForNewParam();
break;
} else {
- proposeGenericTypeCompletions(typeCompleter);
+ proposeGenericTypeCompletions(typeCompleter, false);
proposeTypesForPrefix(identifier);
}
break;
@@ -429,7 +481,7 @@
// {for (in!t x = 0; i < 5; i++); }
case TypeFunctionOrVariable:
// { x; v! x; } or { v! x; }
- proposeGenericTypeCompletions(typeCompleter);
+ proposeGenericTypeCompletions(typeCompleter, true);
proposeIdentifierPrefixCompletions(typeCompleter);
break;
case FunctionLiteral:
@@ -441,7 +493,7 @@
break;
case TypeExpression:
// { if (x is !)}
- proposeGenericTypeCompletions(typeCompleter);
+ proposeGenericTypeCompletions(typeCompleter, false);
proposeTypesForPrefix(identifier);
break;
case ClassBody:
@@ -456,7 +508,7 @@
// class x { ! }
// TODO check for supertype methods whose name starts with identifier
// if found propose a new method matching its signature
- proposeGenericTypeCompletions(typeCompleter);
+ proposeGenericTypeCompletions(typeCompleter, false);
proposeTypesForPrefix(identifier, true);
break;
case TopLevelElement:
@@ -517,8 +569,8 @@
Element parentElement = resolvedMember.getElement().getEnclosingElement();
if (parentElement instanceof ClassElement) {
Type type = ((ClassElement) parentElement).getType();
- createCompletionsForPropertyAccess(identifier, type, false, isStatic);
- createCompletionsForMethodInvocation(identifier, type, false, isStatic);
+ createCompletionsForPropertyAccess(identifier, type, false, false, isStatic);
+ createCompletionsForMethodInvocation(identifier, type, false, false, isStatic);
proposeTypesForPrefix(identifier, false);
} else {
// TODO top-level element
@@ -597,8 +649,8 @@
boolean isStatic = resolvedMember.getModifiers().isStatic();
createCompletionsForLocalVariables(block, null, resolvedMember);
Type type = ((ClassElement) parentElement).getType();
- createCompletionsForPropertyAccess(null, type, false, isStatic);
- createCompletionsForMethodInvocation(null, type, false, isStatic);
+ createCompletionsForPropertyAccess(null, type, false, true, isStatic);
+ createCompletionsForMethodInvocation(null, type, false, true, isStatic);
// Types are legal here but we are not proposing them since they are optional
} else {
// another case of error recovery producing odd AST shapes
@@ -781,6 +833,19 @@
@Override
public Void visitIdentifier(DartIdentifier node) {
DartNode parent = node.getParent();
+ if (node instanceof IdentifierCompleter) {
+ if (((IdentifierCompleter) node).getCompletionParsingContext().size() > 4) {
+ DartNode ancestor = parent.getParent().getParent().getParent();
+ if (ancestor instanceof DartClassMember) {
+ DartClassMember<?> member = (DartClassMember<?>) ancestor;
+ if (member.getModifiers().isConstant()) {
+ // class X { const !; } to be continued with X.init();
+ proposeTypesForNewParam();
+ return null;
+ }
+ }
+ }
+ }
return parent.accept(new IdentifierCompletionProposer(node));
}
@@ -792,8 +857,8 @@
Element parentElement = resolvedMember.getElement().getEnclosingElement();
if (parentElement instanceof ClassElement) {
Type type = ((ClassElement) parentElement).getType();
- createCompletionsForPropertyAccess(null, type, false, isStatic);
- createCompletionsForMethodInvocation(null, type, false, isStatic);
+ createCompletionsForPropertyAccess(null, type, false, true, isStatic);
+ createCompletionsForMethodInvocation(null, type, false, true, isStatic);
}
return null;
}
@@ -810,7 +875,7 @@
// { foo.! doFoo(); }
Type type = analyzeType(completionNode.getTarget());
if (type != null) {
- createCompletionsForQualifiedMemberAccess(functionName, type, false);
+ createCompletionsForQualifiedMemberAccess(functionName, type, false, false);
}
}
}
@@ -832,8 +897,8 @@
Element parentElement = resolvedMember.getElement().getEnclosingElement();
if (parentElement.getKind() == ElementKind.CLASS) {
Type type = ((ClassElement) parentElement).getType();
- createCompletionsForPropertyAccess(synth, type, false, isStatic);
- createCompletionsForMethodInvocation(synth, type, false, isStatic);
+ createCompletionsForPropertyAccess(synth, type, false, true, isStatic);
+ createCompletionsForMethodInvocation(synth, type, false, true, isStatic);
}
return null;
}
@@ -844,8 +909,9 @@
return null;
}
for (SearchMatch match : matches) {
- createTypeCompletionsForConstructor(null, match, "");
+ createTypeCompletionsForConstructor(null, node, match, "");
}
+ createCompletionsForIdentifierPrefix(null, null);
}
return null;
}
@@ -871,10 +937,11 @@
if (matches == null || matches.size() == 0) {
return null;
}
+ String prefix = extractFilterPrefix(typeId);
for (SearchMatch match : matches) {
- String prefix = extractFilterPrefix(typeId);
createTypeCompletionsForParameterDecl(typeId, match, prefix);
}
+ createCompletionsForIdentifierPrefix(typeId, prefix);
} else if (typeName instanceof DartPropertyAccess) {
DartPropertyAccess prop = (DartPropertyAccess) typeName;
if (isCompletionAfterDot
@@ -916,7 +983,7 @@
type = element.getType();
}
}
- createCompletionsForQualifiedMemberAccess(propertyName, type, false);
+ createCompletionsForQualifiedMemberAccess(propertyName, type, true, false);
}
return null;
}
@@ -942,8 +1009,8 @@
if (parentElement instanceof ClassElement) {
Type type = ((ClassElement) parentElement).getType();
boolean isStatic = resolvedMember.getModifiers().isStatic();
- createCompletionsForPropertyAccess(null, type, false, isStatic);
- createCompletionsForMethodInvocation(null, type, false, isStatic);
+ createCompletionsForPropertyAccess(null, type, false, true, isStatic);
+ createCompletionsForMethodInvocation(null, type, false, true, isStatic);
}
break;
}
@@ -1086,6 +1153,8 @@
private static final boolean DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("com.google.dart.tools.ui/debug/CompletionEngine"));
+ private static final String C_VOID = "void";
+
public static char[][] createDefaultParameterNames(int length) {
char[][] names = new char[length][];
for (int i = 0; i < length; i++) {
@@ -1105,13 +1174,6 @@
return posParamCount;
}
- static private List<Element> findAllElements(LibraryUnit library, String prefix) {
- Set<Element> elemSet = findAllElements(library, prefix, new HashSet<LibraryUnit>());
- List<Element> elements = new ArrayList<Element>(elemSet.size());
- elements.addAll(elemSet);
- return elements;
- }
-
static private Set<Element> findAllElements(LibraryUnit library, String prefix,
Set<LibraryUnit> libs) {
if (libs.contains(library)) {
@@ -1258,10 +1320,9 @@
private DartUnit parsedUnit;
private CompilationUnit currentCompilationUnit;
private CompletionMetrics metrics;
-
+ private Set<String> prefixes;
private static final String C_EXTENDS = "extends";
private static final String C_IMPLEMENTS = "implements";
- private static final String C_VOID = "void";
/**
* @param options
@@ -1355,11 +1416,11 @@
DartCompilerListener listener = DartCompilerListener.EMPTY;
ParserContext ctx = new DartScannerParserContext(sourceFile, source, listener);
- Set<String> prefixes = new HashSet<String>();
+ prefixes = new HashSet<String>();
if (currentCompilationUnit != null) {
DartImport[] imports = currentCompilationUnit.getLibrary().getImports();
- for (DartImport imprt : imports) {
- String prefix = imprt.getPrefix();
+ for (DartImport imp : imports) {
+ String prefix = imp.getPrefix();
if (prefix != null) {
prefixes.add(prefix);
}
@@ -1506,14 +1567,23 @@
}
}
- private void createCompletionsForFactoryInvocation(DartIdentifier memberName, InterfaceType itype) {
+ private void createCompletionsForFactoryInvocation(DartIdentifier memberName,
+ DartNode completionNode, InterfaceType itype) {
String prefix = extractFilterPrefix(memberName);
List<Element> members = getConstructors(itype);
if (!isCompletionAfterDot && memberName == null) {
return;
}
+ boolean isConst = false;
+ if (completionNode.getParent() instanceof DartNewExpression) {
+ DartNewExpression newExpr = (DartNewExpression) completionNode.getParent();
+ isConst = newExpr.isConst();
+ }
for (Element elem : members) {
MethodElement method = (MethodElement) elem;
+ if (isConst && !method.getModifiers().isConstant()) {
+ continue;
+ }
String name = method.getName();
if (prefix != null && !name.startsWith(prefix)) {
continue;
@@ -1543,6 +1613,27 @@
}
}
+ private void createCompletionsForIdentifierPrefix(DartNode ref, String prefix) {
+ if (prefix == null) {
+ prefix = "";
+ }
+ for (String candidate : prefixes) {
+ if (!candidate.startsWith(prefix)) {
+ continue;
+ }
+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
+ CompletionProposal.LIBRARY_PREFIX,
+ actualCompletionPosition - offset);
+// proposal.setDeclarationSignature(libraryElement.getLibraryUnit().getName().toCharArray());
+ proposal.setSignature(candidate.toCharArray());
+ proposal.setCompletion(candidate.toCharArray());
+ proposal.setName(candidate.toCharArray());
+ setSourceLoc(proposal, ref, prefix);
+ proposal.setRelevance(1);
+ requestor.accept(proposal);
+ }
+ }
+
private void createCompletionsForLibraryPrefix(DartIdentifier identifier,
LibraryElement libraryElement) {
String prefix = extractFilterPrefix(identifier);
@@ -1654,7 +1745,7 @@
}
private void createCompletionsForMethodInvocation(DartIdentifier node, Type type,
- boolean isQualifiedByThis, boolean isMethodStatic) {
+ boolean isQualifiedByThis, boolean allowDynamic, boolean isMethodStatic) {
String prefix = extractFilterPrefix(node);
if (TypeKind.of(type) == TypeKind.VOID) {
return;
@@ -1663,7 +1754,10 @@
boolean includeDeclaration = true;
List<Element> members;
if (TypeKind.of(itype) == TypeKind.DYNAMIC) {
- members = findAllElements(parsedUnit.getLibrary(), prefix);
+ members = findAllElements(prefix, node);
+ if (members.isEmpty() && allowDynamic) {
+ members = findAllElements(prefix, null);
+ }
includeDeclaration = false;
} else {
members = getAllElements(itype);
@@ -1729,7 +1823,7 @@
}
private void createCompletionsForPropertyAccess(DartIdentifier node, Type type,
- boolean isQualifiedByThis, boolean isMethodStatic) {
+ boolean isQualifiedByThis, boolean allowDynamic, boolean isMethodStatic) {
if (!(type instanceof InterfaceType)) {
return;
}
@@ -1738,7 +1832,10 @@
boolean includeDeclaration = true;
List<Element> members;
if (TypeKind.of(itype) == TypeKind.DYNAMIC) {
- members = findAllElements(parsedUnit.getLibrary(), prefix);
+ members = findAllElements(prefix, node);
+ if (members.isEmpty() && allowDynamic) {
+ members = findAllElements(prefix, null);
+ }
includeDeclaration = false;
} else {
members = getAllElements(itype);
@@ -1793,18 +1890,18 @@
}
private void createCompletionsForQualifiedMemberAccess(DartIdentifier memberName, Type type,
- boolean isInstance) {
+ boolean allowDynamic, boolean isInstance) {
// At the completion point, the language allows both field and method access.
// The parser needs more look-ahead to disambiguate. Those tokens may not have
// been typed yet.
- createCompletionsForPropertyAccess(memberName, type, isInstance, false);
- createCompletionsForMethodInvocation(memberName, type, isInstance, false);
+ createCompletionsForPropertyAccess(memberName, type, isInstance, allowDynamic, false);
+ createCompletionsForMethodInvocation(memberName, type, isInstance, allowDynamic, false);
}
private void createCompletionsForStaticVariables(DartIdentifier identifier, DartClass classDef) {
ClassElement elem = classDef.getElement();
Type type = elem.getType();
- createCompletionsForPropertyAccess(identifier, type, false, true);
+ createCompletionsForPropertyAccess(identifier, type, false, false, true);
}
private void createProposalsForLiterals(DartNode node, String... names) {
@@ -1822,7 +1919,8 @@
}
}
- private void createTypeCompletionsForConstructor(DartNode node, SearchMatch match, String prefix) {
+ private void createTypeCompletionsForConstructor(DartNode node, DartNewExpression newExpr,
+ SearchMatch match, String prefix) {
DartElement element = match.getElement();
if (!(element instanceof com.google.dart.tools.core.model.Type)) {
return;
@@ -1839,7 +1937,50 @@
if (disallowPrivate && name.startsWith("_")) {
return;
}
- if (!isCompletionAfterDot) {
+// if (!isCompletionAfterDot && false) {
+// InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
+// CompletionProposal.TYPE_REF, actualCompletionPosition - offset);
+// char[] nameChars = name.toCharArray();
+// proposal.setCompletion(nameChars);
+// proposal.setSignature(nameChars);
+// setSourceLoc(proposal, node, prefix);
+// proposal.setRelevance(1);
+// requestor.accept(proposal);
+// } else {
+ try {
+ for (com.google.dart.tools.core.model.Method method : type.getMethods()) {
+ if (method.isConstructor()) {
+ if (newExpr.isConst() && !method.getModifiers().isConstant()) {
+ continue;
+ }
+ name = method.getElementName(); // insert named constructors, too
+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
+ CompletionProposal.METHOD_REF,
+ actualCompletionPosition - offset);
+ char[] declaringTypeName = method.getDeclaringType().getElementName().toCharArray();
+ char[] methodName = name.toCharArray();
+ proposal.setDeclarationSignature(declaringTypeName);
+ proposal.setSignature(methodName);
+ proposal.setCompletion(methodName);
+ proposal.setName(methodName);
+ proposal.setIsContructor(method.isConstructor());
+ proposal.setIsGetter(false);
+ proposal.setIsSetter(false);
+ proposal.setParameterNames(getParameterNames(method));
+ proposal.setParameterTypeNames(getParameterTypeNames(method));
+ proposal.setTypeName(CharOperation.toCharArray(method.getReturnTypeName()));
+ proposal.setDeclarationTypeName(declaringTypeName);
+ setSourceLoc(proposal, node, prefix);
+ proposal.setRelevance(1);
+ requestor.setAllowsRequiredProposals(
+ CompletionProposal.CONSTRUCTOR_INVOCATION,
+ CompletionProposal.TYPE_REF,
+ true);
+ requestor.accept(proposal);
+ }
+ }
+ } catch (DartModelException exception) {
+ // TODO Remove this block?
InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
CompletionProposal.TYPE_REF,
actualCompletionPosition - offset);
@@ -1849,51 +1990,8 @@
setSourceLoc(proposal, node, prefix);
proposal.setRelevance(1);
requestor.accept(proposal);
- } else {
- try {
- for (com.google.dart.tools.core.model.Method method : type.getMethods()) {
- if (method.isConstructor()) {
- if (!method.getElementName().equals(name)) {
- // not sure why method.isFactory() doesn't work
- continue;
- }
- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
- CompletionProposal.METHOD_REF,
- actualCompletionPosition - offset);
- char[] declaringTypeName = method.getDeclaringType().getElementName().toCharArray();
- char[] methodName = name.toCharArray();
- proposal.setDeclarationSignature(declaringTypeName);
- proposal.setSignature(methodName);
- proposal.setCompletion(methodName);
- proposal.setName(methodName);
- proposal.setIsContructor(method.isConstructor());
- proposal.setIsGetter(false);
- proposal.setIsSetter(false);
- proposal.setParameterNames(getParameterNames(method));
- proposal.setParameterTypeNames(getParameterTypeNames(method));
- proposal.setTypeName(CharOperation.toCharArray(method.getReturnTypeName()));
- proposal.setDeclarationTypeName(declaringTypeName);
- setSourceLoc(proposal, node, prefix);
- proposal.setRelevance(1);
- requestor.setAllowsRequiredProposals(
- CompletionProposal.CONSTRUCTOR_INVOCATION,
- CompletionProposal.TYPE_REF,
- true);
- requestor.accept(proposal);
- }
- }
- } catch (DartModelException exception) {
- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(
- CompletionProposal.TYPE_REF,
- actualCompletionPosition - offset);
- char[] nameChars = name.toCharArray();
- proposal.setCompletion(nameChars);
- proposal.setSignature(nameChars);
- setSourceLoc(proposal, node, prefix);
- proposal.setRelevance(1);
- requestor.accept(proposal);
- }
}
+// }
}
private void createTypeCompletionsForGenericType(DartNode node, Type type, String prefix) {
@@ -2017,80 +2115,165 @@
return prefix.length() == 0 ? null : prefix;
}
+ private DartIdentifier extractLibraryPrefixQualifier(DartNode node) {
+ if (node == null || node.getParent() == null) {
+ return null;
+ }
+ DartNode parent = node.getParent();
+ // if the AST node looks like a library qualifier and the qualifier is in the prefix set
+ // then return the library prefix, otherwise null
+ if (parent instanceof DartPropertyAccess) {
+ DartPropertyAccess prop = (DartPropertyAccess) parent;
+ DartNode qualNode = prop.getQualifier();
+ if (qualNode instanceof DartTypeNode) {
+ qualNode = ((DartTypeNode) qualNode).getIdentifier();
+ }
+ if (qualNode instanceof DartIdentifier) {
+ return (DartIdentifier) qualNode;
+ }
+ }
+ return null;
+ }
+
+ private List<Element> findAllElements(String prefix, DartNode parent) {
+ // return all elements in parsedUnit library if no prefix specified
+ // return empty collection if specified prefix is not defined for at least one library
+ // return all elements in all libraries that have a specified prefix
+ DartIdentifier qualNode = extractLibraryPrefixQualifier(parent);
+ Collection<LibraryUnit> libs;
+ if (qualNode == null) {
+ libs = Collections.singleton(parsedUnit.getLibrary());
+ } else {
+ String prefixToMatch = qualNode.getName();
+ libs = parsedUnit.getLibrary().getLibrariesWithPrefix(prefixToMatch);
+ }
+ Set<LibraryUnit> searchedLibs = new HashSet<LibraryUnit>();
+ List<Element> elements = new ArrayList<Element>();
+ for (LibraryUnit lib : libs) {
+ Set<Element> elemSet = findAllElements(lib, prefix, searchedLibs);
+ elements.addAll(elemSet);
+ }
+ return elements;
+ }
+
+ private Collection<DartLibrary> findLibrariesForQualifier(DartNode node) {
+ // return null if no prefix is specified
+ // return empty collection if specified prefix is not defined for at least one library
+ // return all libraries that have a specified prefix
+ DartIdentifier qualNode = extractLibraryPrefixQualifier(node);
+ if (qualNode == null) {
+ return null;
+ } else {
+ String qual = qualNode.getName();
+ Collection<DartLibrary> result = new HashSet<DartLibrary>();
+ DartImport[] imports;
+ try {
+ if (currentCompilationUnit == null) {
+ return null; // special case for tests
+ }
+ imports = currentCompilationUnit.getLibrary().getImports();
+ } catch (DartModelException ex) {
+ return result;
+ }
+ for (DartImport imp : imports) {
+ String prefix = imp.getPrefix();
+ if (prefix != null && prefix.equals(qual)) {
+ result.add(imp.getLibrary());
+ }
+ }
+ return result;
+ }
+ }
+
private List<SearchMatch> findTypesWithPrefix(DartIdentifier id) {
SearchEngine engine = SearchEngineFactory.createSearchEngine();
- SearchScope scope = SearchScopeFactory.createWorkspaceScope();
- GatheringSearchListener listener = new GatheringSearchListener();
+ SearchScope scope;
+ Collection<DartLibrary> libs = findLibrariesForQualifier(id);
+ if (libs == null) {
+// if (currentCompilationUnit == null) {
+ // completion search should never use workspace scope, but tests don't set CU
+ scope = SearchScopeFactory.createWorkspaceScope();
+ // apparently, library scope does not include core lib so use workspace for now
+ // TODO figure out how to make the default search use core lib
+ // TODO should ALL searches use core lib?
+// } else {
+// scope = SearchScopeFactory.createLibraryScope(currentCompilationUnit.getLibrary());
+// }
+ } else {
+ if (libs.isEmpty()) {
+ return new ArrayList<SearchMatch>(0);
+ }
+ scope = SearchScopeFactory.createLibraryScope(libs);
+ }
String prefix = extractFilterPrefix(id);
if (prefix == null) {
prefix = "";
}
+ SearchPattern pattern = SearchPatternFactory.createPrefixPattern(prefix, true);
List<SearchMatch> matches;
try {
if (DartCoreDebug.NEW_INDEXER) {
matches = engine.searchTypeDeclarations(
scope,
- SearchPatternFactory.createPrefixPattern(prefix, true),
+ pattern,
(SearchFilter) null,
new NullProgressMonitor());
} else {
- engine.searchTypeDeclarations(
- scope,
- SearchPatternFactory.createPrefixPattern(prefix, true),
- null,
- listener,
- new NullProgressMonitor());
+ GatheringSearchListener listener = new GatheringSearchListener();
+ engine.searchTypeDeclarations(scope, pattern, null, listener, new NullProgressMonitor());
matches = listener.getMatches();
}
} catch (SearchException ex) {
return null;
}
- try {
- int idx = 0;
- for (com.google.dart.tools.core.model.Type localType : getCurrentCompilationUnit().getTypes()) {
- String typeName = localType.getElementName();
- if (typeName.startsWith(prefix)) { // this test is case sensitive
- SearchMatch match = new SearchMatch(
- MatchQuality.EXACT,
- MatchKind.NOT_A_REFERENCE,
- localType,
- localType.getSourceRange());
- boolean found = false;
- for (SearchMatch foundMatch : matches) {
- if (foundMatch.getElement().getElementName().equals(typeName)) {
- found = true;
- break;
+ if (libs == null) { // no prefix specified (vs undefined prefix)
+ try {
+ int idx = 0;
+ for (com.google.dart.tools.core.model.Type localType : getCurrentCompilationUnit().getTypes()) {
+ String typeName = localType.getElementName();
+ if (typeName.startsWith(prefix)) { // this test is case sensitive
+ SearchMatch match = new SearchMatch(
+ MatchQuality.EXACT,
+ MatchKind.NOT_A_REFERENCE,
+ localType,
+ localType.getSourceRange());
+ boolean found = false;
+ for (SearchMatch foundMatch : matches) {
+ if (foundMatch.getElement().getElementName().equals(typeName)) {
+ found = true;
+ break;
+ }
}
+ if (!found) {
+ matches.add(idx++, match);
+ }
}
- if (!found) {
- matches.add(idx++, match);
- }
}
- }
- for (com.google.dart.tools.core.model.DartFunctionTypeAlias localType : getCurrentCompilationUnit().getFunctionTypeAliases()) {
- String typeName = localType.getElementName();
- if (typeName.startsWith(prefix)) { // this test is case sensitive
- SearchMatch match = new SearchMatch(
- MatchQuality.EXACT,
- MatchKind.NOT_A_REFERENCE,
- localType,
- localType.getSourceRange());
- boolean found = false;
- for (SearchMatch foundMatch : matches) {
- if (foundMatch.getElement().getElementName().equals(typeName)) {
- found = true;
- break;
+ for (com.google.dart.tools.core.model.DartFunctionTypeAlias localType : getCurrentCompilationUnit().getFunctionTypeAliases()) {
+ String typeName = localType.getElementName();
+ if (typeName.startsWith(prefix)) { // this test is case sensitive
+ SearchMatch match = new SearchMatch(
+ MatchQuality.EXACT,
+ MatchKind.NOT_A_REFERENCE,
+ localType,
+ localType.getSourceRange());
+ boolean found = false;
+ for (SearchMatch foundMatch : matches) {
+ if (foundMatch.getElement().getElementName().equals(typeName)) {
+ found = true;
+ break;
+ }
}
+ if (!found) {
+ matches.add(idx++, match);
+ }
}
- if (!found) {
- matches.add(idx++, match);
- }
}
+ } catch (DartModelException ex) {
+ // no one cares
+ } catch (NullPointerException ex) {
+ // happens during tests because currentCompilationUnit is null
}
- } catch (DartModelException ex) {
- // no one cares
- } catch (NullPointerException ex) {
- // happens during tests because currentCompilationUnit is null
}
return matches;
}
@@ -2127,14 +2310,18 @@
for (SearchMatch match : matches) {
createTypeCompletionsForTypeDecl(identifier, match, prefix, isClass, !isClass);
}
+ createCompletionsForIdentifierPrefix(identifier, prefix);
}
- private void proposeGenericTypeCompletions(DartNode node) {
+ private void proposeGenericTypeCompletions(DartNode node, boolean includePrefixes) {
+ String prefix = extractFilterPrefix(node);
+ if (includePrefixes) {
+ createCompletionsForIdentifierPrefix(node, prefix);
+ }
if (classElement == null) {
// TODO Handle top-level functions
return;
}
- String prefix = extractFilterPrefix(node);
List<? extends Type> typeParams = classElement.getTypeParameters();
for (Type type : typeParams) {
createTypeCompletionsForGenericType(node, type, prefix);
@@ -2150,10 +2337,11 @@
for (SearchMatch match : matches) {
createTypeCompletionsForTypeDecl(identifier, match, prefix, false, false);
}
+ createCompletionsForIdentifierPrefix(identifier, prefix);
}
private void proposeTypesForNewParam() {
- proposeGenericTypeCompletions(null);
+ proposeGenericTypeCompletions(null, true);
// TODO Combine with proposeTypesForPrefix()
List<SearchMatch> matches = findTypesWithPrefix(null);
if (matches == null || matches.size() == 0) {
@@ -2183,6 +2371,7 @@
uniques.add(matchName);
createTypeCompletionsForParameterDecl(identifier, match, prefix);
}
+ createCompletionsForIdentifierPrefix(identifier, prefix);
if (allowVoid) {
if (prefix == null || prefix.length() == 0) {
createProposalsForLiterals(identifier, C_VOID);

Powered by Google App Engine
This is Rietveld 408576698