Skip to content

Commit

Permalink
Fix for #1523: STC: extended/implemented type for anonymous inner class
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Dec 18, 2023
1 parent bc0819f commit aae7a6f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,15 @@ public void testConstructorReferences17() throws Exception {
" Foo(String s) {}\n" +
"}\n");
createUnit("Other", "import p.Foo\n" +
"def foo = new Foo(0) {\n" + // yes
"def one = new Foo(0) {}\n" + // yes
"@groovy.transform.TypeChecked stc() {\n" +
" def two = new Foo(0) {}\n" + // yes
"}\n" +
"@groovy.transform.CompileStatic sc() {\n" +
" def three = new Foo(0) {}\n" + // yes
"}\n");

assertEquals(1, searchForReferences(foo.getType("Foo").getMethods()[0]).stream().count());
assertEquals(3, searchForReferences(foo.getType("Foo").getMethods()[0]).stream().count());
}

@Test
Expand All @@ -399,7 +404,12 @@ public void testConstructorReferences18() throws Exception {
" Foo(String s) {}\n" + // search for this
"}\n");
createUnit("Other", "import p.Foo\n" +
"def foo = new Foo(0) {\n" + // no
"def one = new Foo(0) {}\n" + // no
"@groovy.transform.TypeChecked stc() {\n" +
" def two = new Foo(0) {}\n" + // no
"}\n" +
"@groovy.transform.CompileStatic sc() {\n" +
" def three = new Foo(0) {}\n" + // no
"}\n");

assertEquals(0, searchForReferences(foo.getType("Foo").getMethods()[1]).stream().count());
Expand All @@ -412,7 +422,7 @@ public void testConstructorReferences19() throws Exception {
" Foo(String s, Map m) {}\n" +
" Foo(String s, ... v) {}\n" + // search for this
"}\n");
createUnit("Other", "def foo = new p.Foo('')\n");
createUnit("Other", "def one = new p.Foo('')\n");

assertEquals(1, searchForReferences(foo.getType("Foo").getMethods()[1]).stream().count());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -961,66 +961,66 @@ public void testClassLiteral5() {
@Test // GRECLIPSE-1229: constructors with map parameters
public void testConstructor1() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"new O(aa: 1, bb:8)\n";
"new C(aa: 1, bb:8)\n";

int start = contents.lastIndexOf("aa");
int end = start + "aa".length();
assertType(contents, start, end, "java.lang.Boolean");
assertDeclaration(contents, start, end, "O", "aa", DeclarationKind.PROPERTY);
assertDeclaration(contents, start, end, "C", "aa", DeclarationKind.PROPERTY);

start = contents.lastIndexOf("bb");
end = start + "bb".length();
assertType(contents, start, end, "java.lang.Integer");
assertDeclaration(contents, start, end, "O", "bb", DeclarationKind.PROPERTY);
assertDeclaration(contents, start, end, "C", "bb", DeclarationKind.PROPERTY);
}

@Test
public void testConstructor2() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"new O([aa: 1, bb:8])\n";
"new C([aa: 1, bb:8])\n";

int start = contents.lastIndexOf("aa");
int end = start + "aa".length();
assertType(contents, start, end, "java.lang.Boolean");
assertDeclaration(contents, start, end, "O", "aa", DeclarationKind.PROPERTY);
assertDeclaration(contents, start, end, "C", "aa", DeclarationKind.PROPERTY);

start = contents.lastIndexOf("bb");
end = start + "bb".length();
assertType(contents, start, end, "java.lang.Integer");
assertDeclaration(contents, start, end, "O", "bb", DeclarationKind.PROPERTY);
assertDeclaration(contents, start, end, "C", "bb", DeclarationKind.PROPERTY);
}

@Test
public void testConstructor3() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"new O([8: 1, bb:8])\n";
"new C([8: 1, bb:8])\n";

int start = contents.lastIndexOf("bb");
int end = start + "bb".length();
assertType(contents, start, end, "java.lang.Integer");
assertDeclaration(contents, start, end, "O", "bb", DeclarationKind.PROPERTY);
assertDeclaration(contents, start, end, "C", "bb", DeclarationKind.PROPERTY);
}

@Test
public void testConstructor4() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"new O([aa: 1, bb:8], 9)\n";
"new C([aa: 1, bb:8], 9)\n";

