diff --git a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/FieldCompletionTests.groovy b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/FieldCompletionTests.groovy index 34e04a6ddd..ed0433a86c 100644 --- a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/FieldCompletionTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/FieldCompletionTests.groovy @@ -17,14 +17,19 @@ package org.codehaus.groovy.eclipse.codeassist.tests import org.codehaus.groovy.eclipse.codeassist.requestor.GroovyCompletionProposalComputer import org.eclipse.jdt.core.ICompilationUnit +import org.eclipse.jdt.ui.PreferenceConstants +import org.eclipse.jface.text.Document import org.eclipse.jface.text.contentassist.ICompletionProposal +import org.junit.After import org.junit.Test -/** - * Tests that Field completions are working properly. - */ final class FieldCompletionTests extends CompletionTestSuite { + @After + void tearDown() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, '') + } + @Test void testSafeDeferencing() { String contents = "public class SomeClass {\nint someProperty\nvoid someMethod() { someProperty?.x}}" @@ -361,4 +366,58 @@ final class FieldCompletionTests extends CompletionTestSuite { ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "."), GroovyCompletionProposalComputer) proposalExists(proposals, "forName", 2) // two public and one private } + + @Test + void testImportStaticField() { + String contents = '''\ + import static java.util.regex.Pattern.DOTALL + DOT + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'DOT'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'DOTALL', 1) + } + + @Test + void testImportStaticStarField() { + String contents = '''\ + import static java.util.regex.Pattern.* + DOT + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'DOT'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'DOTALL', 1) + } + + @Test + void testFavoriteStaticField() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, 'java.util.regex.Pattern.DOTALL') + + String contents = '''\ + DOT + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'DOT'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'DOTALL', 1) + + applyProposalAndCheck(new Document(contents), findFirstProposal(proposals, 'DOTALL', false), '''\ + |import static java.util.regex.Pattern.DOTALL + | + |DOTALL + |'''.stripMargin()) + } + + @Test + void testFavoriteStaticStarField() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, 'java.util.regex.Pattern.*') + + String contents = '''\ + DOT + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'DOT'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'DOTALL', 1) + + applyProposalAndCheck(new Document(contents), findFirstProposal(proposals, 'DOTALL', false), '''\ + |import static java.util.regex.Pattern.DOTALL + | + |DOTALL + |'''.stripMargin()) + } } diff --git a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/MethodCompletionTests.groovy b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/MethodCompletionTests.groovy index 3cb7778288..a0791f1e54 100644 --- a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/MethodCompletionTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/MethodCompletionTests.groovy @@ -15,6 +15,10 @@ */ package org.codehaus.groovy.eclipse.codeassist.tests +import static org.eclipse.jdt.core.tests.util.GroovyUtils.isAtLeastGroovy +import static org.junit.Assert.fail +import static org.junit.Assume.assumeTrue + import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.stmt.ExpressionStatement @@ -22,296 +26,365 @@ import org.codehaus.groovy.ast.stmt.ReturnStatement import org.codehaus.groovy.ast.stmt.Statement import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyMethodProposal import org.codehaus.groovy.eclipse.codeassist.requestor.GroovyCompletionProposalComputer -import org.codehaus.groovy.eclipse.test.SynchronizationUtils import org.codehaus.jdt.groovy.model.GroovyCompilationUnit -import org.eclipse.jdt.core.ICompilationUnit import org.eclipse.jdt.core.compiler.CharOperation +import org.eclipse.jdt.ui.PreferenceConstants +import org.eclipse.jface.text.Document import org.eclipse.jface.text.contentassist.ICompletionProposal +import org.junit.After import org.junit.Test -/** - * Tests that Method completions are working properly. - */ final class MethodCompletionTests extends CompletionTestSuite { - private static class MockGroovyMethodProposal extends GroovyMethodProposal { - public MockGroovyMethodProposal(MethodNode method) { - super(method) + @After + void tearDown() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, '') + } + + private List delegateTestParameterNames(GroovyCompilationUnit unit) { + waitForIndex() + List methods = extract(unit).getMethods('m') + for (MethodNode method : methods) { + if (method.getParameters().length == 1) { + GroovyMethodProposal proposal = new GroovyMethodProposal(method) + char[][] names = proposal.createAllParameterNames(unit) + checkNames(['x'.toCharArray()] as char[][], names) + } + if (method.getParameters().length == 2) { + GroovyMethodProposal proposal = new GroovyMethodProposal(method) + char[][] names = proposal.createAllParameterNames(unit) + checkNames(['x'.toCharArray(), 'y'.toCharArray()] as char[][], names) + } } - @Override - protected char[][] createAllParameterNames(ICompilationUnit unit) { - super.createAllParameterNames(unit) + return methods + } + + private static ClassNode extract(GroovyCompilationUnit unit) { + Statement state = unit.getModuleNode().getStatementBlock().getStatements().get(0) + if (state instanceof ReturnStatement) { + ReturnStatement ret = (ReturnStatement) state + return ret.getExpression().getType() + } else if (state instanceof ExpressionStatement) { + ExpressionStatement expr = (ExpressionStatement) state + return expr.getExpression().getType() + } else { + fail('Invalid statement kind for ' + state + '\nExpecting return statement or expression statement') + return null } } + private static void checkNames(char[][] expected, char[][] names) { + if (!CharOperation.equals(expected, names)) { + fail('Wrong number of parameter names. Expecting:\n' + CharOperation.toString(expected) + '\n\nbut found:\n' + CharOperation.toString(names)) + } + } + + //-------------------------------------------------------------------------- + @Test void testAfterParens1() { - String contents = "HttpRetryException f() {\nnull\n}\nf()." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f()."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + HttpRetryException f() { null } + f(). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f().'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testAfterParens2() { - String contents = "HttpRetryException f() {\nnull\n}\nthis.f()." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f()."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + HttpRetryException f() { null } + this.f(). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f().'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testAfterParens3() { - String contents = "class Super {HttpRetryException f() {\nnull\n}}\nnew Super().f()." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f()."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + class Super { HttpRetryException f() { null } } + new Super().f(). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f().'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testAfterParens4() { - String contents = "class Super {HttpRetryException f() {\nnull\n}}\nclass Sub extends Super { }\nnew Sub().f()." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f()."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + class Super { HttpRetryException f() { null } } + class Sub extends Super { } + new Sub().f(). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f().'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testAfterParens5() { - String contents = "class Super {HttpRetryException f(arg) {\nnull\n}}\ndef s = new Super()\ns.f(null)." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f(null)."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + class Super { HttpRetryException f(arg) { null } } + def s = new Super() + s.f(null). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f(null).'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testAfterParens6() { - String contents = "class Super {HttpRetryException f() {\nnull\n}}\ndef s = new Super()\ns.f()." - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "f()."), GroovyCompletionProposalComputer) - proposalExists(proposals, "cause", 1) + String contents = '''\ + class Super { HttpRetryException f() { null } } + def s = new Super() + s.f(). + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'f().'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'cause', 1) } @Test void testParameterNames1() { - String contents = "import org.codehaus.groovy.runtime.DefaultGroovyMethods\nnew DefaultGroovyMethods()" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ClassNode clazz = extract((GroovyCompilationUnit) unit) - List methods = clazz.getMethods("is") + String contents = '''\ + import org.codehaus.groovy.runtime.DefaultGroovyMethods + new DefaultGroovyMethods() + '''.stripIndent() + GroovyCompilationUnit gunit = addGroovySource(contents) + ClassNode clazz = extract(gunit) + List methods = clazz.getMethods('is') for (MethodNode method : methods) { if (method.getParameters().length == 2) { - MockGroovyMethodProposal proposal = new MockGroovyMethodProposal(method) - char[][] names = proposal.createAllParameterNames(unit) - checkNames(["self".toCharArray(), "other".toCharArray()] as char[][], names) + GroovyMethodProposal proposal = new GroovyMethodProposal(method) + char[][] names = proposal.createAllParameterNames(gunit) + checkNames(['self'.toCharArray(), 'other'.toCharArray()] as char[][], names) } } if (methods.size() != 1) { - fail("expecting to find 1 'is' method, but instead found " + methods.size() + ":\n" + methods) + fail('expecting to find 1 \"is\" method, but instead found ' + methods.size() + ':\n' + methods) } } @Test void testParameterNames2() { - String contents = "MyClass\nclass MyClass { def m(int x) { }\ndef m(String x, int y) { }}" - GroovyCompilationUnit unit = addGroovySource(contents, "File", "") - ClassNode clazz = extract(unit) - List methods = clazz.getMethods("m") + String contents = '''\ + MyClass + class MyClass { + def m(int x) { } + def m(String x, int y) { } + } + '''.stripIndent() + GroovyCompilationUnit gunit = addGroovySource(contents) + ClassNode clazz = extract(gunit) + List methods = clazz.getMethods('m') for (MethodNode method : methods) { if (method.getParameters().length == 1) { - MockGroovyMethodProposal proposal = new MockGroovyMethodProposal(method) - char[][] names = proposal.createAllParameterNames(unit) - checkNames(["x".toCharArray()] as char[][], names) + GroovyMethodProposal proposal = new GroovyMethodProposal(method) + char[][] names = proposal.createAllParameterNames(gunit) + checkNames(['x'.toCharArray()] as char[][], names) } if (method.getParameters().length == 2) { - MockGroovyMethodProposal proposal = new MockGroovyMethodProposal(method) - char[][] names = proposal.createAllParameterNames(unit) - checkNames(["x".toCharArray(), "y".toCharArray()] as char[][], names) + GroovyMethodProposal proposal = new GroovyMethodProposal(method) + char[][] names = proposal.createAllParameterNames(gunit) + checkNames(['x'.toCharArray(), 'y'.toCharArray()] as char[][], names) } } if (methods.size() != 2) { - fail("expecting to find 2 m methods, but instead found " + methods.size() + ":\n" + methods) + fail('expecting to find 2 "m" methods, but instead found ' + methods.size() + ':\n' + methods) } } @Test void testParameterNames3() { - String contents = "class MyClass { def m(int x) { }\ndef m(String x, int y) { }}" - addGroovySource(contents, "File", "") - GroovyCompilationUnit unit = addGroovySource("new MyClass()", "Other", "") + addGroovySource('class MyClass { def m(int x) { }\ndef m(String x, int y) { } }') + GroovyCompilationUnit gunit = addGroovySource('new MyClass()', 'Other') List methods = null for (int i = 0; i < 5; i++) { - methods = delegateTestParameterNames(unit) + methods = delegateTestParameterNames(gunit) if (methods.size() == 2) { - // expected - return + return // as expected } } - fail("expecting to find 2 'm' methods, but instead found " + methods.size() + ":\n" + methods) + fail('expecting to find 2 "m" methods, but instead found ' + methods.size() + ':\n' + methods) } @Test void testParameterNames4() { - addJavaSource("public class MyJavaClass { void m(int x) { }\nvoid m(String x, int y) { }}", "MyJavaClass", "") - GroovyCompilationUnit unit = addGroovySource("new MyJavaClass()", "Other", "") + addJavaSource('public class MyJavaClass { void m(int x) { } void m(String x, int y) { } }', 'MyJavaClass') + GroovyCompilationUnit gunit = addGroovySource('new MyJavaClass()', 'Other') List methods = null for (int i = 0; i < 5; i++) { - methods = delegateTestParameterNames(unit) + methods = delegateTestParameterNames(gunit) if (methods.size() == 2) { - // expected - return + return // as expected } } - fail("expecting to find 2 'm' methods, but instead found " + methods.size() + ":\n" + methods) + fail('expecting to find 2 "m" methods, but instead found ' + methods.size() + ':\n' + methods) } @Test // GRECLIPSE-1374 void testParensExprs1() { - String contents = "(1).\ndef u" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "(1)."), GroovyCompletionProposalComputer) - proposalExists(proposals, "abs", 1) + String contents = '''\ + (1). + def u + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '(1).'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'abs', 1) } @Test // GRECLIPSE-1374 void testParensExprs2() { - String contents = "(((1))).\ndef u" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "(((1)))."), GroovyCompletionProposalComputer) - proposalExists(proposals, "abs", 1) + String contents = '''\ + (((1))). + def u + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '(((1))).'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'abs', 1) } @Test // GRECLIPSE-1374 void testParensExprs3() { - String contents = "(((1))).abs()" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "(((1))).a"), GroovyCompletionProposalComputer) - proposalExists(proposals, "abs", 1) + String contents = '(((1))).abs()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '(((1))).a'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'abs', 1) } @Test // GRECLIPSE-1528 void testGetterSetter1() { - String contents = "class A {\n private int value\n }" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "\n"), GroovyCompletionProposalComputer) - proposalExists(proposals, "getValue", 1) - proposalExists(proposals, "setValue", 1) + String contents = 'class A { private int value\n}' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '\n'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'getValue', 1) + proposalExists(proposals, 'setValue', 1) } @Test void testGetterSetter2() { - String contents = "class A {\n private final int value\n }" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "\n"), GroovyCompletionProposalComputer) - proposalExists(proposals, "getValue", 1) - proposalExists(proposals, "setValue", 0) + String contents = 'class A { private final int value\n}' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '\n'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'getValue', 1) + proposalExists(proposals, 'setValue', 0) } @Test void testGetterSetter3() { - String contents = "class A {\n private boolean value\n }" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "\n"), GroovyCompletionProposalComputer) - proposalExists(proposals, "isValue", 1) - proposalExists(proposals, "setValue", 1) + String contents = 'class A { private boolean value\n}' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '\n'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'isValue', 1) + proposalExists(proposals, 'setValue', 1) } @Test // GRECLIPSE-1752 void testStatic1() { - String contents = - "class A {\n" + - " public static void util() {}\n" + - " void foo() {\n" + - " A.\n" + - " }\n" + - "}" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "A."), GroovyCompletionProposalComputer) - proposalExists(proposals, "util", 1) + String contents = '''\ + class A { + static void util() {} + void foo() { + A. + } + } + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'A.'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'util', 1) } @Test void testStatic2() { - String contents = - "@groovy.transform.CompileStatic\n" + - "class A {\n" + - " public static void util() {}\n" + - " void foo() {\n" + - " A.\n" + - " }\n" + - "}" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "A."), GroovyCompletionProposalComputer) - proposalExists(proposals, "util", 1) + assumeTrue(isAtLeastGroovy(20)) + + String contents = '''\ + @groovy.transform.CompileStatic + class A { + static void util() {} + void foo() { + A. + } + } + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'A.'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'util', 1) } @Test void testClass1() { - String contents = - "class A {\n" + - " public static void util() {}\n" + - " void foo() {\n" + - " A.class.\n" + - " }\n" + - "}" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "A.class."), GroovyCompletionProposalComputer) - proposalExists(proposals, "util", 1) + String contents = '''\ + class A { + static void util() {} + void foo() { + A.class. + } + } + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'A.class.'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'util', 1) } @Test void testClass2() { - String contents = - "@groovy.transform.CompileStatic\n" + - "class A {\n" + - " public static void util() {}\n" + - " void foo() {\n" + - " A.class.\n" + - " }\n" + - "}" - ICompilationUnit unit = addGroovySource(contents, "File", "") - ICompletionProposal[] proposals = performContentAssist(unit, getLastIndexOf(contents, "A.class."), GroovyCompletionProposalComputer) - proposalExists(proposals, "util", 1) + assumeTrue(isAtLeastGroovy(20)) + + String contents = '''\ + @groovy.transform.CompileStatic + class A { + static void util() {} + void foo() { + A.class. + } + }'''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'A.class.'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'util', 1) } - // + @Test + void testImportStaticMethod() { + String contents = '''\ + import static java.util.regex.Pattern.compile + comp + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'comp'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'compile', 2) + } - private List delegateTestParameterNames(GroovyCompilationUnit unit) { - // for some reason, need to wait for indices to be built before this can work - SynchronizationUtils.waitForIndexingToComplete(unit) - ClassNode clazz = extract(unit) - List methods = clazz.getMethods("m") - for (MethodNode method : methods) { - if (method.getParameters().length == 1) { - MockGroovyMethodProposal proposal = new MockGroovyMethodProposal(method) - char[][] names = proposal.createAllParameterNames(unit) - checkNames(["x".toCharArray()] as char[][], names) - } - if (method.getParameters().length == 2) { - MockGroovyMethodProposal proposal = new MockGroovyMethodProposal(method) - char[][] names = proposal.createAllParameterNames(unit) - checkNames(["x".toCharArray(), "y".toCharArray()] as char[][], names) - } - } - return methods + @Test + void testImportStaticStarMethod() { + String contents = '''\ + import static java.util.regex.Pattern.* + comp + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'comp'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'compile', 2) } - private void checkNames(char[][] expected, char[][] names) { - if (!CharOperation.equals(expected, names)) { - fail("Wrong number of parameter names. Expecting:\n" + CharOperation.toString(expected) + "\n\nbut found:\n" + CharOperation.toString(names)) - } + @Test + void testFavoriteStaticMethod() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, 'java.util.regex.Pattern.compile') + + String contents = '''\ + comp + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'comp'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'compile', 2) + + applyProposalAndCheck(new Document(contents), findFirstProposal(proposals, 'compile', false), '''\ + |import static java.util.regex.Pattern.compile + | + |compile("") + |'''.stripMargin()) } - private ClassNode extract(GroovyCompilationUnit unit) { - Statement state = unit.getModuleNode().getStatementBlock().getStatements().get(0) - if (state instanceof ReturnStatement) { - ReturnStatement ret = (ReturnStatement) state - return ret.getExpression().getType() - } else if (state instanceof ExpressionStatement) { - ExpressionStatement expr = (ExpressionStatement) state - return expr.getExpression().getType() - } else { - fail("Invalid statement kind for " + state + "\nExpecting return statement or expression statement") - return null - } + @Test + void testFavoriteStaticStarMethod() { + setJavaPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, 'java.util.regex.Pattern.*') + + String contents = '''\ + comp + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'comp'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'compile', 2) + + applyProposalAndCheck(new Document(contents), findFirstProposal(proposals, 'compile', false), '''\ + |import static java.util.regex.Pattern.compile + | + |compile("") + |'''.stripMargin()) } } diff --git a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/OtherCompletionTests.groovy b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/OtherCompletionTests.groovy index 110455fc5e..87fdb099ee 100644 --- a/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/OtherCompletionTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.codeassist.completion.test/src/org/codehaus/groovy/eclipse/codeassist/tests/OtherCompletionTests.groovy @@ -18,7 +18,6 @@ package org.codehaus.groovy.eclipse.codeassist.tests import org.codehaus.groovy.eclipse.GroovyPlugin import org.codehaus.groovy.eclipse.codeassist.requestor.GroovyCompletionProposalComputer import org.codehaus.groovy.eclipse.core.preferences.PreferenceConstants -import org.eclipse.jdt.core.ICompilationUnit import org.eclipse.jface.text.contentassist.ICompletionProposal import org.junit.Before import org.junit.Test @@ -30,332 +29,270 @@ final class OtherCompletionTests extends CompletionTestSuite { @Before void setUp() { - GroovyPlugin.getDefault().getPreferenceStore().setValue(PreferenceConstants.GROOVY_CONTENT_ASSIST_NOPARENS, false) - GroovyPlugin.getDefault().getPreferenceStore().setValue(PreferenceConstants.GROOVY_CONTENT_PARAMETER_GUESSING, false) - } - - @Test - void testGreclipse414() { - String contents = - "public class Test {\n" + - "int i\n" + - "Test() {\n" + - "this.i = 42\n" + - "}\n" + - "Test(Test other) {\n" + - "this.i = other.i\n" + - "}\n" + - "}" - ICompilationUnit unit = addGroovySource(contents, "File", "") - // ensure that there is no ArrayIndexOutOfBoundsException thrown. - ICompletionProposal[] proposals = performContentAssist(unit, getIndexOf(contents, "this."), GroovyCompletionProposalComputer) - proposalExists(proposals, "i", 1) - } - - // type signatures were popping up in various places in the display string - // ensure this doesn't happen - @Test - void testGreclipse422() { - String javaClass = - "public class StringExtension {\n" + - "public static String bar(String self) {\n" + - "return self;\n" + - "}\n" + - "}\n" - addJavaSource(javaClass, "StringExtension", "") - - String groovyClass = - "public class MyClass {\n" + - "public void foo() {\n" + - "String foo = 'foo';\n" + - "use (StringExtension) {\n" + - "foo.bar()\n" + - "}\n" + - "this.collect\n" + - "}\n" + - "}" - - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "foo.ba"), GroovyCompletionProposalComputer) - proposalExists(proposals, "bar", 1) - assert proposals[0].getDisplayString() == "bar() : String - StringExtension (Category: StringExtension)" - - proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "this.collect"), GroovyCompletionProposalComputer) + GroovyPlugin.default.preferenceStore.setValue(PreferenceConstants.GROOVY_CONTENT_ASSIST_NOPARENS, false) + GroovyPlugin.default.preferenceStore.setValue(PreferenceConstants.GROOVY_CONTENT_PARAMETER_GUESSING, false) + } + + @Test // GRECLIPSE-414 + void testNoIndexOutOfBoundsException() { + String contents = '''\ + public class Test { + int i + Test() { + this.i = 42 + } + Test(Test other) { + this.i = other.i + } + } + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'this.'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'i', 1) + } + + @Test // GRECLIPSE-422: type signatures were popping up in various places in the display string + void testCategoryMethodDisplayString() { + addJavaSource '''\ + public class StringExtension { + public static String bar(String self) { + return self; + } + } + '''.stripIndent(), 'StringExtension' + + String contents = '''\ + public class MyClass { + public void foo() { + String foo = 'foo' + use (StringExtension) { + foo.bar() + } + this.collect + } + } + '''.stripIndent() + def gunit = addGroovySource(contents) + ICompletionProposal[] proposals = performContentAssist(gunit, getIndexOf(contents, 'foo.ba'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'bar', 1) + assert proposals[0].displayString == 'bar() : String - StringExtension (Category: StringExtension)' + + proposals = performContentAssist(gunit, getIndexOf(contents, 'this.collect'), GroovyCompletionProposalComputer) Arrays.sort(proposals, { ICompletionProposal o1, ICompletionProposal o2 -> - o2.getDisplayString() <=> o1.getDisplayString() + o2.displayString <=> o1.displayString } as Comparator) - proposalExists(proposals, "collect", 3) - assert proposals[0].getDisplayString().matches( - "collect\\(Collection \\w+, Closure \\w+\\) : Collection - DefaultGroovyMethods \\(Category: DefaultGroovyMethods\\)") : printProposals(proposals) - assert proposals[1].getDisplayString().matches( - "collect\\(Closure \\w+\\) : List - DefaultGroovyMethods \\(Category: DefaultGroovyMethods\\)") : printProposals(proposals) - assert proposals[2].getDisplayString().matches( - "collect\\(\\) : Collection - DefaultGroovyMethods \\(Category: DefaultGroovyMethods\\)") : printProposals(proposals) + proposalExists(proposals, 'collect', 3) + assert proposals[0].displayString ==~ /collect\(Collection \w+, Closure \w+\) : Collection - DefaultGroovyMethods \(Category: DefaultGroovyMethods\)/ : printProposals(proposals) + assert proposals[1].displayString ==~ /collect\(Closure \w+\) : List - DefaultGroovyMethods \(Category: DefaultGroovyMethods\)/ : printProposals(proposals) + assert proposals[2].displayString ==~ /collect\(\) : Collection - DefaultGroovyMethods \(Category: DefaultGroovyMethods\)/ : printProposals(proposals) } @Test void testVisibility() { - String groovyClass = - "class B { }\n" + - "class C {\n" + - "B theB\n" + - "}\n" + - "new C().th\n" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "().th"), GroovyCompletionProposalComputer) - - proposalExists(proposals, "theB", 1) - assert proposals[0].getDisplayString() == "theB : B - C (Groovy)" + String contents = '''\ + class B { } + class C { + B theB + } + new C().th + '''.stripIndent() + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '().th'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'theB', 1) + assert proposals[0].displayString == 'theB : B - C' } @Test void testGString1() { - String groovyClass = '\"${new String().c}\"' - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, ".c"), GroovyCompletionProposalComputer) - proposalExists(proposals, "center", 2) + String contents = '"${new String().c}"' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '.c'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'center', 2) } @Test void testGString2() { - String groovyClass = '\"\"\"${new String().c}\"\"\"' - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, ".c"), GroovyCompletionProposalComputer) - proposalExists(proposals, "center", 2) + String contents = '"""${new String().c}"""' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '.c'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'center', 2) } - // GRECLIPSE-706 - @Test + @Test // GRECLIPSE-706 void testContentAssistInInitializers1() { - String groovyClass = - "class A { { aa }\n def aaaa }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "aa"), GroovyCompletionProposalComputer) - proposalExists(proposals, "aaaa", 1) + String contents = 'class A { { aa }\n def aaaa }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'aa'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'aaaa', 1) } - // GRECLIPSE-706 - @Test + @Test // GRECLIPSE-706 void testContentAssistInInitializers2() { - String groovyClass = - "class A { { }\n def aaaa }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "{ { "), GroovyCompletionProposalComputer) - proposalExists(proposals, "aaaa", 1) + String contents = 'class A { { }\n def aaaa }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '{ { '), GroovyCompletionProposalComputer) + proposalExists(proposals, 'aaaa', 1) } - // GRECLIPSE-706 - @Test + @Test // GRECLIPSE-706 void testContentAssistInStaticInitializers1() { - String groovyClass = - "class A { static { aa }\n static aaaa }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "aa"), GroovyCompletionProposalComputer) - proposalExists(proposals, "aaaa", 1) + String contents = 'class A { static { aa }\n static aaaa }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'aa'), GroovyCompletionProposalComputer) + proposalExists(proposals, 'aaaa', 1) } - // GRECLIPSE-706 - @Test + @Test // GRECLIPSE-706 void testContentAssistInStaticInitializers2() { - String groovyClass = - "class A { static { }\n static aaaa }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "static { "), GroovyCompletionProposalComputer) - proposalExists(proposals, "aaaa", 1) + String contents = 'class A { static { }\n static aaaa }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'static { '), GroovyCompletionProposalComputer) + proposalExists(proposals, 'aaaa', 1) } - // GRECLIPSE-692 - @Test + @Test // GRECLIPSE-692 void testMethodWithSpaces() { - String groovyClass = - "class A { def \"ff f\"() { ff } }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "{ ff"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "\"ff f\"()", 1) + String contents = 'class A { def "ff f"() { ff } }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '{ ff'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, '"ff f"()', 1) } - // GRECLIPSE-692 - @Test + @Test // GRECLIPSE-692 void testMethodWithSpaces2() { - String groovyClass = - "class A { def \"fff\"() { fff } }" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "{ fff"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "fff()", 1) + String contents = 'class A { def "fff"() { fff } }' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '{ fff'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'fff()', 1) } - // STS-1165 content assist after a static method call was broken - @Test + @Test // STS-1165 content assist after a static method call was broken void testAfterStaticCall() { - String groovyClass = - "class A { static xxx(x) { }\n def something() {\nxxx oth }\ndef other}" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(groovyClass, "oth"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "other", 1) + String contents = 'class A { static xxx(x) { }\n def something() {\nxxx oth }\ndef other}' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, 'oth'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'other', 1) } @Test void testArrayCompletion1() { - String groovyClass = "class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].x" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "x"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "xx", 1) + String contents = 'class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].x' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'x'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'xx', 1) } @Test void testArrayCompletion2() { - String groovyClass = "class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].getX" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "getX"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "getXx()", 1) + String contents = 'class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].getX' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'getX'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'getXx()', 1) } @Test void testArrayCompletion3() { - String groovyClass = "class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].setX" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "setX"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "setXx(value)", 1) + String contents = 'class XX { \nXX[] xx\nXX yy }\nnew XX().xx[0].setX' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'setX'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'setXx(value)', 1) } @Test void testArrayCompletion4() { - String groovyClass = "class XX { \nXX[] xx\nXX yy }\nnew XX().getXx()[0].x" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "x"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "xx", 1) + String contents = 'class XX { \nXX[] xx\nXX yy }\nnew XX().getXx()[0].x' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, 'x'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'xx', 1) } @Test void testListCompletion1() { - String groovyClass = "[]." - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, ["removeAll(arg0)","removeAll(c)"] as String[], 1) + String contents = '[].' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, ['removeAll(arg0)', 'removeAll(c)'] as String[], 1) } @Test void testListCompletion2() { - String groovyClass = "[].re" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".re"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, ["removeAll(arg0)","removeAll(c)"] as String[], 1) + String contents = '[].re' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.re'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, ['removeAll(arg0)', 'removeAll(c)'] as String[], 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion1() { - String groovyClass = "[1,2,3]*.intValue()[0].value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.intValue()[0].value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion2() { - String groovyClass = "[1,2,3]*.intValue()[0].value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".va"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.intValue()[0].value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.va'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion3() { - String groovyClass = "[x:1,y:2,z:3]*.getKey()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "getKey()", 1) + String contents = '[x:1,y:2,z:3]*.getKey()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'getKey()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion4() { - String groovyClass = "[x:1,y:2,z:3]*.getKey()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".get"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "getKey()", 1) + String contents = '[x:1,y:2,z:3]*.getKey()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.get'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'getKey()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion5() { - String groovyClass = "[x:1,y:2,z:3]*.key[0].toLowerCase()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "toLowerCase()", 1) + String contents = '[x:1,y:2,z:3]*.key[0].toLowerCase()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'toLowerCase()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion6() { - String groovyClass = "[x:1,y:2,z:3]*.key[0].toLowerCase()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".to"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "toLowerCase()", 1) + String contents = '[x:1,y:2,z:3]*.key[0].toLowerCase()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.to'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'toLowerCase()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion7() { - String groovyClass = "[x:1,y:2,z:3]*.value[0].intValue()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "intValue()", 1) + String contents = '[x:1,y:2,z:3]*.value[0].intValue()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'intValue()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion8() { - String groovyClass = "[x:1,y:2,z:3]*.value[0].intValue()" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".int"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "intValue()", 1) + String contents = '[x:1,y:2,z:3]*.value[0].intValue()' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.int'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'intValue()', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion9() { - String groovyClass = "[1,2,3]*.value[0].value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.value[0].value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion10() { - String groovyClass = "[1,2,3]*.value[0].value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".val"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.value[0].value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.val'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion11() { - String groovyClass = "[1,2,3]*.value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, "."), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1165 - @Test + @Test // GRECLIPSE-1165 void testSpreadCompletion12() { - String groovyClass = "[1,2,3]*.value" - ICompilationUnit groovyUnit = addGroovySource(groovyClass, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getLastIndexOf(groovyClass, ".val"), GroovyCompletionProposalComputer) - checkReplacementString(proposals, "value", 1) + String contents = '[1,2,3]*.value' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getLastIndexOf(contents, '.val'), GroovyCompletionProposalComputer) + checkReplacementString(proposals, 'value', 1) } - // GRECLIPSE-1388 - @Test + @Test // GRECLIPSE-1388 void testBeforeScript() { - String script = "\n\ndef x = 9" - ICompilationUnit groovyUnit = addGroovySource(script, "File", "") - ICompletionProposal[] proposals = performContentAssist(groovyUnit, getIndexOf(script, "\n"), GroovyCompletionProposalComputer) - assertProposalOrdering(proposals, "binding") + String contents = '\n\ndef x = 9' + ICompletionProposal[] proposals = performContentAssist(addGroovySource(contents), getIndexOf(contents, '\n'), GroovyCompletionProposalComputer) + assertProposalOrdering(proposals, 'binding') } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyJavaFieldCompletionProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaFieldCompletionProposal.java similarity index 66% rename from ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyJavaFieldCompletionProposal.java rename to ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaFieldCompletionProposal.java index d637900137..d4bb76a9e2 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyJavaFieldCompletionProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaFieldCompletionProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -13,28 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.codehaus.groovy.eclipse.codeassist.proposals; +package org.codehaus.groovy.eclipse.codeassist.completions; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.internal.ui.text.java.FieldProposalInfo; import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal; +import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.viewers.StyledString; -import org.eclipse.swt.graphics.Image; -/** - * - * @author Andrew Eisenberg - * @created Dec 8, 2009 - */ public class GroovyJavaFieldCompletionProposal extends JavaCompletionProposal { private final CompletionProposal proposal; - public GroovyJavaFieldCompletionProposal(CompletionProposal proposal, Image image, StyledString displayString) { - super(String.valueOf(proposal.getName()), proposal.getReplaceStart(), - proposal.getReplaceEnd()-proposal.getReplaceStart(), - image, displayString, proposal.getRelevance()); - this.proposal = proposal; - this.setRelevance(proposal.getRelevance()); + + public GroovyJavaFieldCompletionProposal(CompletionProposal proposal, StyledString displayString, JavaContentAssistInvocationContext javaContext) { + super(String.valueOf(proposal.getName()), proposal.getReplaceStart(), proposal.getReplaceEnd() - proposal.getReplaceStart(), + ProposalUtils.getImage(proposal), displayString, proposal.getRelevance(), false, javaContext); + this.setProposalInfo(new FieldProposalInfo(javaContext.getProject(), (this.proposal = proposal))); this.setTriggerCharacters(ProposalUtils.VAR_TRIGGER); } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaMethodCompletionProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaMethodCompletionProposal.java index fd2a003957..5d65f5df45 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaMethodCompletionProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyJavaMethodCompletionProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -24,12 +24,13 @@ import org.eclipse.jdt.internal.ui.javaeditor.EditorHighlightingSynchronizer; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal; +import org.eclipse.jdt.internal.ui.text.java.MethodProposalInfo; import org.eclipse.jdt.internal.ui.text.java.ProposalContextInformation; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.link.LinkedModeModel; @@ -38,15 +39,9 @@ import org.eclipse.jface.text.link.LinkedPositionGroup; import org.eclipse.jface.viewers.StyledString; import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; -/** - * @author Andrew Eisenberg - * @created Aug 11, 2009 - * - */ public class GroovyJavaMethodCompletionProposal extends JavaMethodCompletionProposal { private static final String CLOSURE_TEXT = "{ }"; @@ -60,33 +55,30 @@ public class GroovyJavaMethodCompletionProposal extends JavaMethodCompletionProp // if true, shows the context only and does not private boolean contextOnly; - public GroovyJavaMethodCompletionProposal(GroovyCompletionProposal proposal, - JavaContentAssistInvocationContext context, ProposalFormattingOptions groovyFormatterPrefs) { + public GroovyJavaMethodCompletionProposal(GroovyCompletionProposal proposal, JavaContentAssistInvocationContext context, ProposalFormattingOptions options) { super(proposal, context); - this.proposalOptions = groovyFormatterPrefs; - this.contributor = "Groovy"; + this.proposalOptions = options; + this.setProposalInfo(new MethodProposalInfo(context.getProject(), proposal)); this.setRelevance(proposal.getRelevance()); - if (proposal.hasParameters()) { - this.setTriggerCharacters(ProposalUtils.METHOD_WITH_ARGUMENTS_TRIGGERS); - } else { - this.setTriggerCharacters(ProposalUtils.METHOD_TRIGGERS); - } + this.setTriggerCharacters(!proposal.hasParameters() ? ProposalUtils.METHOD_TRIGGERS : ProposalUtils.METHOD_WITH_ARGUMENTS_TRIGGERS); } - public GroovyJavaMethodCompletionProposal(GroovyCompletionProposal proposal, - JavaContentAssistInvocationContext context, ProposalFormattingOptions groovyFormatterPrefs, String contributor) { - this(proposal, context, groovyFormatterPrefs); + public GroovyJavaMethodCompletionProposal(GroovyCompletionProposal proposal, JavaContentAssistInvocationContext context, ProposalFormattingOptions options, String contributor) { + this(proposal, context, options); this.contributor = contributor; } - public void contextOnly() { contextOnly = true; } @Override protected StyledString computeDisplayString() { - return super.computeDisplayString().append(getStyledGroovy()); + StyledString displayString = super.computeDisplayString(); + if (contributor != null && contributor.trim().length() > 0) { + displayString.append(new StyledString(" (" + contributor + ")", StyledString.DECORATIONS_STYLER)); + } + return displayString; } @Override @@ -101,53 +93,48 @@ protected IContextInformation computeContextInformation() { return super.computeContextInformation(); } - - private StyledString getStyledGroovy() { - return new StyledString(" (" + contributor + ")", StyledString.DECORATIONS_STYLER); - } - /* * @see ICompletionProposalExtension#apply(IDocument, char) */ @Override public void apply(IDocument document, char trigger, int offset) { super.apply(document, trigger, offset); - int baseOffset= getReplacementOffset(); - String replacement= getReplacementString(); + int baseOffset = getReplacementOffset(); + String replacement = getReplacementString(); fSelectedRegion = new Region(baseOffset + replacement.length(), 0); } @Override protected void setUpLinkedMode(IDocument document, char closingCharacter) { - if (fArgumentOffsets != null && getTextViewer() != null) { + ITextViewer textViewer = getTextViewer(); + if (textViewer != null && fArgumentOffsets != null) { int baseOffset = getReplacementOffset(); String replacement = getReplacementString(); try { - LinkedModeModel model= new LinkedModeModel(); - for (int i= 0; i != fArgumentOffsets.length; i++) { - LinkedPositionGroup group= new LinkedPositionGroup(); + LinkedModeModel model = new LinkedModeModel(); + for (int i = 0, n = fArgumentOffsets.length; i < n; i += 1) { + LinkedPositionGroup group = new LinkedPositionGroup(); group.addPosition(new LinkedPosition(document, baseOffset + fArgumentOffsets[i], fArgumentLengths[i], LinkedPositionGroup.NO_STOP)); model.addGroup(group); } - model.forceInstall(); - JavaEditor editor= getJavaEditor(); + + JavaEditor editor = getJavaEditor(); if (editor != null) { model.addLinkingListener(new EditorHighlightingSynchronizer(editor)); } - LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer()); - ui.setExitPosition(getTextViewer(), baseOffset + replacement.length(), 0, Integer.MAX_VALUE); - ui.setExitPolicy(new ExitPolicy(')', document)); + LinkedModeUI ui = new EditorLinkedModeUI(model, textViewer); + ui.setExitPosition(textViewer, baseOffset + replacement.length(), 0, Integer.MAX_VALUE); + ui.setExitPolicy(new ExitPolicy(closingCharacter, document)); ui.setDoContextInfo(true); ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT); ui.enter(); - fSelectedRegion= ui.getSelectedRegion(); + fSelectedRegion = ui.getSelectedRegion(); } catch (BadLocationException e) { JavaPlugin.log(e); - openErrorDialog(e); } } } @@ -340,10 +327,4 @@ public Point getSelection(IDocument document) { return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength()); } - - private void openErrorDialog(BadLocationException e) { - Shell shell= getTextViewer().getTextWidget().getShell(); - MessageDialog.openError(shell, "Error inserting parameters", e.getMessage()); - } - -} \ No newline at end of file +} diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/AbstractProposalCreator.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/AbstractProposalCreator.java index 61ec356744..23e438bb72 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/AbstractProposalCreator.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/AbstractProposalCreator.java @@ -15,12 +15,20 @@ */ package org.codehaus.groovy.eclipse.codeassist.creators; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; import java.util.Set; +import groovyjarjarasm.asm.Opcodes; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.FieldNode; import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.ModuleNode; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.eclipse.jdt.groovy.search.AccessorSupport; import org.eclipse.jdt.groovy.search.VariableScope; @@ -29,27 +37,89 @@ public abstract class AbstractProposalCreator implements IProposalCreator { /** * The type of the LHS of the assignment statement associated with this - * invocation or null if there is none + * invocation or null if there is none. */ protected ClassNode lhsType; + public void setLhsType(ClassNode lhsType) { + this.lhsType = lhsType; + } + protected VariableScope currentScope; + public void setCurrentScope(VariableScope currentScope) { + this.currentScope = currentScope; + } + + protected Set favoriteStaticMembers; + + public void setFavoriteStaticMembers(Set favoriteStaticMembers) { + this.favoriteStaticMembers = favoriteStaticMembers; + } + protected boolean checkName(String name) { return name.charAt(0) != '<' && !name.contains("$"); } - protected void getAllSupers(ClassNode type, Set set, Set except) { + /** + * Returns all fields, even those that are converted into properties. + */ + protected Collection getAllFields(ClassNode thisType, Set exclude) { + Map allFields = new HashMap(); + + // use a LinkedHashSet to preserve order + Set types = new LinkedHashSet(); + getAllSupers(thisType, types, exclude); + + for (ClassNode type : types) { + for (FieldNode field : type.getFields()) { + if (checkName(field.getName())) { + // only add new field if the new field is more accessible than the existing one + FieldNode existing = allFields.get(field.getName()); + if (existing == null || leftIsMoreAccessible(field, existing)) { + allFields.put(field.getName(), field); + } + } + } + } + + // don't do anything with these types next time + exclude.addAll(types); + + return allFields.values(); + } + + protected List getAllMethods(ClassNode type, Set exclude) { + List allMethods = type.getAllDeclaredMethods(); + if (!exclude.isEmpty()) { + // remove all methods from classes that we have already visited + for (Iterator methodIter = allMethods.iterator(); methodIter.hasNext();) { + if (exclude.contains(methodIter.next().getDeclaringClass())) { + methodIter.remove(); + } + } + } + + Set types = new LinkedHashSet(); + getAllSupers(type, types, exclude); + + // keep track of the already seen types so that next time, we won't include them + exclude.addAll(types); + + return allMethods; + } + + protected void getAllSupers(ClassNode type, Set set, Set exclude) { if (type == null) { return; } - if (!except.contains(type)) { + if (!exclude.contains(type)) { set.add(type); } - getAllSupers(type.getSuperClass(), set, except); + getAllSupers(type.getSuperClass(), set, exclude); for (ClassNode inter : (Iterable) type.getAllInterfaces()) { if (!inter.getName().equals(type.getName())) { - getAllSupers(inter, set, except); + getAllSupers(inter, set, exclude); } } } @@ -58,6 +128,44 @@ protected boolean isInterestingType(ClassNode type) { return lhsType != null && ClassHelper.getUnwrapper(type).equals(lhsType); } + /** + * find the most accessible element + */ + private static boolean leftIsMoreAccessible(FieldNode field, FieldNode existing) { + int leftAcc; + switch (field.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) { + case Opcodes.ACC_PUBLIC: + leftAcc = 0; + break; + case Opcodes.ACC_PROTECTED: + leftAcc = 1; + break; + case Opcodes.ACC_PRIVATE: + leftAcc = 3; + break; + default: // package default + leftAcc = 2; + break; + } + + int rightAcc; + switch (existing.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) { + case Opcodes.ACC_PUBLIC: + rightAcc = 0; + break; + case Opcodes.ACC_PROTECTED: + rightAcc = 1; + break; + case Opcodes.ACC_PRIVATE: + rightAcc = 3; + break; + default: // package default + rightAcc = 2; + break; + } + return leftAcc < rightAcc; + } + protected void getAllSupersAsStrings(ClassNode type, Set set) { if (type == null) { return; @@ -71,30 +179,20 @@ protected void getAllSupersAsStrings(ClassNode type, Set set) { } } - public void setLhsType(ClassNode lhsType) { - this.lhsType = lhsType; - } - - public void setCurrentScope(VariableScope currentScope) { - this.currentScope = currentScope; - } - /** - * Check to ensure that there is no field with a getter or setter name before creating the mock - * field + * Check to ensure that there is no field with a getter or setter name before creating the mock field. + * * @param declaringClass declaring type of the method * @param methodName method to check for */ protected boolean hasNoField(ClassNode declaringClass, String methodName) { - return declaringClass.getField(ProposalUtils.createMockFieldName(methodName)) == null - && declaringClass - .getField(ProposalUtils.createCapitalMockFieldName(methodName)) == null; + return declaringClass.getField(ProposalUtils.createMockFieldName(methodName)) == null && + declaringClass.getField(ProposalUtils.createCapitalMockFieldName(methodName)) == null; } protected FieldNode createMockField(MethodNode method) { - FieldNode field = new FieldNode(ProposalUtils.createMockFieldName(method.getName()), - method.getModifiers(), method.getReturnType(), - method.getDeclaringClass(), null); + FieldNode field = new FieldNode(ProposalUtils.createMockFieldName( + method.getName()), method.getModifiers(), method.getReturnType(), method.getDeclaringClass(), null); field.setDeclaringClass(method.getDeclaringClass()); field.setSourcePosition(method); return field; @@ -116,4 +214,19 @@ protected AccessorSupport findLooselyMatchedAccessorKind(String prefix, String m public boolean redoForLoopClosure() { return true; } + + protected static ClassNode tryResolveClassNode(String typeName, ModuleNode module) { + for (ClassNode t : module.getClasses()) { + if (t.getName().equals(typeName)) { + return t; + } + } + try { + //ClassNode type = ((EclipseSourceUnit) module.getContext()).resolver.resolve(typeName); + Class t = module.getContext().getClassLoader().loadClass(typeName, true, true, true); + return ClassHelper.make(t); + } catch (ClassNotFoundException e) { + return null; + } + } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java index 64b898e2b5..686fd9ed39 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java @@ -41,8 +41,7 @@ public List findAllProposals(ClassNode type, Set cat Set set = new HashSet(); getAllSupersAsStrings(candidate, set); set.add("java.lang.Object"); - List groovyProposals = findAllProposals(set, categories, prefix, candidate); - return groovyProposals; + return findAllProposals(set, categories, prefix, candidate); } private List findAllProposals(Set set, Set categories, String prefix, ClassNode declaringClass) { @@ -64,8 +63,8 @@ private List findAllProposals(Set set, Set c if (method.isStatic() && method.isPublic()) { Parameter[] params = method.getParameters(); if (ProposalUtils.looselyMatches(prefix, methodName)) { - if (params != null && params.length > 0 && set.contains(params[0].getType().getName()) - && !dupMethod(method, existingMethodProposals)) { + if (params != null && params.length > 0 && + set.contains(params[0].getType().getName()) && !dupMethod(method, existingMethodProposals)) { GroovyCategoryMethodProposal methodProposal = new GroovyCategoryMethodProposal(method); methodProposal.setRelevanceMultiplier(isInterestingType(method.getReturnType()) ? 101 : 1); groovyProposals.add(methodProposal); @@ -76,16 +75,15 @@ private List findAllProposals(Set set, Set c } methodList.add(method); } - } else if (params.length == 1 - && findLooselyMatchedAccessorKind(prefix, methodName, true).isAccessorKind(method, true) - && !existingFieldProposals.contains(methodName) && hasNoField(declaringClass, methodName)) { + } else if (params.length == 1 && + findLooselyMatchedAccessorKind(prefix, methodName, true).isAccessorKind(method, true) && + !existingFieldProposals.contains(methodName) && hasNoField(declaringClass, methodName)) { // add property variant of accessor name GroovyFieldProposal fieldProposal = new GroovyFieldProposal(createMockField(method)); fieldProposal.setRelevanceMultiplier(1); groovyProposals.add(fieldProposal); existingFieldProposals.add(methodName); } - } } } 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 545438565c..861406c1ce 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 @@ -17,12 +17,9 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import groovyjarjarasm.asm.Opcodes; @@ -36,6 +33,8 @@ import org.codehaus.groovy.ast.expr.ClosureExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.stmt.BlockStatement; +import org.codehaus.groovy.eclipse.GroovyLogManager; +import org.codehaus.groovy.eclipse.TraceCategory; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyFieldProposal; import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyMethodProposal; @@ -50,7 +49,7 @@ public class FieldProposalCreator extends AbstractProposalCreator implements IPr private static final GroovyFieldProposal CLASS_PROPOSAL = createClassProposal(); - private Set alreadySeen = Collections.emptySet(); + private Set alreadySeen = new HashSet(); private static GroovyFieldProposal createClassProposal() { FieldNode field = new FieldNode("class", Opcodes.ACC_PUBLIC & Opcodes.ACC_STATIC & Opcodes.ACC_FINAL, VariableScope.CLASS_CLASS_NODE, VariableScope.OBJECT_CLASS_NODE, null); @@ -59,9 +58,11 @@ private static GroovyFieldProposal createClassProposal() { } public List findAllProposals(ClassNode type, Set categories, String prefix, boolean isStatic, boolean isPrimary) { + List proposals = new ArrayList(); + boolean isFirstTime = alreadySeen.isEmpty(); - Collection allFields = getAllFields(type); - List groovyProposals = new ArrayList(); + Collection allFields = getAllFields(type, alreadySeen); + for (FieldNode field : allFields) { // in static context, only allow static fields if ((!isStatic || field.isStatic()) && ProposalUtils.looselyMatches(prefix, field.getName())) { @@ -70,29 +71,30 @@ public List findAllProposals(ClassNode type, Set cat // de-emphasize 'this' references inside closure if (!isFirstTime) relevanceMultiplier *= 0.1f; - GroovyFieldProposal fieldProposal = new GroovyFieldProposal(field); - fieldProposal.setRelevanceMultiplier(relevanceMultiplier); - groovyProposals.add(fieldProposal); + GroovyFieldProposal proposal = new GroovyFieldProposal(field); + proposal.setRelevanceMultiplier(relevanceMultiplier); + proposals.add(proposal); if (field.getInitialExpression() instanceof ClosureExpression) { // also add a method-like proposal - groovyProposals.add(new GroovyMethodProposal(convertToMethodProposal(field))); + proposals.add(new GroovyMethodProposal(convertToMethodProposal(field))); } } } if (isStatic && "class".startsWith(prefix)) { - groovyProposals.add(CLASS_PROPOSAL); + proposals.add(CLASS_PROPOSAL); } - // add all proposals coming from static imports if (currentScope != null) { ClassNode enclosingTypeDeclaration = currentScope.getEnclosingTypeDeclaration(); if (enclosingTypeDeclaration != null && isFirstTime && isPrimary && type.getModule() != null) { - groovyProposals.addAll(getStaticImportProposals(prefix, type.getModule())); + findStaticImportProposals(proposals, prefix, type.getModule()); + findStaticFavoriteProposals(proposals, prefix, type.getModule()); } } - return groovyProposals; + + return proposals; } @Override @@ -102,7 +104,7 @@ protected boolean isInterestingType(ClassNode type) { private MethodNode convertToMethodProposal(FieldNode field) { MethodNode method = new MethodNode(field.getName(), field.getModifiers(), field.getType(), - extractParameters(field.getInitialExpression()), ClassNode.EMPTY_ARRAY, new BlockStatement()); + extractParameters(field.getInitialExpression()), ClassNode.EMPTY_ARRAY, new BlockStatement()); method.setDeclaringClass(field.getDeclaringClass()); return method; } @@ -114,96 +116,62 @@ private Parameter[] extractParameters(Expression expr) { return Parameter.EMPTY_ARRAY; } - private List getStaticImportProposals(String prefix, ModuleNode module) { - List staticProposals = new ArrayList(); - Map staticImports = ImportNodeCompatibilityWrapper.getStaticImports(module); - for (Entry entry : staticImports.entrySet()) { + private void findStaticImportProposals(List proposals, String prefix, ModuleNode module) { + for (Map.Entry entry : ImportNodeCompatibilityWrapper.getStaticImports(module).entrySet()) { String fieldName = entry.getValue().getFieldName(); if (fieldName != null && ProposalUtils.looselyMatches(prefix, fieldName)) { FieldNode field = entry.getValue().getType().getField(fieldName); - if (field != null) { - staticProposals.add(new GroovyFieldProposal(field)); + if (field != null && field.isStatic()) { + proposals.add(new GroovyFieldProposal(field)); } } } - Map staticStarImports = ImportNodeCompatibilityWrapper.getStaticStarImports(module); - for (Entry entry : staticStarImports.entrySet()) { + for (Map.Entry entry : ImportNodeCompatibilityWrapper.getStaticStarImports(module).entrySet()) { ClassNode type = entry.getValue().getType(); if (type != null) { for (FieldNode field : (Iterable) type.getFields()) { if (field.isStatic() && ProposalUtils.looselyMatches(prefix, field.getName())) { - staticProposals.add(new GroovyFieldProposal(field)); + proposals.add(new GroovyFieldProposal(field)); } } } } - - return staticProposals; } - /** - * returns all fields, even those that are converted into properties - */ - private Collection getAllFields(ClassNode thisType) { - // use a LinkedHashSet to preserve order - Set types = new LinkedHashSet(); - getAllSupers(thisType, types, alreadySeen); - Map nameFieldMap = new HashMap(); - for (ClassNode type : types) { - for (FieldNode field : type.getFields()) { - if (checkName(field.getName())) { - // only add new field if the new field is more accessible than the existing one - FieldNode existing = nameFieldMap.get(field.getName()); - if (existing == null || leftIsMoreAccessible(field, existing)) { - nameFieldMap.put(field.getName(), field); + private void findStaticFavoriteProposals(List proposals, String prefix, ModuleNode module) { + for (String favoriteStaticMember : favoriteStaticMembers) { + int pos = favoriteStaticMember.lastIndexOf('.'); + String typeName = favoriteStaticMember.substring(0, pos); + String fieldName = favoriteStaticMember.substring(pos + 1); + ClassNode typeNode = tryResolveClassNode(typeName, module); + + if (typeNode == null) { + if (GroovyLogManager.manager.hasLoggers()) { + GroovyLogManager.manager.log(TraceCategory.CONTENT_ASSIST, "FieldProposalCreator: Cannot resolve favorite type " + typeName); + } + continue; + } + + if ("*".equals(fieldName)) { + for (FieldNode field : (Iterable) typeNode.getFields()) { + if (field.isStatic() && ProposalUtils.looselyMatches(prefix, field.getName())) { + proposals.add(newFavoriteFieldProposal(field, typeName + '.' + field.getName())); + } + } + } else { + if (ProposalUtils.looselyMatches(prefix, fieldName)) { + FieldNode field = typeNode.getField(fieldName); + if (field != null && field.isStatic()) { + proposals.add(newFavoriteFieldProposal(field, favoriteStaticMember)); } } } } - // don't do anything with these types next time - if (alreadySeen.isEmpty()) { - alreadySeen = types; - } else { - alreadySeen.addAll(types); - } - return nameFieldMap.values(); } - /** - * find the most accessible element - */ - private boolean leftIsMoreAccessible(FieldNode field, FieldNode existing) { - int leftAcc; - switch (field.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) { - case Opcodes.ACC_PUBLIC: - leftAcc = 0; - break; - case Opcodes.ACC_PROTECTED: - leftAcc = 1; - break; - case Opcodes.ACC_PRIVATE: - leftAcc = 3; - break; - default: // package default - leftAcc = 2; - break; - } - - int rightAcc; - switch (existing.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) { - case Opcodes.ACC_PUBLIC: - rightAcc = 0; - break; - case Opcodes.ACC_PROTECTED: - rightAcc = 1; - break; - case Opcodes.ACC_PRIVATE: - rightAcc = 3; - break; - default: // package default - rightAcc = 2; - break; - } - return leftAcc < rightAcc; + private IGroovyProposal newFavoriteFieldProposal(FieldNode field, String favorite) { + GroovyFieldProposal proposal = new GroovyFieldProposal(field); + proposal.setRequiredStaticImport(favorite); + return 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 f697ba4a19..cfd81525b0 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 @@ -16,14 +16,9 @@ package org.codehaus.groovy.eclipse.codeassist.creators; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import org.codehaus.groovy.ast.ClassNode; @@ -31,6 +26,8 @@ import org.codehaus.groovy.ast.ImportNodeCompatibilityWrapper; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.ModuleNode; +import org.codehaus.groovy.eclipse.GroovyLogManager; +import org.codehaus.groovy.eclipse.TraceCategory; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyFieldProposal; import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyMethodProposal; @@ -41,18 +38,19 @@ /** * Generates all of the method proposals for a given location. - * Also will add the non-getter form of getter methods if appropriate. + * Also will add the property form of accessor methods if appropriate. */ public class MethodProposalCreator extends AbstractProposalCreator implements IProposalCreator { - ProposalFormattingOptions options = ProposalFormattingOptions.newFromOptions(); + private ProposalFormattingOptions options = ProposalFormattingOptions.newFromOptions(); - private Set alreadySeen = Collections.emptySet(); + private Set alreadySeen = new HashSet(); public List findAllProposals(ClassNode type, Set categories, String prefix, boolean isStatic, boolean isPrimary) { + List proposals = new ArrayList(); + boolean firstTime = alreadySeen.isEmpty(); - List allMethods = getAllMethods(type); - List groovyProposals = new LinkedList(); + List allMethods = getAllMethods(type, alreadySeen); Set alreadySeenFields = new HashSet(); if (isStatic) { // "class" is added by FieldProposalCreator @@ -69,95 +67,111 @@ public List findAllProposals(ClassNode type, Set cat isInterestingType = isInterestingType(method.getReturnType()); } if (ProposalUtils.looselyMatches(prefix, methodName)) { - GroovyMethodProposal methodProposal = new GroovyMethodProposal(method, "Groovy", options); + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setProposalFormattingOptions(options); float relevanceMultiplier = isInterestingType ? 101f : 1f; relevanceMultiplier *= method.isStatic() ? 0.1f : 1f; // de-emphasize 'this' references inside closure relevanceMultiplier *= !alreadySeen.isEmpty() ? 0.1f : 1f; - methodProposal.setRelevanceMultiplier(relevanceMultiplier); - groovyProposals.add(methodProposal); + proposal.setRelevanceMultiplier(relevanceMultiplier); + proposals.add(proposal); } AccessorSupport accessor = findLooselyMatchedAccessorKind(prefix, methodName, false); if (accessor.isAccessorKind(method, false)) { - // if there is a getter or setter, then add a field proposal - // with the name being gotten + // if there is a getter or setter, then add a field proposal as well String mockFieldName = ProposalUtils.createMockFieldName(methodName); if (!alreadySeenFields.contains(mockFieldName)) { // be careful not to add fields twice alreadySeenFields.add(mockFieldName); if (hasNoField(method.getDeclaringClass(), methodName)) { - GroovyFieldProposal fieldProposal = new GroovyFieldProposal(createMockField(method)); - fieldProposal.setRelevanceMultiplier(isInterestingType ? 11 : 1); - groovyProposals.add(fieldProposal); + GroovyFieldProposal proposal = new GroovyFieldProposal(createMockField(method)); + proposal.setRelevanceMultiplier(isInterestingType ? 11 : 1); + proposals.add(proposal); } } } } } - // now do methods from static imports if (currentScope != null) { ClassNode enclosingTypeDeclaration = currentScope.getEnclosingTypeDeclaration(); if (enclosingTypeDeclaration != null && firstTime && isPrimary && type.getModule() != null) { - groovyProposals.addAll(getStaticImportProposals(prefix, type.getModule())); - } - } - - return groovyProposals; - } - - protected List getAllMethods(ClassNode type) { - List allMethods = type.getAllDeclaredMethods(); - if (!alreadySeen.isEmpty()) { - // remove all methods from classes that we have already visited - for (Iterator methodIter = allMethods.iterator(); methodIter.hasNext();) { - if (alreadySeen.contains(methodIter.next().getDeclaringClass())) { - methodIter.remove(); - } + findStaticImportProposals(proposals, prefix, type.getModule()); + findStaticFavoriteProposals(proposals, prefix, type.getModule()); } } - // keep track of the already seen types so that next time, we won't include them - Set types = new LinkedHashSet(); - getAllSupers(type, types, alreadySeen); - if (alreadySeen.isEmpty()) { - alreadySeen = types; - } else { - alreadySeen.addAll(types); - } - - return allMethods; + return proposals; } - private List getStaticImportProposals(String prefix, ModuleNode module) { - List staticProposals = new ArrayList(); - - Map staticImports = ImportNodeCompatibilityWrapper.getStaticImports(module); - for (Entry entry : staticImports.entrySet()) { + private void findStaticImportProposals(List proposals, String prefix, ModuleNode module) { + for (Map.Entry entry : ImportNodeCompatibilityWrapper.getStaticImports(module).entrySet()) { String fieldName = entry.getValue().getFieldName(); - if (fieldName != null && ProposalUtils.looselyMatches(prefix, fieldName)) { + if (ProposalUtils.looselyMatches(prefix, fieldName)) { List methods = entry.getValue().getType().getDeclaredMethods(fieldName); if (methods != null) { for (MethodNode method : methods) { - staticProposals.add(new GroovyMethodProposal(method, "Groovy", options)); + if (method.isStatic()) { + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setProposalFormattingOptions(options); + proposals.add(proposal); + } } } } } - - Map staticStarImports = ImportNodeCompatibilityWrapper.getStaticStarImports(module); - for (Entry entry : staticStarImports.entrySet()) { + for (Map.Entry entry : ImportNodeCompatibilityWrapper.getStaticStarImports(module).entrySet()) { ClassNode type = entry.getValue().getType(); if (type != null) { for (MethodNode method : (Iterable) type.getMethods()) { if (method.isStatic() && ProposalUtils.looselyMatches(prefix, method.getName())) { - staticProposals.add(new GroovyMethodProposal(method, "Groovy", options)); + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setProposalFormattingOptions(options); + proposals.add(proposal); + } + } + } + } + } + + private void findStaticFavoriteProposals(List proposals, String prefix, ModuleNode module) { + for (String favoriteStaticMember : favoriteStaticMembers) { + int pos = favoriteStaticMember.lastIndexOf('.'); + String typeName = favoriteStaticMember.substring(0, pos); + String fieldName = favoriteStaticMember.substring(pos + 1); + ClassNode typeNode = tryResolveClassNode(typeName, module); + + if (typeNode == null) { + if (GroovyLogManager.manager.hasLoggers()) { + GroovyLogManager.manager.log(TraceCategory.CONTENT_ASSIST, "Cannot resolve favorite type " + typeName); + } + continue; + } + + if ("*".equals(fieldName)) { + for (MethodNode method : (Iterable) typeNode.getMethods()) { + if (method.isStatic() && ProposalUtils.looselyMatches(prefix, method.getName())) { + proposals.add(newFavoriteMethodProposal(method, typeName + '.' + method.getName())); + } + } + } else { + if (ProposalUtils.looselyMatches(prefix, fieldName)) { + List methods = typeNode.getDeclaredMethods(fieldName); + for (MethodNode method : methods) { + if (method.isStatic()) { + proposals.add(newFavoriteMethodProposal(method, favoriteStaticMember)); + } } } } } + } - return staticProposals; + private IGroovyProposal newFavoriteMethodProposal(MethodNode method, String favorite) { + GroovyMethodProposal proposal = new GroovyMethodProposal(method); + proposal.setProposalFormattingOptions(options); + proposal.setRequiredStaticImport(favorite); + return proposal; } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyCompletionProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyCompletionProposal.java index 722cc25feb..46ebf98648 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyCompletionProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/processors/GroovyCompletionProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -57,7 +57,6 @@ public class GroovyCompletionProposal extends InternalCompletionProposal { */ private char[][] regularParameterTypeNames = CharOperation.NO_CHAR_CHAR; - private boolean useExtraParameters = false; public GroovyCompletionProposal(int kind, int completionLocation) { @@ -67,15 +66,19 @@ public GroovyCompletionProposal(int kind, int completionLocation) { public char[][] getNamedParameterNames() { return namedParameterNames; } + public char[][] getNamedParameterTypeNames() { return namedParameterTypeNames; } + public char[][] getOptionalParameterNames() { return optionalParameterNames; } + public char[][] getOptionalParameterTypeNames() { return optionalParameterTypeNames; } + public char[][] getRegularParameterNames() { if (useExtraParameters) { return regularParameterNames; @@ -155,7 +158,7 @@ public void setTypeName(char[] typeName) { } @Override - protected void setDeclarationPackageName(char[] declarationPackageName) { + public void setDeclarationPackageName(char[] declarationPackageName) { super.setDeclarationPackageName(declarationPackageName); } @@ -172,4 +175,4 @@ public char[][] findParameterNames(IProgressMonitor monitor) { public boolean hasParameters() { return super.getParameterTypeNames() != null && super.getParameterTypeNames().length > 0; } -} \ No newline at end of file +} 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 6cb3f63b1e..0efdcff6fc 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 @@ -68,29 +68,22 @@ import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.text.contentassist.ICompletionProposal; -/** - * @author Andrew Eisenberg - * @created Nov 11, 2009 - */ public class StatementAndExpressionCompletionProcessor extends AbstractGroovyCompletionProcessor { - class ExpressionCompletionRequestor implements ITypeRequestor { - - boolean visitSuccessful = false; - boolean isStatic = false; - ClassNode resultingType; - - ClassNode lhsType; - Set categories; - - VariableScope currentScope; + private class ExpressionCompletionRequestor implements ITypeRequestor { + // tracks the number of array accesses that must be dereferenced + private int derefCount; + private boolean isStatic; + private ClassNode lhsType; + private ClassNode resultingType; + private Set categories; private Expression arrayAccessLHS; + private VariableScope currentScope; - // keep track of the number of array accesses that must be dereferenced - private int derefCount = 0; + private boolean visitSuccessful; - public ExpressionCompletionRequestor() { + private ExpressionCompletionRequestor() { // remember the rightmost part of the LHS of a binary expression ASTNode maybeLHS = getContext().getPerceivedCompletionNode(); while (maybeLHS != null) { @@ -112,9 +105,7 @@ public ExpressionCompletionRequestor() { } } - public VisitStatus acceptASTNode(ASTNode node, TypeLookupResult result, - IJavaElement enclosingElement) { - + public VisitStatus acceptASTNode(ASTNode node, TypeLookupResult result, IJavaElement enclosingElement) { // check to see if the enclosing element does not enclose the nodeToLookFor if (!interestingElement(enclosingElement)) { return VisitStatus.CANCEL_MEMBER; @@ -128,8 +119,8 @@ public VisitStatus acceptASTNode(ASTNode node, TypeLookupResult result, } else if (node instanceof MethodNode) { MethodNode run = (MethodNode) node; if (run.getName().equals("run") && - run.getDeclaringClass().isScript() && - (run.getParameters() == null || run.getParameters().length == 0)) { + run.getDeclaringClass().isScript() && + (run.getParameters() == null || run.getParameters().length == 0)) { return VisitStatus.CONTINUE; } } @@ -142,9 +133,8 @@ public VisitStatus acceptASTNode(ASTNode node, TypeLookupResult result, } if (success) { maybeRememberLHSType(result); - resultingType = findResultingType(result, derefList); - categories = result.scope.getCategoryNames(); + resultingType = findResultingType(result, derefList); visitSuccessful = true; isStatic = node instanceof StaticMethodCallExpression || // if we are completing on '.class' then never static context @@ -209,7 +199,7 @@ private boolean doTestForAfterArrayAccess(ASTNode node) { } private void maybeRememberLHSType(TypeLookupResult result) { - if (isAssignmentOfLhs(result.enclosingAssignment)) { + if (isAssignmentOfLHS(result.enclosingAssignment)) { // check to see if this is the rhs of an assignment. // if so, then attempt to use the type of the lhs for // ordering of the proposals @@ -230,11 +220,12 @@ private void maybeRememberLHSType(TypeLookupResult result) { } } - private boolean isAssignmentOfLhs(BinaryExpression node) { + private boolean isAssignmentOfLHS(BinaryExpression node) { if (node != null && lhsNode != null) { Expression expression = node.getLeftExpression(); - return expression.getClass() == lhsNode.getClass() && expression.getStart() == lhsNode.getStart() - && expression.getEnd() == lhsNode.getEnd(); + return expression.getClass() == lhsNode.getClass() && + expression.getStart() == lhsNode.getStart() && + expression.getEnd() == lhsNode.getEnd(); } return false; } @@ -260,8 +251,7 @@ private boolean doTest(ASTNode node) { } /** - * @param enclosingElement - * @return true iff enclosingElement's source location contains the source location of {@link #nodeToLookFor} + * @return {@code true} iff enclosingElement's source location contains the source location of {@link #nodeToLookFor} */ private boolean interestingElement(IJavaElement enclosingElement) { // the clinit is always interesting since the clinit contains static initializers @@ -290,29 +280,18 @@ private boolean isNotExpressionAndStatement(ASTNode thisNode, ASTNode otherNode) return true; } } - - public ClassNode getResultingType() { - return resultingType; - } - public Set getCategories() { - return categories; - } - - public boolean isVisitSuccessful() { - return visitSuccessful; - } } /** * the ASTNode being completed. */ - final ASTNode completionNode; + private final ASTNode completionNode; /** * the LHS of the assignment statement associated with this content assist * invocation, or null if there is none. */ - final Expression lhsNode; + private final Expression lhsNode; public StatementAndExpressionCompletionProcessor(ContentAssistContext context, JavaContentAssistInvocationContext javaContext, SearchableEnvironment nameEnvironment) { @@ -334,7 +313,7 @@ public List generateProposals(IProgressMonitor monitor) { ClassNode completionType; boolean isStatic; List groovyProposals = new LinkedList(); - if (requestor.isVisitSuccessful()) { + if (requestor.visitSuccessful) { isStatic = isStatic() || requestor.isStatic; completionType = getCompletionType(requestor); if (completionType == null) { @@ -450,8 +429,7 @@ public List generateProposals(IProgressMonitor monitor) { } private void proposalCreatorLoop(ContentAssistContext context, ExpressionCompletionRequestor requestor, - ClassNode completionType, boolean isStatic, List groovyProposals, IProposalCreator[] creators, - boolean isClosureThis) { + ClassNode completionType, boolean isStatic, List groovyProposals, IProposalCreator[] creators, boolean isClosureThis) { for (IProposalCreator creator : creators) { if (isClosureThis && !creator.redoForLoopClosure()) { // avoid duplicate DGMs by not proposing category proposals twice @@ -460,9 +438,14 @@ private void proposalCreatorLoop(ContentAssistContext context, ExpressionComplet if (creator instanceof AbstractProposalCreator) { ((AbstractProposalCreator) creator).setLhsType(requestor.lhsType); ((AbstractProposalCreator) creator).setCurrentScope(requestor.currentScope); + ((AbstractProposalCreator) creator).setFavoriteStaticMembers(context.getFavoriteStaticMembers()); } - groovyProposals.addAll(creator.findAllProposals(completionType, requestor.categories, - context.getPerceivedCompletionExpression(), isStatic, ContentAssistLocation.STATEMENT == context.location)); + groovyProposals.addAll(creator.findAllProposals( + completionType, + requestor.categories, + context.getPerceivedCompletionExpression(), + isStatic, + ContentAssistLocation.STATEMENT == context.location)); } } 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 c62b557c6d..acae679bfa 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-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -15,41 +15,42 @@ */ package org.codehaus.groovy.eclipse.codeassist.proposals; -import groovyjarjarasm.asm.Opcodes; -import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; -import org.codehaus.groovy.ast.FieldNode; -import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.eclipse.codeassist.relevance.Relevance; -import org.eclipse.jdt.core.CompletionProposal; -import org.eclipse.jdt.internal.ui.JavaPlugin; -import org.eclipse.jdt.internal.ui.JavaPluginImages; -import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry; -import org.eclipse.jdt.ui.text.java.CompletionProposalLabelProvider; -import org.eclipse.swt.graphics.Image; -/** - * @author Andrew Eisenberg - * @created Nov 12, 2009 - * - */ public abstract class AbstractGroovyProposal implements IGroovyProposal { - private final static ImageDescriptorRegistry registry= JavaPlugin.getImageDescriptorRegistry(); + /** + * @return the AST node associated with this proposal, or null if there is none + */ + public AnnotatedNode getAssociatedNode() { + return null; + } + + protected int computeRelevance() { + return Relevance.calculateRelevance(this, relevanceMultiplier); + } private float relevanceMultiplier = 1; - protected Image getImage(CompletionProposal proposal, CompletionProposalLabelProvider labelProvider) { - return registry.get(labelProvider.createImageDescriptor(proposal)); + public void setRelevanceMultiplier(float relevanceMultiplier) { + this.relevanceMultiplier = relevanceMultiplier; } + protected String requiredStaticImport; + + public void setRequiredStaticImport(String requiredStaticImport) { + this.requiredStaticImport = requiredStaticImport; + } + + /*protected Image getImage(CompletionProposal proposal, CompletionProposalLabelProvider labelProvider) { + return JavaPlugin.getImageDescriptorRegistry().get(labelProvider.createImageDescriptor(proposal)); + }*/ + /** - * Use {@link ProposalUtils#getImage(CompletionProposal)} instead - * - * @param node - * @return + * Use {@link ProposalUtils#getImage(CompletionProposal)} instead. */ - @Deprecated + /*@Deprecated protected Image getImageFor(ASTNode node) { if (node instanceof FieldNode) { int mods = ((FieldNode) node).getModifiers(); @@ -74,16 +75,16 @@ protected Image getImageFor(ASTNode node) { return JavaPluginImages.get(JavaPluginImages.IMG_FIELD_DEFAULT); } return null; - } - private boolean test(int flags, int mask) { + }*/ + + /*private boolean test(int flags, int mask) { return (flags & mask) != 0; - } + }*/ /** - * Very simple way to calculate relevance based on name. Now deprecated. Use - * {@link #computeRelevance()} or {@link #computeRelevance(float)} instead + * Use {@link #computeRelevance()} or {@link #computeRelevance(float)} instead. */ - @Deprecated + /*@Deprecated protected int getRelevance(char[] name) { switch(name[0]) { case '$': @@ -93,22 +94,5 @@ protected int getRelevance(char[] name) { default: return 1000; } - } - - /** - * @return the AST node associated with this proposal, or null if there is - * none. - */ - public AnnotatedNode getAssociatedNode() { - return null; - } - - protected int computeRelevance() { - return Relevance.calculateRelevance(this, relevanceMultiplier); - } - - public void setRelevanceMultiplier(float relevanceMultiplier) { - this.relevanceMultiplier = relevanceMultiplier; - } - + }*/ } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyCategoryMethodProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyCategoryMethodProposal.java index 0cf56fca16..236e73dfd1 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyCategoryMethodProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyCategoryMethodProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -16,39 +16,25 @@ package org.codehaus.groovy.eclipse.codeassist.proposals; import groovyjarjarasm.asm.Opcodes; - import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.eclipse.jdt.core.ICompilationUnit; -/** - * @author Andrew Eisenberg - * @created Nov 12, 2009 - * - */ public class GroovyCategoryMethodProposal extends GroovyMethodProposal { public GroovyCategoryMethodProposal(MethodNode method) { super(method, "Category: " + method.getDeclaringClass().getNameWithoutPackage()); } - public GroovyCategoryMethodProposal(MethodNode method, String contributor) { - super(method, contributor); - } - - public GroovyCategoryMethodProposal(MethodNode method, String contributor, ProposalFormattingOptions options) { - super(method, contributor, options); - } - @Override protected int getModifiers() { - return method.getModifiers() & ~Opcodes.ACC_STATIC; // category methods are defined as static, but should not appear as such when a proposal + return getMethod().getModifiers() & ~Opcodes.ACC_STATIC; // category methods are defined as static, but should not appear as such when a proposal } @Override protected char[] createMethodSignature() { - return ProposalUtils.createMethodSignature(method, 1); + return ProposalUtils.createMethodSignature(getMethod(), 1); } @Override diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyFieldProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyFieldProposal.java index 522c972b2d..3bfa9b2dd9 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyFieldProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyFieldProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -18,89 +18,77 @@ import org.codehaus.groovy.ast.AnnotatedNode; import org.codehaus.groovy.ast.FieldNode; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; +import org.codehaus.groovy.eclipse.codeassist.completions.GroovyJavaFieldCompletionProposal; +import org.codehaus.groovy.eclipse.codeassist.processors.GroovyCompletionProposal; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistLocation; +import org.eclipse.jdt.core.CompletionFlags; import org.eclipse.jdt.core.CompletionProposal; -import org.eclipse.jdt.internal.codeassist.InternalCompletionProposal; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.viewers.StyledString; -/** - * @author Andrew Eisenberg - * @created Nov 12, 2009 - * - */ public class GroovyFieldProposal extends AbstractGroovyProposal { - private final FieldNode field; - private final String contributor; + public GroovyFieldProposal(FieldNode field) { this.field = field; - this.contributor = "Groovy"; - } - public GroovyFieldProposal(FieldNode field, String contributor) { - this.field = field; - this.contributor = contributor; } - public GroovyFieldProposal(FieldNode field, int relevanceMultiplier) { - this.field = field; - setRelevanceMultiplier(relevanceMultiplier); - this.contributor = "Groovy"; + @Override + public AnnotatedNode getAssociatedNode() { + return field; } - public GroovyFieldProposal(FieldNode field, int relevanceMultiplier, - String contributor) { - this.field = field; - setRelevanceMultiplier(relevanceMultiplier); - this.contributor = contributor; + public FieldNode getField() { + return field; } - public IJavaCompletionProposal createJavaProposal( - ContentAssistContext context, - JavaContentAssistInvocationContext javaContext) { + public IJavaCompletionProposal createJavaProposal(ContentAssistContext context, JavaContentAssistInvocationContext javaContext) { if (context.location == ContentAssistLocation.METHOD_CONTEXT) { return null; } - CompletionProposal proposal = createProposal(context); - return new GroovyJavaFieldCompletionProposal(proposal, - ProposalUtils.getImage(proposal), createDisplayString(field)); - } + GroovyCompletionProposal proposal = new GroovyCompletionProposal(CompletionProposal.FIELD_REF, context.completionLocation); + proposal.setCompletion(proposal.getName()); + proposal.setDeclarationSignature(ProposalUtils.createTypeSignature(field.getDeclaringClass())); + proposal.setFlags(field.getModifiers()); + proposal.setName(field.getName().toCharArray()); + proposal.setRelevance(computeRelevance()); + proposal.setReplaceRange(context.completionLocation - context.completionExpression.length(), context.completionEnd); + proposal.setSignature(ProposalUtils.createTypeSignature(field.getType())); - @Override - public AnnotatedNode getAssociatedNode() { - return field; - } + if (requiredStaticImport != null) { + GroovyCompletionProposal fieldImportProposal = new GroovyCompletionProposal(CompletionProposal.FIELD_IMPORT, context.completionLocation); + fieldImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); + fieldImportProposal.setCompletion(("import static " + requiredStaticImport + "\n").toCharArray()); + fieldImportProposal.setDeclarationSignature(proposal.getDeclarationSignature()); + fieldImportProposal.setName(proposal.getName()); - protected StyledString createDisplayString(FieldNode field) { - StyledString ss = new StyledString(); + /* + fieldImportProposal.setDeclarationPackageName(field.getDeclaringClass().getPackageName().toCharArray()); + fieldImportProposal.setDeclarationTypeName(field.getDeclaringClass().getName().toCharArray()); + fieldImportProposal.setFlags(proposal.getFlags()); + fieldImportProposal.setPackageName(field.getType().getPackageName().toCharArray()); + fieldImportProposal.setRelevance(proposal.getRelevance()); + fieldImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); + fieldImportProposal.setSignature(proposal.getSignature()); + fieldImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); + fieldImportProposal.setTypeName(field.getType().getName().toCharArray()); + */ - ss.append(field.getName()) - .append(" : ") - .append(ProposalUtils.createSimpleTypeName(field.getType())) - .append(" - ") - .append(ProposalUtils.createSimpleTypeName(field.getDeclaringClass()), StyledString.QUALIFIER_STYLER) - .append(" (" + contributor + ")", StyledString.DECORATIONS_STYLER); - return ss; - } + proposal.setRequiredProposals(new CompletionProposal[] {fieldImportProposal}); + } - private CompletionProposal createProposal(ContentAssistContext context) { - InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.FIELD_REF, context.completionLocation); - proposal.setFlags(field.getModifiers()); - proposal.setName(field.getName().toCharArray()); - proposal.setCompletion(proposal.getName()); - proposal.setSignature(ProposalUtils.createTypeSignature(field.getType())); - proposal.setDeclarationSignature(ProposalUtils.createTypeSignature(field.getDeclaringClass())); - proposal.setRelevance(computeRelevance()); - int startIndex = context.completionLocation-context.completionExpression.length(); - proposal.setReplaceRange(startIndex, context.completionEnd); - return proposal; + return new GroovyJavaFieldCompletionProposal(proposal, createDisplayString(field), javaContext); } - public FieldNode getField() { - return field; + private StyledString createDisplayString(FieldNode field) { + return new StyledString().append(field.getName()) + .append(" : ") + .append(ProposalUtils.createSimpleTypeName(field.getType())) + .append(" - ") + .append(ProposalUtils.createSimpleTypeName(field.getDeclaringClass()), StyledString.QUALIFIER_STYLER); } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java index f27275c139..3ab70ac644 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -46,13 +46,9 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; -/** - * @author Andrew Eisenberg - * @created Nov 12, 2009 - */ public class GroovyMethodProposal extends AbstractGroovyProposal { - protected final MethodNode method; + private final MethodNode method; private String contributor; @@ -72,9 +68,8 @@ public class GroovyMethodProposal extends AbstractGroovyProposal { public GroovyMethodProposal(MethodNode method) { super(); this.method = method; - contributor = "Groovy"; - useNamedArguments = false; - noParens = false; + this.noParens = false; + this.useNamedArguments = false; } public GroovyMethodProposal(MethodNode method, String contributor) { @@ -82,8 +77,11 @@ public GroovyMethodProposal(MethodNode method, String contributor) { this.contributor = contributor; } - public GroovyMethodProposal(MethodNode method, String contributor, ProposalFormattingOptions options) { - this(method, contributor); + public MethodNode getMethod() { + return method; + } + + public void setProposalFormattingOptions(ProposalFormattingOptions options) { this.options = options; } @@ -101,7 +99,6 @@ public AnnotatedNode getAssociatedNode() { } public IJavaCompletionProposal createJavaProposal(ContentAssistContext context, JavaContentAssistInvocationContext javaContext) { - int kind = (context.location == ContentAssistLocation.ANNOTATION_BODY ? CompletionProposal.ANNOTATION_ATTRIBUTE_REF : CompletionProposal.METHOD_REF); GroovyCompletionProposal proposal = new GroovyCompletionProposal(kind, context.completionLocation); @@ -133,6 +130,32 @@ public IJavaCompletionProposal createJavaProposal(ContentAssistContext context, proposal.setKey(proposal.getSignature()); proposal.setRelevance(computeRelevance()); + if (requiredStaticImport != null) { + GroovyCompletionProposal methodImportProposal = new GroovyCompletionProposal(CompletionProposal.METHOD_IMPORT, context.completionLocation); + methodImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); + methodImportProposal.setCompletion(("import static " + requiredStaticImport + "\n").toCharArray()); + methodImportProposal.setDeclarationSignature(proposal.getDeclarationSignature()); + methodImportProposal.setName(proposal.getName()); + + /* + methodImportProposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); + methodImportProposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); + methodImportProposal.setFlags(method.modifiers); + if (original != method) proposal.setOriginalSignature(getSignature(original)); + if(parameterNames != null) methodImportProposal.setParameterNames(parameterNames); + methodImportProposal.setParameterPackageNames(parameterPackageNames); + methodImportProposal.setParameterTypeNames(parameterTypeNames); + methodImportProposal.setPackageName(method.returnType.qualifiedPackageName()); + methodImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); + methodImportProposal.setRelevance(relevance); + methodImportProposal.setSignature(getSignature(method)); + methodImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); + methodImportProposal.setTypeName(method.returnType.qualifiedSourceName()); + */ + + proposal.setRequiredProposals(new CompletionProposal[] {methodImportProposal}); + } + LazyJavaCompletionProposal lazyProposal = null; if (kind == CompletionProposal.ANNOTATION_ATTRIBUTE_REF) { proposal.setSignature(createTypeSignature(getMethod().getReturnType())); @@ -147,23 +170,16 @@ public IJavaCompletionProposal createJavaProposal(ContentAssistContext context, } if (lazyProposal == null) { lazyProposal = new GroovyJavaMethodCompletionProposal(proposal, javaContext, groovyProposalOptions, contributor); - // if location is METHOD_CONTEXT, then the type must be - // MethodInfoContentAssistContext, - // but there are other times when the type is - // MethodInfoContentAssistContext as well. + // if location is METHOD_CONTEXT, then the type must be MethodInfoContentAssistContext + // ...but there are other times when the type is MethodInfoContentAssistContext as well if (context.location == ContentAssistLocation.METHOD_CONTEXT) { ((GroovyJavaMethodCompletionProposal) lazyProposal).contextOnly(); } } - if (context.location == ContentAssistLocation.METHOD_CONTEXT) { - // attempt to find the location immediately after the opening - // paren. - // if this is wrong, no big deal, but the context information - // will not be properly - // highlighted. - // Assume that there is the method name, and then an opening - // paren (or a space) and then - // the arguments (hence the +2). + if (context.location == ContentAssistLocation.METHOD_CONTEXT) { // NOTE: I've seen STATEMENT for 'assertNu|' and EXPRESSION for 'Assert.assertNu|' + // attempt to find the location immediately after the opening paren + // if this is wrong, no big deal, but the context information will not be properly highlighted + // assume that there is the method name, and then an opening paren (or a space) and then the arguments lazyProposal.setContextInformationPosition(((MethodInfoContentAssistContext) context).methodNameEnd + 1); } } @@ -322,12 +338,7 @@ protected char[][] calculateAllParameterNames(ICompilationUnit unit, MethodNode } /** - * Finds a method with the same name and parameter types - * - * @param declaringType - * @param parameterTypeSignatures - * @return - * @throws JavaModelException + * Finds a method with the same name and parameter types. */ private IMethod findPreciseMethod(IType declaringType, String[] parameterTypeSignatures) throws JavaModelException { IMethod closestMatch = declaringType.getMethod(method.getName(), parameterTypeSignatures); @@ -368,9 +379,7 @@ private IMethod findPreciseMethod(IType declaringType, String[] parameterTypeSig private String removeGenerics(String maybeMethodParameterName) { int genericStart = maybeMethodParameterName.indexOf("<"); if (genericStart > 0) { - maybeMethodParameterName = maybeMethodParameterName.substring(0, genericStart) - + maybeMethodParameterName.substring(maybeMethodParameterName.indexOf(">") + 1, - maybeMethodParameterName.length()); + maybeMethodParameterName = maybeMethodParameterName.substring(0, genericStart) + maybeMethodParameterName.substring(maybeMethodParameterName.indexOf(">") + 1, maybeMethodParameterName.length()); } return maybeMethodParameterName; } @@ -380,7 +389,7 @@ private char[][] getSpecialParameterNames(Parameter[] params) { // correct as is // because these parameters were explicitly set by a script char[][] paramNames = new char[params.length][]; - for (int i = 0; i < params.length; i++) { + for (int i = 0, n = params.length; i < n; i += 1) { paramNames[i] = params[i].getName().toCharArray(); } return paramNames; @@ -392,11 +401,4 @@ private IType findDeclaringType(ICompilationUnit unit, MethodNode method) throws } return cachedDeclaringType; } - - /** - * @return the method - */ - public MethodNode getMethod() { - return method; - } } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyPropertyProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyPropertyProposal.java index f4101590d0..79d81c93b8 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyPropertyProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyPropertyProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -17,6 +17,7 @@ import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; +import org.codehaus.groovy.eclipse.codeassist.completions.GroovyJavaFieldCompletionProposal; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistLocation; import org.eclipse.jdt.core.CompletionProposal; @@ -45,16 +46,13 @@ public GroovyPropertyProposal(PropertyNode property, String contributor) { this.contributor = contributor; } - public IJavaCompletionProposal createJavaProposal( - ContentAssistContext context, - JavaContentAssistInvocationContext javaContext) { + public IJavaCompletionProposal createJavaProposal(ContentAssistContext context, JavaContentAssistInvocationContext javaContext) { if (context.location == ContentAssistLocation.METHOD_CONTEXT) { return null; } CompletionProposal proposal = createProposal(context); - return new GroovyJavaFieldCompletionProposal(proposal, - ProposalUtils.getImage(proposal), createDisplayString(property)); + return new GroovyJavaFieldCompletionProposal(proposal, createDisplayString(property), javaContext); } protected StyledString createDisplayString(PropertyNode property) { diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/IGroovyProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/IGroovyProposal.java index 15cf3d903f..fe6d8e702f 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/IGroovyProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/IGroovyProposal.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -19,12 +19,6 @@ import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; -/** - * @author Andrew Eisenberg - * @created Nov 12, 2009 - * - */ public interface IGroovyProposal { - IJavaCompletionProposal createJavaProposal(ContentAssistContext context, - JavaContentAssistInvocationContext javaContext); + IJavaCompletionProposal createJavaProposal(ContentAssistContext context, JavaContentAssistInvocationContext javaContext); } diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/requestor/ContentAssistContext.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/requestor/ContentAssistContext.java index 711852cfff..65d86b6157 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/requestor/ContentAssistContext.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/requestor/ContentAssistContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2016 the original author or authors. + * Copyright 2009-2017 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. @@ -15,6 +15,10 @@ */ package org.codehaus.groovy.eclipse.codeassist.requestor; +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; import org.codehaus.groovy.ast.ClassNode; @@ -25,11 +29,8 @@ import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.groovy.search.VariableScope; +import org.eclipse.jdt.ui.PreferenceConstants; -/** - * @author Andrew Eisenberg - * @created Nov 9, 2009 - */ public class ContentAssistContext { /** @@ -97,6 +98,8 @@ public class ContentAssistContext { */ public VariableScope currentScope; + private Set favoriteStaticMembers; + public ContentAssistContext( int completionLocation, String completionExpression, @@ -140,6 +143,23 @@ public ClassNode getEnclosingGroovyType() { } } + /** + * @see org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposalComputer.getFavoriteStaticMembers() + */ + public Set getFavoriteStaticMembers() { + if (favoriteStaticMembers == null) { + String serializedFavorites = PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS); + if (serializedFavorites != null && serializedFavorites.length() > 0) { + favoriteStaticMembers = new TreeSet(); + Collections.addAll(favoriteStaticMembers, + serializedFavorites.split(";")); + } else { + favoriteStaticMembers = Collections.emptySet(); + } + } + return favoriteStaticMembers; + } + /** * The completion node that is being used for completion * (may be different than the default if doing a method context completon diff --git a/ide/org.codehaus.groovy.eclipse.dsl/src/org/codehaus/groovy/eclipse/dsl/contributions/MethodContributionElement.java b/ide/org.codehaus.groovy.eclipse.dsl/src/org/codehaus/groovy/eclipse/dsl/contributions/MethodContributionElement.java index 146d26a3bd..b6ff4a408b 100644 --- a/ide/org.codehaus.groovy.eclipse.dsl/src/org/codehaus/groovy/eclipse/dsl/contributions/MethodContributionElement.java +++ b/ide/org.codehaus.groovy.eclipse.dsl/src/org/codehaus/groovy/eclipse/dsl/contributions/MethodContributionElement.java @@ -106,11 +106,12 @@ public TypeAndDeclaration lookupType(String name, ClassNode declaringType, Resol } public IGroovyProposal toProposal(ClassNode declaringType, ResolverCache resolver) { - GroovyMethodProposal groovyMethodProposal = new GroovyMethodProposal(toMethod(declaringType.redirect(), resolver), provider, options); - groovyMethodProposal.setUseNamedArguments(useNamedArgs); - groovyMethodProposal.setNoParens(noParens); - groovyMethodProposal.setRelevanceMultiplier(relevanceMultiplier); - return groovyMethodProposal; + GroovyMethodProposal proposal = new GroovyMethodProposal(toMethod(declaringType.redirect(), resolver), provider); + proposal.setRelevanceMultiplier(relevanceMultiplier); + proposal.setProposalFormattingOptions(options); + proposal.setUseNamedArguments(useNamedArgs); + proposal.setNoParens(noParens); + return proposal; } public List extraProposals(ClassNode declaringType, ResolverCache resolver, Expression expression) {