Skip to content

Commit

Permalink
Fix for issue #367: propose one set of enum values for guessed params
Browse files Browse the repository at this point in the history
respect Content Assist preferences:
 - Add import instead of qualified name
 - Use static imports (only 1.5 or higher)
  • Loading branch information
eric-milles committed Jan 24, 2018
1 parent 016acc4 commit 5817fe3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,8 @@ final class GuessingCompletionTests extends CompletionTestSuite {

// check the parameter guesses
ICompletionProposal[] choices = proposal.choices[0]
Assert.assertEquals(['MILLIS', 'DAYS', 'TimeUnit.DAYS', 'HOURS', 'TimeUnit.HOURS', 'MINUTES', 'TimeUnit.MINUTES',
'SECONDS', 'TimeUnit.SECONDS', 'MILLISECONDS', 'TimeUnit.MILLISECONDS', 'MICROSECONDS', 'TimeUnit.MICROSECONDS',
'NANOSECONDS', 'TimeUnit.NANOSECONDS', 'null'].join('\n'), choices*.displayString.join('\n'))
Assert.assertEquals(['MILLIS', 'DAYS', 'HOURS', 'MINUTES', 'SECONDS', 'MILLISECONDS', 'MICROSECONDS', 'NANOSECONDS', 'null'].join('\n'),
choices*.displayString.join('\n'))

// TODO: Something below is not matching the real editor's application of the parameter proposal
/*applyProposalAndCheck(document, choices[1], '''\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private IJavaElement[] computeVisibleElements(String typeSignature) {
if (GroovyUtils.isAssignable(type, targetType)) {
// NOTE: parent, source location, typeSignature, etc. are not important here
int start = 0, until = varName.length() - 1;
visibleElements.put(varName, new LocalVariable(
visibleElements.putIfAbsent(varName, new LocalVariable(
(JavaElement) getEnclosingElement(), varName, start, until, start, until, typeSignature, null, 0, false));
}
}
Expand All @@ -165,8 +165,7 @@ private IJavaElement[] computeVisibleElements(String typeSignature) {
IType enumType = new GroovyProjectFacade(enclosingElement).groovyClassToJavaType(targetType);
for (IField enumField : enumType.getFields()) {
if (enumField.isEnumConstant()) {
visibleElements.put(enumField.getElementName(), enumField);
visibleElements.put(enumType.getElementName() + '.' + enumField.getElementName(), enumField);
visibleElements.putIfAbsent(enumField.getElementName(), enumField);
}
}
} catch (JavaModelException e) {
Expand All @@ -176,26 +175,22 @@ private IJavaElement[] computeVisibleElements(String typeSignature) {
return visibleElements.values().toArray(new IJavaElement[0]);
}

public void addFields(ClassNode targetType, Map<String, IJavaElement> nameElementMap, IType type)
public void addFields(ClassNode targetType, Map<String, IJavaElement> visibleElements, IType type)
throws JavaModelException {
IField[] fields = type.getFields();
for (IField field : fields) {
for (IField field : type.getFields()) {
ClassNode fieldTypeClassNode = toClassNode(field.getTypeSignature());
if (GroovyUtils.isAssignable(fieldTypeClassNode, targetType)) {
nameElementMap.put(field.getElementName(), field);
visibleElements.putIfAbsent(field.getElementName(), field);
}
}
// also add methods
IMethod[] methods = type.getMethods();
for (IMethod method : methods) {
for (IMethod method : type.getMethods()) {
ClassNode methodReturnTypeClassNode = toClassNode(method.getReturnType());
if (GroovyUtils.isAssignable(methodReturnTypeClassNode, targetType)) {
if ((method.getParameterTypes() == null || method.getParameterTypes().length == 0) &&
(method.getElementName().startsWith("get") || method.getElementName().startsWith("is"))) {

nameElementMap.put(method.getElementName(), method);
(method.getElementName().startsWith("get") || method.getElementName().startsWith("is"))) {
visibleElements.putIfAbsent(method.getElementName(), method);
IField field = new PropertyVariant(method);
nameElementMap.put(field.getElementName(), field);
visibleElements.putIfAbsent(field.getElementName(), field);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,21 @@
*/
package org.codehaus.groovy.eclipse.codeassist.completions;

import java.util.HashSet;
import java.util.Set;

import org.codehaus.groovy.eclipse.codeassist.GroovyContentAssist;
import org.codehaus.groovy.eclipse.codeassist.ProposalUtils;
import org.codehaus.groovy.eclipse.codeassist.processors.GroovyCompletionProposal;
import org.eclipse.jdt.core.CompletionFlags;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.groovy.core.util.ArrayUtils;
import org.eclipse.jdt.groovy.search.VariableScope;
import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
import org.eclipse.jdt.internal.ui.text.java.FieldProposalInfo;
import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal;
import org.eclipse.jdt.internal.ui.text.java.ParameterGuesser;
import org.eclipse.jdt.internal.ui.text.template.contentassist.PositionBasedCompletionProposal;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
Expand All @@ -57,10 +55,9 @@ public ICompletionProposal[] parameterProposals(String parameterType, String par
if (completions != null && completions.length > 0 && suggestions != null && suggestions.length > 0) {
IType declaring = (IType) suggestions[suggestions.length - 1].getAncestor(IJavaElement.TYPE);
if (declaring != null && declaring.isEnum()) {
// each enum constant is proposed twice; see GroovyExtendedCompletionContext.computeVisibleElements
boolean preferStaticImport = isStaticImportPreferred();

// NOTE: completions and suggestions are not parallel arrays
Set<String> seen = new HashSet<>(suggestions.length);
for (int i = 0; i < completions.length; i += 1) {
ICompletionProposal completion = completions[i];

Expand All @@ -74,18 +71,16 @@ public ICompletionProposal[] parameterProposals(String parameterType, String par
}

if (suggestion != null) {
GroovyCompletionProposal supporting;
CompletionProposal supporting;
String replacement = completion.getDisplayString();

// for first occurrence, propose "NAME"; for second occurrence, propose "Type.NAME"
if (seen.add(replacement)) {
supporting = new GroovyCompletionProposal(CompletionProposal.FIELD_IMPORT, 0);
if (preferStaticImport) {
supporting = CompletionProposal.create(CompletionProposal.FIELD_IMPORT, 0);
supporting.setAdditionalFlags(CompletionFlags.StaticImport);
supporting.setDeclarationSignature(Signature.createTypeSignature(declaring.getFullyQualifiedName(), true).toCharArray());
supporting.setName(replacement.toCharArray());
} else {
replacement = declaring.getElementName() + '.' + replacement;
supporting = new GroovyCompletionProposal(CompletionProposal.TYPE_IMPORT, 0);
supporting = CompletionProposal.create(CompletionProposal.TYPE_IMPORT, 0);
supporting.setSignature(Signature.createTypeSignature(declaring.getFullyQualifiedName(), true).toCharArray());
}

Expand Down Expand Up @@ -145,19 +140,38 @@ private ICompletionProposal[] addExtras(ICompletionProposal[] parameterProposals
return parameterProposals;
}

private boolean isStaticImportPreferred() {
if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.CODEASSIST_ADDIMPORT)) {
return new AssistOptions(invocationContext.getProject().getOptions(true)).suggestStaticImport;
}
return false;
}

private ICompletionProposal newEnumProposal(Position position, String replacement, CompletionProposal supporting, Image image, char[] triggers) {
GroovyCompletionProposal groovyProposal = new GroovyCompletionProposal(CompletionProposal.FIELD_REF, 0);
CompletionProposal groovyProposal = CompletionProposal.create(CompletionProposal.METHOD_REF, 0);
groovyProposal.setRequiredProposals(new CompletionProposal[] {supporting});

// replacement offset and length are not known at this time, so they must be supplied from Position upon request
JavaCompletionProposal javaProposal = new JavaCompletionProposal(replacement, 0, 0, image, null, 1, false, invocationContext) {
@Override
public int getReplacementLength() {
return position.getLength();
}
@Override
public int getReplacementOffset() {
return position.getOffset();
}
@Override
public int getReplacementLength() {
return position.getLength();
public void setReplacementOffset(int offset) {
if (offset > getReplacementOffset()) {
position.setOffset(getReplacementOffset() + (getReplacementLength() - super.getReplacementLength()));
position.setLength(super.getReplacementLength());
}
super.setReplacementOffset(offset);
}
@Override
public void setReplacementLength(int length) {
super.setReplacementLength(length);
}
};
javaProposal.setProposalInfo(new FieldProposalInfo(invocationContext.getProject(), groovyProposal));
Expand Down

0 comments on commit 5817fe3

Please sign in to comment.