From e39b61f127c6e821647f6b847fc8032a3ca0f341 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Tue, 8 Jan 2019 12:22:59 -0600 Subject: [PATCH] Fix for #787: tweak relevance multipliers for fields and methods --- .../codeassist/tests/RelevanceTests.groovy | 45 ++++++++++++++++++- .../creators/FieldProposalCreator.java | 18 ++++---- .../creators/MethodProposalCreator.java | 25 ++++++----- ...ementAndExpressionCompletionProcessor.java | 8 ++-- .../proposals/AbstractGroovyProposal.java | 4 +- 5 files changed, 74 insertions(+), 26 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 31fe7e93fb..e32761eed2 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 @@ -1,5 +1,5 @@ /* - * Copyright 2009-2018 the original author or authors. + * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -118,6 +118,49 @@ final class RelevanceTests extends CompletionTestSuite { assertProposalOrdering(proposals, 'getAt', 'getDelegate()', 'getDirective()', 'getMetaClass()', 'getDefaultMetaClass()') } + @Test // https://github.com/groovy/groovy-eclipse/issues/787 + void testClosureMethodsAndProperties3() { + String contents = '''\ + class Outer { + static class Foo { + String string + } + static class Bar { + String string + void meth(Foo foo) { + foo.with { + s + } + } + } + } + '''.stripIndent() + ICompletionProposal[] proposals = orderByRelevance(createProposalsAtOffset(contents, getLastIndexOf(contents, 's'))) + assertProposalOrdering(proposals, 'string : String - Foo', 'string : String - Bar', 'setString(String value) : void - Foo', 'setString(String value) : void - Bar', 'setMetaClass') + } + + @Test + void testClosureMethodsAndProperties4() { + String contents = '''\ + class Outer { + static class Foo { + String string + } + static class Bar { + String string + def foo(@DelegatesTo(value=Foo, strategy=Closure.OWNER_FIRST) Closure c) {} + void meth() { + foo { -> + s + } + } + } + } + '''.stripIndent() + ICompletionProposal[] proposals = orderByRelevance(createProposalsAtOffset(contents, getLastIndexOf(contents, 's'))) + assertProposalOrdering(proposals, 'string : String - Bar', 'string : String - Foo', 'setString(String value) : void - Bar', 'setString(String value) : void - Foo', 'setMetaClass') + } + @Test void testStaticImportFieldsAndMethods() { String contents = '''\ diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/FieldProposalCreator.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/FieldProposalCreator.java index 8f36591c6f..274b8d4909 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/FieldProposalCreator.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/FieldProposalCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2018 the original author or authors. + * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,12 +59,8 @@ public List findAllProposals(ClassNode type, Set cat for (FieldNode field : allFields) { // in static context, only allow static fields if ((!isStatic || field.isStatic()) && matcher.test(prefix, field.getName())) { - // de-emphasize 'this' references inside closure - float relevanceMultiplier = !firstTime ? 0.1f : 1.0f; - if (field.isEnum()) relevanceMultiplier *= 5.0f; - GroovyFieldProposal proposal = new GroovyFieldProposal(field); - proposal.setRelevanceMultiplier(relevanceMultiplier); + proposal.setRelevanceMultiplier(field.isEnum() ? 5 : 1); proposals.add(proposal); if (field.getInitialExpression() instanceof ClosureExpression) { @@ -128,7 +124,9 @@ private void findStaticImportProposals(List proposals, String p if (fieldName != null && matcher.test(prefix, fieldName)) { FieldNode field = entry.getValue().getType().getField(fieldName); if (field != null && field.isStatic()) { - proposals.add(new GroovyFieldProposal(field)); + GroovyFieldProposal proposal = new GroovyFieldProposal(field); + proposal.setRelevanceMultiplier(0.95f); + proposals.add(proposal); } } } @@ -137,7 +135,9 @@ private void findStaticImportProposals(List proposals, String p if (type != null) { for (FieldNode field : type.getFields()) { if (field.isStatic() && matcher.test(prefix, field.getName())) { - proposals.add(new GroovyFieldProposal(field)); + GroovyFieldProposal proposal = new GroovyFieldProposal(field); + proposal.setRelevanceMultiplier(0.95f); + proposals.add(proposal); } } } @@ -163,6 +163,7 @@ private void findStaticFavoriteProposals(List proposals, String if (field.isStatic() && matcher.test(prefix, field.getName())) { GroovyFieldProposal proposal = new GroovyFieldProposal(field); proposal.setRequiredStaticImport(typeName + '.' + field.getName()); + proposal.setRelevanceMultiplier(0.95f); proposals.add(proposal); } } @@ -172,6 +173,7 @@ private void findStaticFavoriteProposals(List proposals, String if (field != null && field.isStatic()) { GroovyFieldProposal proposal = new GroovyFieldProposal(field); proposal.setRequiredStaticImport(favoriteStaticMember); + proposal.setRelevanceMultiplier(0.95f); proposals.add(proposal); } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/MethodProposalCreator.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/MethodProposalCreator.java index 018c8c5ed6..d72041cf63 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/MethodProposalCreator.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/MethodProposalCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2018 the original author or authors. + * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,7 +62,7 @@ public List findAllProposals(ClassNode type, Set cat if ((!isStatic || method.isStatic() || method.getDeclaringClass().equals(VariableScope.OBJECT_CLASS_NODE))) { if (matcher.test(prefix, methodName) && !"".equals(methodName)) { GroovyMethodProposal proposal = new GroovyMethodProposal(method); - setRelevanceMultiplier(proposal, firstTime, isStatic); + setRelevanceMultiplier(proposal, isStatic); proposals.add(proposal); } @@ -115,7 +115,9 @@ private void findStaticImportProposals(List proposals, String p if (methods != null) { for (MethodNode method : methods) { if (method.isStatic()) { - proposals.add(new GroovyMethodProposal(method)); + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setRelevanceMultiplier(0.95f); + proposals.add(proposal); } } } @@ -126,7 +128,9 @@ private void findStaticImportProposals(List proposals, String p if (type != null) { for (MethodNode method : type.getMethods()) { if (method.isStatic() && matcher.test(prefix, method.getName())) { - proposals.add(new GroovyMethodProposal(method)); + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setRelevanceMultiplier(0.95f); + proposals.add(proposal); } } } @@ -152,6 +156,7 @@ private void findStaticFavoriteProposals(List proposals, String if (method.isStatic() && matcher.test(prefix, method.getName())) { GroovyMethodProposal proposal = new GroovyMethodProposal(method); proposal.setRequiredStaticImport(typeName + '.' + method.getName()); + proposal.setRelevanceMultiplier(0.95f); proposals.add(proposal); } } @@ -162,6 +167,7 @@ private void findStaticFavoriteProposals(List proposals, String if (method.isStatic()) { GroovyMethodProposal proposal = new GroovyMethodProposal(method); proposal.setRequiredStaticImport(favoriteStaticMember); + proposal.setRelevanceMultiplier(0.95f); proposals.add(proposal); } } @@ -170,21 +176,16 @@ private void findStaticFavoriteProposals(List proposals, String } } - private void setRelevanceMultiplier(GroovyMethodProposal proposal, boolean firstTime, boolean isStatic) { + private void setRelevanceMultiplier(GroovyMethodProposal proposal, boolean isStatic) { MethodNode method = proposal.getMethod(); float relevanceMultiplier; if (isStatic && method.isStatic()) { - relevanceMultiplier = 1.10f; + relevanceMultiplier = 1.05f; } else if (!method.isStatic()) { relevanceMultiplier = 1.00f; } else { - relevanceMultiplier = 0.77f; - } - - // de-emphasize 'this' references inside closure - if (!firstTime) { - relevanceMultiplier *= 0.1f; + relevanceMultiplier = 0.95f; } proposal.setRelevanceMultiplier(relevanceMultiplier); diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/StatementAndExpressionCompletionProcessor.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/StatementAndExpressionCompletionProcessor.java index a6cdd5acd2..02021c602f 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/StatementAndExpressionCompletionProcessor.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/StatementAndExpressionCompletionProcessor.java @@ -375,7 +375,7 @@ private static void setClosureQualifiers(Collection delegatePro Consumer reduceRelevance = p -> { AbstractGroovyProposal agp = (AbstractGroovyProposal) p; - agp.setRelevanceMultiplier(agp.getRelevanceMultiplier() * 0.9f); + agp.setRelevanceMultiplier(agp.getRelevanceMultiplier() * 0.999f); }; if (!delegateProposals.isEmpty()) { @@ -383,7 +383,8 @@ private static void setClosureQualifiers(Collection delegatePro if (resolveStrategy == Closure.OWNER_FIRST && !ownerProposals.isEmpty()) { Set names = ownerProposals.stream().map(toName).collect(Collectors.toSet()); - delegateProposals.stream().filter(p -> names.contains(toName.apply(p))).forEach(addDelegateQualifier); + delegateProposals.stream().filter(p -> names.contains(toName.apply(p))) + .forEach(addDelegateQualifier.andThen(reduceRelevance)); } else if (resolveStrategy == Closure.TO_SELF) { delegateProposals.forEach(addDelegateQualifier.andThen(reduceRelevance)); } @@ -394,7 +395,8 @@ private static void setClosureQualifiers(Collection delegatePro if (resolveStrategy == Closure.DELEGATE_FIRST && !delegateProposals.isEmpty()) { Set names = delegateProposals.stream().map(toName).collect(Collectors.toSet()); - ownerProposals.stream().filter(p -> names.contains(toName.apply(p))).forEach(addOwnerQualifier); + ownerProposals.stream().filter(p -> names.contains(toName.apply(p))) + .forEach(addOwnerQualifier.andThen(reduceRelevance)); } else if (resolveStrategy == Closure.TO_SELF) { ownerProposals.forEach(addOwnerQualifier.andThen(reduceRelevance)); } 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 4c89d4ddf6..cb557a6ac9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2009-2018 the original author or authors. + * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -141,7 +141,7 @@ protected int computeRelevance(ContentAssistContext context) { } if (relevance > 1 && this instanceof GroovyMethodProposal) { - relevance *= 0.9f; // promote fields + relevance *= 0.99f; // promote fields } return Math.max(relevance, RelevanceConstants.R_INTERESTING);