Skip to content

Commit 789df42

Browse files
committed
GROOVY-9822
1 parent ee2e716 commit 789df42

File tree

3 files changed

+89
-12
lines changed

3 files changed

+89
-12
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+53
Original file line numberDiff line numberDiff line change
@@ -492,4 +492,57 @@ public void testTypeChecked9803() {
492492

493493
runConformTest(sources, "123");
494494
}
495+
496+
@Test
497+
public void testTypeChecked9822() {
498+
//@formatter:off
499+
String[] sources = {
500+
"Main.groovy",
501+
"@groovy.transform.TypeChecked\n" +
502+
"GraphTraversalSource test(Graph graph) {\n" +
503+
" def strategy = ReadOnlyStrategy.instance()\n" +
504+
" graph.traversal().withStrategies(strategy)\n" +
505+
"}\n",
506+
507+
"Types.java", // from org.apache.tinkerpop:gremlin-core:3.4.8
508+
"@SuppressWarnings(\"rawtypes\")\n" +
509+
"interface TraversalStrategy<S extends TraversalStrategy> extends Comparable<Class<? extends TraversalStrategy>> {\n" +
510+
" interface VerificationStrategy extends TraversalStrategy<VerificationStrategy> {\n" +
511+
" }\n" +
512+
"}\n" +
513+
"@SuppressWarnings(\"rawtypes\")\n" +
514+
"abstract class AbstractTraversalStrategy<S extends TraversalStrategy> implements TraversalStrategy<S> {\n" +
515+
"}\n" +
516+
"abstract\n" + // don't want to implement Comparable
517+
"class ReadOnlyStrategy extends AbstractTraversalStrategy<TraversalStrategy.VerificationStrategy>\n" +
518+
" implements TraversalStrategy.VerificationStrategy {\n" +
519+
" static ReadOnlyStrategy instance() { return null; }\n" +
520+
"}\n" +
521+
"interface TraversalSource extends Cloneable, AutoCloseable {\n" +
522+
" @SuppressWarnings(\"rawtypes\")\n" +
523+
" default TraversalSource withStrategies(TraversalStrategy... strategies) {\n" +
524+
" return null;\n" +
525+
" }\n" +
526+
"}\n" +
527+
"abstract\n" + // don't want to implement AutoCloseable
528+
"class GraphTraversalSource implements TraversalSource {\n" +
529+
" @Override\n" +
530+
" @SuppressWarnings(\"rawtypes\")\n" +
531+
" public GraphTraversalSource withStrategies(TraversalStrategy... strategies) {\n" +
532+
" return (GraphTraversalSource) TraversalSource.super.withStrategies(strategies);\n" +
533+
" }\n" +
534+
"}\n" +
535+
"class Graph {\n" +
536+
" public <C extends TraversalSource> C traversal(Class<C> c) {\n" +
537+
" return null;\n" +
538+
" }\n" +
539+
" public GraphTraversalSource traversal() {\n" +
540+
" return null;\n" +
541+
" }\n" +
542+
"}\n",
543+
};
544+
//@formatter:on
545+
546+
runNegativeTest(sources, "");
547+
}
495548
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+19-9
Original file line numberDiff line numberDiff line change
@@ -1993,9 +1993,7 @@ private static boolean hasNonTrivialBounds(GenericsType gt) {
19931993
}
19941994

