From c4fa59e7ab5e06d21a33a98141a96bb8f08f161e Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Thu, 16 Nov 2017 14:01:24 -0600 Subject: [PATCH] Fix for issue #390: visit statically-compiled enum constant members --- .../search/Groovy21InferencingTests.java | 51 +++++++++++++++---- .../TypeInferencingVisitorWithRequestor.java | 48 +++++++++++------ .../testEnumOverrides/in/A.groovy | 6 +-- .../testEnumOverrides/out/A.groovy | 6 +-- .../testEnumOverrides2/in/A.groovy | 24 +++++++++ .../testEnumOverrides2/out/A.groovy | 24 +++++++++ .../test/rename/RenameMethodTests.groovy | 9 +++- 7 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/in/A.groovy create mode 100644 ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/out/A.groovy diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java index a4e7e53bf4..3edbb1464c 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java @@ -38,7 +38,7 @@ public void setUp() { } @Test - public void testDelegatesToValue1() { + public void testDelegatesToValue() { String contents = "class Other { }\n" + "def meth(@DelegatesTo(Other) Closure c) { }\n" + @@ -225,8 +225,41 @@ public void testDelegatesToTarget5() { assertUnknownConfidence(contents, offset, offset + 1, "B", false); } + @Test // https://github.com/groovy/groovy-eclipse/issues/389 + public void testEnumOverrides() { + String contents = + "enum E {\n" + + " ONE() {\n" + + " void meth(Number param) { println param }\n" + + " },\n" + + " TWO() {\n" + + " void meth(Number param) { null }\n" + + " }\n" + + " abstract void meth(Number param);\n" + + "}"; + int offset = contents.indexOf("println param") + "println ".length(); + assertType(contents, offset, offset + "param".length(), "java.lang.Number"); + } + + @Test // https://github.com/groovy/groovy-eclipse/issues/390 + public void testEnumOverrides2() { + String contents = + "@groovy.transform.CompileStatic\n" + + "enum E {\n" + + " ONE() {\n" + + " void meth(Number param) { println param }\n" + + " },\n" + + " TWO() {\n" + + " void meth(Number param) { null }\n" + + " }\n" + + " abstract void meth(Number param);\n" + + "}"; + int offset = contents.indexOf("println param") + "println ".length(); + assertType(contents, offset, offset + "param".length(), "java.lang.Number"); + } + @Test - public void testStaticCompile1() { + public void testStaticCompile() { Activator.getInstancePreferences().getBoolean(Activator.GROOVY_SCRIPT_FILTERS_ENABLED, Activator.DEFAULT_SCRIPT_FILTERS_ENABLED); Activator.getInstancePreferences().get(Activator.GROOVY_SCRIPT_FILTERS, Activator.DEFAULT_GROOVY_SCRIPT_FILTER); try { @@ -261,13 +294,13 @@ public void testStaticCompile1() { String contents = "import groovy.transform.TypeChecked\n" + - "class Robot {\n" + - " void move(String dist) { println \"Moved $dist\" }\n" + - "}\n" + - "@TypeChecked(extensions = 'robot/RobotMove.groovy')\n" + - "void operate() {\n" + - " robot.move \"left\"\n" + - "}"; + "class Robot {\n" + + " void move(String dist) { println \"Moved $dist\" }\n" + + "}\n" + + "@TypeChecked(extensions = 'robot/RobotMove.groovy')\n" + + "void operate() {\n" + + " robot.move \"left\"\n" + + "}"; int start = contents.lastIndexOf("move"); int end = start + "move".length(); diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java index 4a62c3a373..201b3fbea6 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java @@ -754,6 +754,28 @@ private void visitMethodInternal(MethodNode node, boolean isCtor) { } } + /** + * @param node anonymous inner class for enum constant + */ + private void visitMethodOverrides(ClassNode node) { + scopes.add(new VariableScope(scopes.getLast(), node, false)); + ASTNode enclosingDeclaration0 = enclosingDeclarationNode; + IJavaElement enclosingElement0 = enclosingElement; + enclosingDeclarationNode = node; + try { + for (MethodNode method : node.getMethods()) { + if (method.getEnd() > 0) { + //enclosingElement = ((SourceType) enclosingElement0).getMethod(method.getName(), getParameterTypeSignatures(method.getParameters())); + visitMethodInternal(method, false); + } + } + } finally { + scopes.removeLast(); + enclosingElement = enclosingElement0; + enclosingDeclarationNode = enclosingDeclaration0; + } + } + // @Override @@ -1493,6 +1515,11 @@ public void visitMethodCallExpression(MethodCallExpression node) { node.getArguments().visit(this); scope.forgetEnclosingMethodCall(); + ClassNode type; + if (isEnumInit(node) && GroovyUtils.isAnonymous(type = ((Expression) node.getReceiver()).getType())) { + visitMethodOverrides(type); + } + // if this method call is the primary of a larger expression, then pass the inferred type onwards if (node.isSpreadSafe()) { returnType = createParameterizedList(returnType); @@ -1688,22 +1715,7 @@ public void visitStaticMethodCallExpression(StaticMethodCallExpression node) { super.visitStaticMethodCallExpression(node); // visit anonymous inner class members if (GroovyUtils.isAnonymous(type)) { - scopes.add(new VariableScope(scopes.getLast(), type, false)); - ASTNode enclosingDeclaration0 = enclosingDeclarationNode; - IJavaElement enclosingElement0 = enclosingElement; - enclosingDeclarationNode = type; - try { - for (MethodNode method : type.getMethods()) { - if (method.getEnd() > 0) { - //enclosingElement = ((SourceType) enclosingElement0).getMethod(method.getName(), getParameterTypeSignatures(method.getParameters())); - visitMethodInternal(method, false); - } - } - } finally { - scopes.removeLast(); - enclosingElement = enclosingElement0; - enclosingDeclarationNode = enclosingDeclaration0; - } + visitMethodOverrides(type); } } } @@ -2756,6 +2768,10 @@ private static ClassNode[] inferClosureParamTypes(VariableScope scope, ClosureEx return inferredTypes; } + private static boolean isEnumInit(MethodCallExpression node) { + return (node.getType().isEnum() && node.getMethodAsString().equals("$INIT")); + } + private static boolean isEnumInit(StaticMethodCallExpression node) { return (node.getOwnerType().isEnum() && node.getMethod().equals("$INIT")); } diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/in/A.groovy b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/in/A.groovy index e33486ea54..bec4dad7b6 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/in/A.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/in/A.groovy @@ -2,12 +2,12 @@ package p; enum A { - A() { + ONE() { @Override String getFoo() { } }, - B() { + TWO() { @Override String getFoo() { "bar" @@ -16,4 +16,4 @@ enum A { String getFoo() { } -} \ No newline at end of file +} diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/out/A.groovy b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/out/A.groovy index 5a4038bf5b..f5a9a80b79 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/out/A.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides/out/A.groovy @@ -2,12 +2,12 @@ package p; enum A { - A() { + ONE() { @Override String foo() { } }, - B() { + TWO() { @Override String foo() { "bar" @@ -16,4 +16,4 @@ enum A { String foo() { } -} \ No newline at end of file +} diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/in/A.groovy b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/in/A.groovy new file mode 100644 index 0000000000..e19ea85f8d --- /dev/null +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/in/A.groovy @@ -0,0 +1,24 @@ +package p; + +import groovy.transform.CompileStatic; + +@CompileStatic +enum A { + + A() { + @Override + String getFoo() { + 'bar' + } + }, + + B() { + @Override + String getFoo() { + 'baz' + } + } + + String getFoo() { + } +} diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/out/A.groovy b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/out/A.groovy new file mode 100644 index 0000000000..87955192ec --- /dev/null +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/resources/RenameMethod/testEnumOverrides2/out/A.groovy @@ -0,0 +1,24 @@ +package p; + +import groovy.transform.CompileStatic; + +@CompileStatic +enum A { + + A() { + @Override + String foo() { + 'bar' + } + }, + + B() { + @Override + String foo() { + 'baz' + } + } + + String foo() { + } +} diff --git a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/src/org/codehaus/groovy/eclipse/refactoring/test/rename/RenameMethodTests.groovy b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/src/org/codehaus/groovy/eclipse/refactoring/test/rename/RenameMethodTests.groovy index e65f1ae2b6..1acaf58f7c 100644 --- a/ide-test/org.codehaus.groovy.eclipse.refactoring.test/src/org/codehaus/groovy/eclipse/refactoring/test/rename/RenameMethodTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.refactoring.test/src/org/codehaus/groovy/eclipse/refactoring/test/rename/RenameMethodTests.groovy @@ -129,13 +129,20 @@ final class RenameMethodTests extends RefactoringTestSuite { runTest('I', 'run', 'sam', [], true, false); } - @Test // GRECLIPSE-1538 + @Test // https://github.com/groovy/groovy-eclipse/issues/389 void testEnumOverrides() { assumeTrue(isAtLeastGroovy(21)) // rename A.getFoo() to A.foo() and enum constant overrides should change runTest('A', 'getFoo', 'foo', [], true, false) } + @Test // https://github.com/groovy/groovy-eclipse/issues/390 + void testEnumOverrides2() { + assumeTrue(isAtLeastGroovy(21)) + // rename A.getFoo() to A.foo() and enum constant overrides should change + runTest('A', 'getFoo', 'foo', [], true, false) + } + @Test void testInitializer1() { runTest('A', 'm', 'k', [], true, false)