[jira] [Commented] (GROOVY-9059) Failed to parse/compile generic methods with "extends"
[ https://issues.apache.org/jira/browse/GROOVY-9059?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16901316#comment-16901316 ] Eric Milles commented on GROOVY-9059: - Taking another look at this, it appears that {{GenericsUtils.addMethodGenerics}} is where the information loss occurs for groovyc. {code:java} public static Map addMethodGenerics(MethodNode current, Map oldSpec) { Map ret = new HashMap(oldSpec); // ret starts with the original type specs, now add gts for the current method if any GenericsType[] sgts = current.getGenericsTypes(); if (sgts != null) { for (GenericsType sgt : sgts) { String name = sgt.getName(); if (sgt.isPlaceholder()) { ClassNode redirect; if (sgt.getUpperBounds() != null) { redirect = sgt.getUpperBounds()[0]; } else if (sgt.getLowerBound() != null) { redirect = sgt.getLowerBound(); } else { redirect = ClassHelper.OBJECT_TYPE; } ClassNode type = ClassHelper.makeWithoutCaching(name); type.setGenericsPlaceHolder(true); // type is "O" and redirect is "T -> Object" type.setRedirect(redirect); // after this, type is "O -> Object"; "T" has been lost ret.put(name, type); } else { ret.put(name, sgt.getType()); } } } return ret; } {code} For the {{correctToGenericsSpec}} calls to work after this, "T" must be retained in the redirect of "O". > Failed to parse/compile generic methods with "extends" > -- > > Key: GROOVY-9059 > URL: https://issues.apache.org/jira/browse/GROOVY-9059 > Project: Groovy > Issue Type: Bug > Components: Static compilation >Affects Versions: 2.4.16, 3.0.0-alpha-4, 2.5.6 >Reporter: Xiaoguang Wang >Priority: Major > Attachments: image-2019-03-30-13-10-20-819.png > > > > {code:java} > import groovy.transform.CompileStatic > // This bug affects: groovy-2.4.16, groovy-2.5.6, groovy-3.0.0-alpha-4 > // This bug also affect IDEA's syntax parser > interface X { > // Intellij IDEA reports that 'public' is not necessary > // BUT without the 'public' modifier, there is a syntax error > public T foo(T o); > } > interface Y { > public O foo(O o); > } > @CompileStatic > class TestGroovyGeneric { > static void main(String[] args) { > def x = new X() { > // it compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not > implemented > @Override > String foo(String o) { return o } > } > // Strangely, such code compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not implemented > def y1 = new Y() { > @Override > public String foo(String o) { return o } > } > // Can not compile: > // BUT: Intellij IDEA reports no error > def y2 = new Y() { > @Override > String foo(String o) { return o } > } > } > } > {code} > !image-2019-03-30-13-10-20-819.png! > -- This message was sent by Atlassian JIRA (v7.6.14#76016)
[jira] [Commented] (GROOVY-9059) Failed to parse/compile generic methods with "extends"
[ https://issues.apache.org/jira/browse/GROOVY-9059?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16822125#comment-16822125 ] Eric Milles commented on GROOVY-9059: - So by including the generics of {{oldMethod}}, {{equalParametersWithGenerics}} can get from {{O -> Object}} to {{O -> T -> Object}}. Since {{genericsSpec}} is only used to convert types from {{oldMethod}}, I removed the existing call {{addMethodGenerics(overridingMethod, genericsSpec)}}. {code:java} // org.codehaus.groovy.classgen.Verifier private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, boolean ignoreError) { // method name if (!oldMethod.getName().equals(overridingMethod.getName())) return null; if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null; if (oldMethod.isPrivate()) return null; // GRECLIPSE add -- GROOVY-9059 genericsSpec = GenericsUtils.addMethodGenerics(oldMethod, genericsSpec); // GRECLIPSE end // parameters boolean normalEqualParameters = equalParametersNormal(overridingMethod, oldMethod); boolean genericEqualParameters = equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec); if (!normalEqualParameters && !genericEqualParameters) return null; /* GRECLIPSE edit -- GROOVY-9059 //correct to method level generics for the overriding method genericsSpec = GenericsUtils.addMethodGenerics(overridingMethod, genericsSpec); */ // return type ClassNode mr = overridingMethod.getReturnType(); ClassNode omr = oldMethod.getReturnType(); boolean equalReturnType = mr.equals(omr); ClassNode testmr = correctToGenericsSpec(genericsSpec, omr); {code} >From there, it needs some help to use the entry {{T=T->java.lang.String}} from >{{genericsSpec}}. I did it using a special method from ClassNode that was >introduced for a previous fix: {code:java} // org.codehaus.groovy.ast.tools.GenericsUtils public static ClassNode correctToGenericsSpec(Map genericsSpec, ClassNode type) { if (type.isArray()) { return correctToGenericsSpec(genericsSpec, type.getComponentType()).makeArray(); } if (type.isGenericsPlaceHolder()) { String name = type.getGenericsTypes()[0].getName(); type = genericsSpec.get(name); // GRECLIPSE add -- GROOVY-9059 if (type != null && type.isGenericsPlaceHolder()) { type = type.asGenericsType().getUpperBounds()[0]; return correctToGenericsSpec(genericsSpec, type); } // GRECLIPSE end } if (type == null) type = ClassHelper.OBJECT_TYPE; return type; } {code} {code:java} // org.codehaus.groovy.ast.ClassNode public GenericsType asGenericsType() { if (!isGenericsPlaceHolder()) { return new GenericsType(this); } else { ClassNode upper = (redirect != null ? redirect : this); return new GenericsType(this, new ClassNode[]{upper}, null); } } {code} With that in place, you can do this without error: {code:groovy} class Why implements Y { @Override public CS foo(CS s) { s } } // or def why = new Y() { @Override public CS foo(CS s) { s } } {code} However, your example of using String and no method generics still produces 1 errors (from groovyc) and 1 warning (from eclipse): 1. Method 'foo' from class 'Bar$1' does not override method from its superclass or interfaces but is annotated with @Override. 2. The return type String for foo(String) from the type new Y(){} needs unchecked conversion to conform to O from the type Y > Failed to parse/compile generic methods with "extends" > -- > > Key: GROOVY-9059 > URL: https://issues.apache.org/jira/browse/GROOVY-9059 > Project: Groovy > Issue Type: Bug > Components: Static compilation >Affects Versions: 2.4.16, 3.0.0-alpha-4, 2.5.6 >Reporter: Xiaoguang Wang >Priority: Major > Attachments: image-2019-03-30-13-10-20-819.png > > > > {code:java} > import groovy.transform.CompileStatic > // This bug affects: groovy-2.4.16, groovy-2.5.6, groovy-3.0.0-alpha-4 > // This bug also affect IDEA's syntax parser > interface X { > // Intellij IDEA reports that 'public' is not necessary > // BUT without the 'public' modifier, there is a syntax error > public T foo(T o); > } > interface Y { > public O foo(O o); > } > @CompileStatic > class TestGroovyGeneric { > static void main(String[] args) { > def x = new X() { > // it compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not > implemented >
[jira] [Commented] (GROOVY-9059) Failed to parse/compile generic methods with "extends"
[ https://issues.apache.org/jira/browse/GROOVY-9059?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16822059#comment-16822059 ] Eric Milles commented on GROOVY-9059: - {code:java} private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, boolean ignoreError) { // method name if (!oldMethod.getName().equals(overridingMethod.getName())) return null; if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null; if (oldMethod.isPrivate()) return null; // GRECLIPSE add -- GROOVY-9059 genericsSpec = GenericsUtils.addMethodGenerics(overridingMethod, genericsSpec); // GRECLIPSE end // parameters boolean normalEqualParameters = equalParametersNormal(overridingMethod, oldMethod); boolean genericEqualParameters = equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec); if (!normalEqualParameters && !genericEqualParameters) return null; /* GRECLIPSE edit -- GROOVY-9059 //correct to method level generics for the overriding method genericsSpec = GenericsUtils.addMethodGenerics(overridingMethod, genericsSpec); */ {code} > Failed to parse/compile generic methods with "extends" > -- > > Key: GROOVY-9059 > URL: https://issues.apache.org/jira/browse/GROOVY-9059 > Project: Groovy > Issue Type: Bug > Components: Static compilation >Affects Versions: 2.4.16, 3.0.0-alpha-4, 2.5.6 >Reporter: Xiaoguang Wang >Priority: Major > Attachments: image-2019-03-30-13-10-20-819.png > > > > {code:java} > import groovy.transform.CompileStatic > // This bug affects: groovy-2.4.16, groovy-2.5.6, groovy-3.0.0-alpha-4 > // This bug also affect IDEA's syntax parser > interface X { > // Intellij IDEA reports that 'public' is not necessary > // BUT without the 'public' modifier, there is a syntax error > public T foo(T o); > } > interface Y { > public O foo(O o); > } > @CompileStatic > class TestGroovyGeneric { > static void main(String[] args) { > def x = new X() { > // it compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not > implemented > @Override > String foo(String o) { return o } > } > // Strangely, such code compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not implemented > def y1 = new Y() { > @Override > public String foo(String o) { return o } > } > // Can not compile: > // BUT: Intellij IDEA reports no error > def y2 = new Y() { > @Override > String foo(String o) { return o } > } > } > } > {code} > !image-2019-03-30-13-10-20-819.png! > -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-9059) Failed to parse/compile generic methods with "extends"
[ https://issues.apache.org/jira/browse/GROOVY-9059?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16822054#comment-16822054 ] Eric Milles commented on GROOVY-9059: - Just after this, the method generics spec is loaded: {code} genericsSpec = GenericsUtils.addMethodGenerics(overridingMethod, genericsSpec); {code} This is probably needed to correctly determine covariance. > Failed to parse/compile generic methods with "extends" > -- > > Key: GROOVY-9059 > URL: https://issues.apache.org/jira/browse/GROOVY-9059 > Project: Groovy > Issue Type: Bug > Components: Static compilation >Affects Versions: 2.4.16, 3.0.0-alpha-4, 2.5.6 >Reporter: Xiaoguang Wang >Priority: Major > Attachments: image-2019-03-30-13-10-20-819.png > > > > {code:java} > import groovy.transform.CompileStatic > // This bug affects: groovy-2.4.16, groovy-2.5.6, groovy-3.0.0-alpha-4 > // This bug also affect IDEA's syntax parser > interface X { > // Intellij IDEA reports that 'public' is not necessary > // BUT without the 'public' modifier, there is a syntax error > public T foo(T o); > } > interface Y { > public O foo(O o); > } > @CompileStatic > class TestGroovyGeneric { > static void main(String[] args) { > def x = new X() { > // it compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not > implemented > @Override > String foo(String o) { return o } > } > // Strangely, such code compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not implemented > def y1 = new Y() { > @Override > public String foo(String o) { return o } > } > // Can not compile: > // BUT: Intellij IDEA reports no error > def y2 = new Y() { > @Override > String foo(String o) { return o } > } > } > } > {code} > !image-2019-03-30-13-10-20-819.png! > -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (GROOVY-9059) Failed to parse/compile generic methods with "extends"
[ https://issues.apache.org/jira/browse/GROOVY-9059?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16822042#comment-16822042 ] Eric Milles commented on GROOVY-9059: - This last line in {{Verifier.getCovariantImplementation}} fails to identify the link between {{String foo(String o)}} in the impl and {{ O foo(O o)}} in the interface. And so, without the covariant method, the abstract method errors are produced. {code:java} private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, boolean ignoreError) { // method name if (!oldMethod.getName().equals(overridingMethod.getName())) return null; if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null; if (oldMethod.isPrivate()) return null; // parameters boolean normalEqualParameters = equalParametersNormal(overridingMethod, oldMethod); boolean genericEqualParameters = equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec); {code} > Failed to parse/compile generic methods with "extends" > -- > > Key: GROOVY-9059 > URL: https://issues.apache.org/jira/browse/GROOVY-9059 > Project: Groovy > Issue Type: Bug > Components: Static compilation >Affects Versions: 2.4.16, 3.0.0-alpha-4, 2.5.6 >Reporter: Xiaoguang Wang >Priority: Major > Attachments: image-2019-03-30-13-10-20-819.png > > > > {code:java} > import groovy.transform.CompileStatic > // This bug affects: groovy-2.4.16, groovy-2.5.6, groovy-3.0.0-alpha-4 > // This bug also affect IDEA's syntax parser > interface X { > // Intellij IDEA reports that 'public' is not necessary > // BUT without the 'public' modifier, there is a syntax error > public T foo(T o); > } > interface Y { > public O foo(O o); > } > @CompileStatic > class TestGroovyGeneric { > static void main(String[] args) { > def x = new X() { > // it compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not > implemented > @Override > String foo(String o) { return o } > } > // Strangely, such code compiles > // BUT: Intellij IDEA reports: ERROR: Method 'foo' is not implemented > def y1 = new Y() { > @Override > public String foo(String o) { return o } > } > // Can not compile: > // BUT: Intellij IDEA reports no error > def y2 = new Y() { > @Override > String foo(String o) { return o } > } > } > } > {code} > !image-2019-03-30-13-10-20-819.png! > -- This message was sent by Atlassian JIRA (v7.6.3#76005)