int start = contents.lastIndexOf("aa");
int end = start + "aa".length();
Expand All @@ -1036,11 +1036,11 @@ public void testConstructor4() {
@Test
public void testConstructor5() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"new O(9, [aa: 1, bb:8])\n";
"new C(9, [aa: 1, bb:8])\n";

int start = contents.lastIndexOf("aa");
int end = start + "aa".length();
Expand All @@ -1056,11 +1056,11 @@ public void testConstructor5() {
@Test
public void testConstructor6() {
String contents =
"class O {\n" +
"class C {\n" +
" boolean aa\n" +
" int bb\n" +
"}\n" +
"def g = [aa: 1, bb:8]\n";
"def c = C[aa: 1, bb:8]\n";

int start = contents.lastIndexOf("aa");
int end = start + "aa".length();
Expand Down Expand Up @@ -2272,45 +2272,59 @@ public void testInnerClass11() {

@Test
public void testAnonInner1() {
String contents = "def foo = new Object() {}";
String contents = "def aic = new Object() {}";
assertType(contents, "aic", "java.lang.Object");
assertType(contents, "Object", "java.lang.Object");
}

@Test
public void testAnonInner2() {
String contents = "def foo = new Runnable() {\n void run() {}\n}";
assertType(contents, "Runnable", "java.lang.Runnable");
String contents = "def aic = new Cloneable() {}";
assertType(contents, "aic", "java.lang.Cloneable");
assertType(contents, "Cloneable", "java.lang.Cloneable");
}

@Test
@Test // https://github.com/groovy/groovy-eclipse/issues/1523
public void testAnonInner3() {
String contents = "def foo = new Comparable<String>() {\n int compareTo(String that) {}\n}";
assertType(contents, "Comparable", "java.lang.Comparable<java.lang.String>");
for (String mode : new String[] {"TypeChecked", "CompileStatic", "CompileDynamic"}) {
String contents = "@groovy.transform." + mode + " m() {\n" +
" def aic = new Number() {}\n" +
" def cia = new Cloneable() {}\n" +
"}";
assertType(contents, "aic", "java.lang.Number");
assertType(contents, "cia", "java.lang.Cloneable");
}
}

@Test
public void testAnonInner4() {
String contents = "def foo = new Comparable<String>() {\n int compareTo(String that) {\n compareTo('x')\n}\n}";
assertDeclaringType(contents, "compareTo", "Search$1");
String contents = "def aic = new Comparable<String>() {\n int compareTo(String that) {}\n}";
assertType(contents, "Comparable", "java.lang.Comparable<java.lang.String>");
}

@Test
public void testAnonInner5() {
String contents = "def foo = new Comparable<String>() {\n int compareTo(String that) {}\n}\n" +
"foo.compareTo('x')";
assertDeclaringType(contents, "compareTo", "java.lang.Comparable<java.lang.String>");
String contents = "def aic = new Comparable<String>() {\n int compareTo(String that) {\n compareTo('x')\n}\n}";
assertDeclaringType(contents, "compareTo", "Search$1");
}

@Test
public void testAnonInner6() {
String contents = "def foo = new Comparable<Integer>() {\n int compareTo(Integer that) {}\n}\n" +
"foo = new Comparable<String>() {\n int compareTo(String that) {}\n}\n" +
"foo.compareTo('x')";
String contents = "def aic = new Comparable<String>() {\n int compareTo(String that) {}\n}\n" +
"aic.compareTo('x')";
assertDeclaringType(contents, "compareTo", "java.lang.Comparable<java.lang.String>");
}

@Test // https://github.com/groovy/groovy-eclipse/issues/378
@Test
public void testAnonInner7() {
String contents = "def aic = new Comparable<Integer>() {\n int compareTo(Integer that) {}\n}\n" +
"aic = new Comparable<String>() {\n int compareTo(String that) {}\n}\n" +
"aic.compareTo('x')";
assertDeclaringType(contents, "compareTo", "java.lang.Comparable<java.lang.String>");
}

@Test // https://github.com/groovy/groovy-eclipse/issues/378
public void testAnonInner8() {
String contents =
"class A {\n" +
" protected def f\n" +
Expand All @@ -2331,7 +2345,7 @@ public void testAnonInner7() {
}

@Test // https://github.com/groovy/groovy-eclipse/issues/383
public void testAnonInner8() {
public void testAnonInner9() {
String contents =
"class A {\n" +
" protected def m() {}\n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2022 the original author or authors.
* Copyright 2009-2023 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.
Expand Down Expand Up @@ -42,6 +42,7 @@
import org.codehaus.groovy.syntax.Types;
import org.codehaus.groovy.transform.stc.ExtensionMethodNode;
import org.codehaus.groovy.transform.stc.StaticTypesMarker;
import org.eclipse.jdt.groovy.core.util.GroovyUtils;
import org.eclipse.jdt.groovy.search.ITypeLookup;
import org.eclipse.jdt.groovy.search.TypeLookupResult;
import org.eclipse.jdt.groovy.search.TypeLookupResult.TypeConfidence;
Expand Down Expand Up @@ -91,6 +92,15 @@ public TypeLookupResult lookupType(final Expression expr, final VariableScope sc
if (info != null && VariableScope.isParameterizedClosure(info.type)) {
inferredType = info.type; // Closure --> Closure<String>
}
} else if (GroovyUtils.isAnonymous((ClassNode) inferredType)) {
ClassNode type = (ClassNode) inferredType;
// return extended/implemented type for anonymous inner class
if (type.getUnresolvedSuperClass(false) != VariableScope.OBJECT_CLASS_NODE) {
type = type.getUnresolvedSuperClass(false);
} else {
type = type.getUnresolvedInterfaces()[0];
}
inferredType = type;
}
} else {
// defer to other type lookup impls
Expand Down

0 comments on commit aae7a6f

Please sign in to comment.