Skip to content

Commit

Permalink
Fix for DSLD method param/return types involving generics
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Oct 20, 2018
1 parent 8cff1a6 commit b781cbe
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ final class MetaDSLInferencingTests extends DSLInferencingTestSuite {
'''.stripIndent())

int offset = unit.source.lastIndexOf('types')
InferencingTestSuite.assertType(unit, offset, offset + 'types'.length(), 'java.util.Collection<E extends java.lang.Object>')
InferencingTestSuite.assertType(unit, offset, offset + 'types'.length(), 'java.util.Collection')
}

@Test
Expand All @@ -89,7 +89,7 @@ final class MetaDSLInferencingTests extends DSLInferencingTestSuite {
'''.stripIndent())

int offset = unit.source.lastIndexOf('types')
InferencingTestSuite.assertType(unit, offset, offset + 'types'.length(), 'java.util.Collection<E extends java.lang.Object>')
InferencingTestSuite.assertType(unit, offset, offset + 'types'.length(), 'java.util.Collection')
}

@Test
Expand All @@ -101,7 +101,7 @@ final class MetaDSLInferencingTests extends DSLInferencingTestSuite {
'''.stripIndent())

int offset = unit.source.lastIndexOf('annos')
InferencingTestSuite.assertType(unit, offset, offset + 'annos'.length(), 'java.util.Collection<E extends java.lang.Object>')
InferencingTestSuite.assertType(unit, offset, offset + 'annos'.length(), 'java.util.Collection')
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.tools.GenericsUtils;
import org.codehaus.groovy.eclipse.dsl.lookup.ResolverCache;

/**
Expand All @@ -27,29 +26,24 @@ public class ParameterContribution {

final String name;
final String type;
private Parameter cachedParameter;
private Parameter value;

public ParameterContribution(String name, String type) {
this.name = name;
this.type = type;
}

public ParameterContribution(Parameter cachedParameter) {
this.cachedParameter = cachedParameter;
this.name = cachedParameter.getName();
this.type = DSLContributionGroup.getTypeName(cachedParameter.getType());
}

public ParameterContribution(String name) {
this.name = name;
this.type = null;
public ParameterContribution(Parameter value) {
this.value = value;
this.name = value.getName();
this.type = DSLContributionGroup.getTypeName(value.getType());
}

public Parameter toParameter(ResolverCache resolver) {
if (cachedParameter == null) {
cachedParameter = new Parameter(resolver != null ? GenericsUtils.nonGeneric(resolver.resolve(type)) : ClassHelper.DYNAMIC_TYPE, name);
if (value == null) {
value = new Parameter(resolver != null ? resolver.resolve(type) : ClassHelper.DYNAMIC_TYPE, name);
}
return cachedParameter;
return value;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.tools.GenericsUtils;
import org.codehaus.jdt.groovy.internal.compiler.ast.JDTResolver;
import org.eclipse.jdt.groovy.search.VariableScope;

Expand All @@ -33,35 +34,37 @@ public class ResolverCache {

private final Map<String, ClassNode> nameTypeCache;
private final JDTResolver resolver;
public final ModuleNode module;

public ResolverCache(JDTResolver resolver, ModuleNode thisModule) {
public ResolverCache(JDTResolver resolver, ModuleNode module) {
this.nameTypeCache = new WeakHashMap<>();
this.resolver = resolver;
this.module = module;
}

/**
* Resolves a class name to a ClassNode. Using the fully qualified type name,
* or the array type signature for arrays. Can specify type parameters, also
* using fully qualified names.
*/
public ClassNode resolve(String qName) {
if (qName == null || (qName = qName.trim()).isEmpty()) {
public ClassNode resolve(String name) {
if (name == null || (name = name.trim()).isEmpty()) {
return ClassHelper.DYNAMIC_TYPE;
}
if ("void".equals(qName) || "java.lang.Void".equals(qName)) {
if ("void".equals(name) || "java.lang.Void".equals(name)) {
return VariableScope.VOID_CLASS_NODE;
}
ClassNode clazz = nameTypeCache.get(qName);
int arrayCount = 0;
if (clazz == null && resolver != null) {
int typeParamEnd = qName.lastIndexOf('>');
int arrayStart = qName.indexOf('[', typeParamEnd);
ClassNode type = nameTypeCache.get(name);
if (type == null && resolver != null) {
int typeParamEnd = name.lastIndexOf('>');
int arrayStart = name.indexOf('[', typeParamEnd);
String componentName;
int arrayCount = 0;
if (arrayStart > 0) {
componentName = qName.substring(0, arrayStart);
arrayCount = calculateArrayCount(qName, arrayStart);
componentName = name.substring(0, arrayStart);
arrayCount = calculateArrayCount(name, arrayStart);
} else {
componentName = qName;
componentName = name;
}

String erasureName = componentName;
Expand All @@ -72,47 +75,42 @@ public ClassNode resolve(String qName) {
erasureName = componentName.substring(0, typeParamStart);
}
}
clazz = resolver.resolve(erasureName);
if (clazz == null) {
clazz = VariableScope.OBJECT_CLASS_NODE;
type = resolver.resolve(erasureName);
if (type == null) {
type = VariableScope.OBJECT_CLASS_NODE;
}
nameTypeCache.put(erasureName, clazz);
nameTypeCache.put(erasureName, type);

// now recur down through the type parameters
if (typeParamStart > 0) {
// only need to clone if generics are involved
clazz = VariableScope.clone(clazz);

if (typeParamStart > 0 && type.isUsingGenerics()) {
String[] typeParameterNames = componentName.substring(typeParamStart + 1, componentName.length() - 1).split(",");
ClassNode[] typeParameters = new ClassNode[typeParameterNames.length];
ClassNode[] typeParameterTypes = new ClassNode[typeParameterNames.length];
for (int i = 0; i < typeParameterNames.length; i += 1) {
typeParameters[i] = resolve(typeParameterNames[i]);
typeParameterTypes[i] = resolve(typeParameterNames[i]); // TODO: Handle "? extends T" and "? super T"
}
clazz = VariableScope.clone(clazz);
GenericsType[] genericsTypes = clazz.getGenericsTypes();
if (genericsTypes != null) {
// need to be careful here...there may be too many or too few type parameters
for (int i = 0; i < genericsTypes.length && i < typeParameters.length; i += 1) {
genericsTypes[i].setResolved(true);
genericsTypes[i].setWildcard(false);
genericsTypes[i].setPlaceholder(false);
genericsTypes[i].setLowerBound(null);
genericsTypes[i].setUpperBounds(null);
genericsTypes[i].setType(typeParameters[i]);
genericsTypes[i].setName(typeParameters[i].getName());
}
nameTypeCache.put(componentName, clazz);
type = VariableScope.clone(type);
GenericsType[] genericsTypes = type.getGenericsTypes();
// need to be careful here...there may be too many or too few type parameters
for (int i = 0; i < genericsTypes.length && i < typeParameterTypes.length; i += 1) {
genericsTypes[i].setResolved(true);
genericsTypes[i].setWildcard(false);
genericsTypes[i].setLowerBound(null);
genericsTypes[i].setUpperBounds(null);
genericsTypes[i].setPlaceholder(false);
genericsTypes[i].setType(typeParameterTypes[i]);
genericsTypes[i].setName(typeParameterTypes[i].getName());
}
nameTypeCache.put(componentName, type);
}

while (arrayCount > 0) {
arrayCount -= 1;
componentName += "[]";
clazz = clazz.makeArray();
nameTypeCache.put(componentName, clazz);
type = type.makeArray();
nameTypeCache.put(componentName, type);
}
}

return clazz;
return (name.indexOf('<') < 0 ? GenericsUtils.nonGeneric(type) : type);
}

private int calculateArrayCount(String qName, int arrayStart) {
Expand Down

1 comment on commit b781cbe

@eric-milles
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.