From 15ebd7cfdafbfd3a5764ae2b83584c28bdd3bffe Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Sun, 12 Aug 2018 20:45:16 -0500 Subject: [PATCH] Fix for #411: boost relevance for exact, prefix, camel case or substring --- .../codeassist/tests/RelevanceTests.groovy | 32 +++++++++--- .../eclipse/codeassist/ProposalUtils.java | 2 +- .../proposals/AbstractGroovyProposal.java | 51 +++++++++++++++---- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/RelevanceTests.groovy b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/RelevanceTests.groovy index ef3cbd1d5f..3cb442db65 100644 --- a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/RelevanceTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/RelevanceTests.groovy @@ -25,21 +25,23 @@ import org.junit.Test final class RelevanceTests extends CompletionTestSuite { @Test - void testParamThenFieldThenMethodThenDGM() { + void testExactMatchThenPrefixMatchThenIgnoreCaseThenCamelCaseThenSubstring() { String contents = '''\ class Outer { - def f - def m(p) { - null - } + def aToZ() {} + def toz() {} + def Toz() {} + def toZAbc() {} + def tozXyz() {} } + new Outer().toz '''.stripIndent() - ICompletionProposal[] proposals = orderByRelevance(createProposalsAtOffset(contents, getIndexOf(contents, 'null\n'))) - assertProposalOrdering(proposals, 'p', 'f', 'getF', 'm', 'find') + ICompletionProposal[] proposals = orderByRelevance(createProposalsAtOffset(contents, getLastIndexOf(contents, 'toz'))) + assertProposalOrdering(proposals, 'toz', 'tozXyz', 'Toz', 'toZAbc', 'aToZ') } @Test - void testLocalVarThenFieldThenMethodThenDGM() { + void testLocalThenFieldThenMethodThenDGM() { String contents = '''\ class Outer { def f @@ -52,6 +54,20 @@ final class RelevanceTests extends CompletionTestSuite { assertProposalOrdering(proposals, 'p', 'f', 'getF', 'm', 'find') } + @Test + void testParamThenFieldThenMethodThenDGM() { + String contents = '''\ + class Outer { + def f + def m(p) { + null + } + } + '''.stripIndent() + ICompletionProposal[] proposals = orderByRelevance(createProposalsAtOffset(contents, getIndexOf(contents, 'null\n'))) + assertProposalOrdering(proposals, 'p', 'f', 'getF', 'm', 'find') + } + @Test void testObjectMethods() { String contents = '''\ diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/ProposalUtils.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/ProposalUtils.java index 6e917de5b9..4e6888d4e0 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/ProposalUtils.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/ProposalUtils.java @@ -251,6 +251,6 @@ public static boolean matches(String pattern, String candidate, boolean camelCas if (camelCaseMatch && SearchPattern.camelCaseMatch(pattern, candidate)) { return true; } - return substringMatch ? candidate.toLowerCase().contains(pattern) : candidate.startsWith(pattern); + return substringMatch ? CharOperation.substringMatch(pattern, candidate) : candidate.startsWith(pattern); } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/AbstractGroovyProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/AbstractGroovyProposal.java index d78c2b952d..ca6ce640a2 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/AbstractGroovyProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/AbstractGroovyProposal.java @@ -26,8 +26,12 @@ import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.eclipse.codeassist.relevance.Relevance; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext; +import org.codehaus.groovy.runtime.StringGroovyMethods; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.groovy.core.util.GroovyUtils; import org.eclipse.jdt.groovy.search.VariableScope; +import org.eclipse.jdt.internal.codeassist.RelevanceConstants; public abstract class AbstractGroovyProposal implements IGroovyProposal { @@ -82,17 +86,44 @@ protected int computeRelevance(ContentAssistContext context) { int relevance = getRelevanceClass().getRelevance(getRelevanceMultiplier()); AnnotatedNode node = getAssociatedNode(); - if (node != null && context.lhsType != null) { - ClassNode type = null; - if (node instanceof FieldNode) { - type = ((FieldNode) node).getType(); - } else if (node instanceof MethodNode) { - type = ((MethodNode) node).getReturnType(); - } else if (node instanceof PropertyNode) { - type = ((PropertyNode) node).getType(); + if (node != null) { + if (context.lhsType != null) { + ClassNode type = null; + if (node instanceof FieldNode) { + type = ((FieldNode) node).getType(); + } else if (node instanceof MethodNode) { + type = ((MethodNode) node).getReturnType(); + } else if (node instanceof PropertyNode) { + type = ((PropertyNode) node).getType(); + } + if (type != null && GroovyUtils.isAssignable(type, context.lhsType)) { + relevance = Math.max(relevance, Relevance.HIGH.getRelevance()); + } } - if (type != null && GroovyUtils.isAssignable(type, context.lhsType)) { - relevance = Math.max(relevance, Relevance.HIGH.getRelevance()); + + if (StringGroovyMethods.asBoolean(context.completionExpression)) { + String name = null; + if (node instanceof FieldNode) { + name = ((FieldNode) node).getName(); + } else if (node instanceof MethodNode) { + name = ((MethodNode) node).getName(); + } else if (node instanceof PropertyNode) { + name = ((PropertyNode) node).getName(); + } + if (StringGroovyMethods.asBoolean(name)) { + String expr = context.getPerceivedCompletionExpression(); + if (name.equals(expr)) { + relevance += RelevanceConstants.R_EXACT_NAME + RelevanceConstants.R_CASE; + } else if (name.equalsIgnoreCase(expr)) { + relevance += RelevanceConstants.R_EXACT_NAME; + } else if (/*name.startsWithIgnoreCase(expr)*/CharOperation.prefixEquals(expr.toCharArray(), name.toCharArray(), false)) { + if (name.startsWith(expr)) relevance += RelevanceConstants.R_CASE; + } else if (/*options.camelCaseMatch &&*/ SearchPattern.camelCaseMatch(expr, name)) { + relevance += RelevanceConstants.R_CAMEL_CASE; + } else if (/*options.substringMatch &&*/ CharOperation.substringMatch(expr, name)) { + relevance += RelevanceConstants.R_SUBSTRING; + } + } } }