19951995
// GRECLIPSE private->package
1996-
static ClassNode[] applyGenericsContext(
1997-
Map<GenericsTypeName, GenericsType> spec, ClassNode[] bounds
1998-
) {
1996+
static ClassNode[] applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final ClassNode[] bounds) {
19991997
if (bounds == null) return null;
20001998
ClassNode[] newBounds = new ClassNode[bounds.length];
20011999
for (int i = 0; i < bounds.length; i++) {
@@ -2004,26 +2002,38 @@ static ClassNode[] applyGenericsContext(
20042002
return newBounds;
20052003
}
20062004

2007-
static ClassNode applyGenericsContext(
2008-
Map<GenericsTypeName, GenericsType> spec, ClassNode bound
2009-
) {
2005+
static ClassNode applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final ClassNode bound) {
2006+
/* GRECLIPSE edit -- GROOVY-9822
20102007
if (bound == null) return null;
2008+
*/
2009+
if (bound == null || !isUsingGenericsOrIsArrayUsingGenerics(bound)) {
2010+
return bound;
2011+
}
2012+
// GRECLIPSE end
20112013
if (bound.isArray()) {
20122014
return applyGenericsContext(spec, bound.getComponentType()).makeArray();
20132015
}
2016+
/* GRECLIPSE edit -- GROOVY-9822
20142017
if (!bound.isUsingGenerics()) return bound;
20152018
ClassNode newBound = bound.getPlainNodeReference();
20162019
newBound.setGenericsTypes(applyGenericsContext(spec, bound.getGenericsTypes()));
2020+
*/
2021+
ClassNode newBound = bound.getPlainNodeReference();
2022+
GenericsType[] gt = bound.getGenericsTypes();
2023+
if (spec != null && !spec.isEmpty()) {
2024+
gt = applyGenericsContext(spec, gt);
2025+
}
2026+
newBound.setGenericsTypes(gt);
2027+
// GRECLIPSE end
20172028
if (bound.isGenericsPlaceHolder()) {
2018-
GenericsType[] gt = newBound.getGenericsTypes();
20192029
boolean hasBounds = hasNonTrivialBounds(gt[0]);
20202030
if (hasBounds || !gt[0].isPlaceholder()) return getCombinedBoundType(gt[0]);
2021-
String placeHolderName = newBound.getGenericsTypes()[0].getName();
2031+
String placeHolderName = gt[0].getName();
20222032
if (!placeHolderName.equals(newBound.getUnresolvedName())) {
20232033
// we should produce a clean placeholder ClassNode here
20242034
ClassNode clean = make(placeHolderName);
2025-
clean.setGenericsTypes(newBound.getGenericsTypes());
20262035
clean.setRedirect(newBound);
2036+
clean.setGenericsTypes(gt);
20272037
newBound = clean;
20282038
}
20292039
newBound.setGenericsPlaceHolder(true);

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+17-3
Original file line numberDiff line numberDiff line change
@@ -1882,23 +1882,37 @@ static ClassNode[] applyGenericsContext(final Map<GenericsTypeName, GenericsType
18821882
}
18831883

18841884
static ClassNode applyGenericsContext(final Map<GenericsTypeName, GenericsType> spec, final ClassNode bound) {
1885+
/* GRECLIPSE edit -- GROOVY-9822
18851886
if (bound == null) return null;
1887+
*/
1888+
if (bound == null || !isUsingGenericsOrIsArrayUsingGenerics(bound)) {
1889+
return bound;
1890+
}
1891+
// GRECLIPSE end
18861892
if (bound.isArray()) {
18871893
return applyGenericsContext(spec, bound.getComponentType()).makeArray();
18881894
}
1895+
/* GRECLIPSE edit -- GROOVY-9822
18891896
if (!bound.isUsingGenerics()) return bound;
18901897
ClassNode newBound = bound.getPlainNodeReference();
18911898
newBound.setGenericsTypes(applyGenericsContext(spec, bound.getGenericsTypes()));
1899+
*/
1900+
ClassNode newBound = bound.getPlainNodeReference();
1901+
GenericsType[] gt = bound.getGenericsTypes();
1902+
if (asBoolean(spec)) {
1903+
gt = applyGenericsContext(spec, gt);
1904+
}
1905+
newBound.setGenericsTypes(gt);
1906+
// GRECLIPSE end
18921907
if (bound.isGenericsPlaceHolder()) {
1893-
GenericsType[] gt = newBound.getGenericsTypes();
18941908
boolean hasBounds = hasNonTrivialBounds(gt[0]);
18951909
if (hasBounds || !gt[0].isPlaceholder()) return getCombinedBoundType(gt[0]);
1896-
String placeHolderName = newBound.getGenericsTypes()[0].getName();
1910+
String placeHolderName = gt[0].getName();
18971911
if (!placeHolderName.equals(newBound.getUnresolvedName())) {
18981912
// we should produce a clean placeholder ClassNode here
18991913
ClassNode clean = make(placeHolderName);
1900-
clean.setGenericsTypes(newBound.getGenericsTypes());
19011914
clean.setRedirect(newBound);
1915+
clean.setGenericsTypes(gt);
19021916
newBound = clean;
19031917
}
19041918
newBound.setGenericsPlaceHolder(true);

0 commit comments

Comments
 (0)