Skip to content

Commit

Permalink
Fix for #1374: new IntersectionType for multi-catch parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Jun 21, 2022
1 parent 8b3ff02 commit daae628
Show file tree
Hide file tree
Showing 4 changed files with 402 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2395,7 +2395,7 @@ public void testCatchBlock6() {
String contents = "try {\n} catch (Exception | Error e) {\n}\n";

int offset = contents.lastIndexOf("e");
assertType(contents, offset, offset + 1, "java.lang.Throwable");
assertType(contents, offset, offset + 1, "java.lang.Exception or java.lang.Error");
}

private static final String CONTENTS_GETAT1 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,17 @@ public static ClassNode[] getTypeParameterBounds(ClassNode typeParam) {
* @see org.eclipse.jdt.core.Signature
*/
public static String getTypeSignature(ClassNode node, boolean qualified, boolean resolved) {
if (getBaseType(node).getName().startsWith("<UnionType:")) {
ClassNode baseType = getBaseType(node);
if (baseType.getName().startsWith("<UnionType:")) {
return getUnionTypeSignature(node, type -> getTypeSignature(type, qualified, resolved));
}
if (baseType instanceof IntersectionType) {
return getIntersectionTypeSignature(node, type -> getTypeSignature(type, qualified, resolved));
}

String signature = getTypeSignatureWithoutGenerics(node, qualified, resolved);

if (getBaseType(node).getGenericsTypes() != null && !getBaseType(node).isGenericsPlaceHolder()) {
if (baseType.getGenericsTypes() != null && !baseType.isGenericsPlaceHolder()) {
GenericsType[] generics = getGenericsTypes(node);
if (generics.length > 0) {
StringBuilder builder = new StringBuilder(signature);
Expand Down Expand Up @@ -253,9 +257,13 @@ public static String getTypeSignature(ClassNode node, boolean qualified, boolean
}

public static String getTypeSignatureWithoutGenerics(ClassNode node, boolean qualified, boolean resolved) {
if (getBaseType(node).getName().startsWith("<UnionType:")) {
ClassNode baseType = getBaseType(node);
if (baseType.getName().startsWith("<UnionType:")) {
return getUnionTypeSignature(node, type -> getTypeSignatureWithoutGenerics(type, qualified, resolved));
}
if (baseType instanceof IntersectionType) {
return getIntersectionTypeSignature(node, type -> getTypeSignatureWithoutGenerics(type, qualified, resolved));
}

StringBuilder builder = new StringBuilder();
while (node.isArray()) {
Expand Down Expand Up @@ -304,6 +312,19 @@ private static String getUnionTypeSignature(ClassNode node, java.util.function.F
return builder.append(signature).toString();
}

private static String getIntersectionTypeSignature(ClassNode node, java.util.function.Function<ClassNode, String> signer) {
StringBuilder builder = new StringBuilder();
while (node.isArray()) {
builder.append('[');
node = node.getComponentType();
}

Stream<ClassNode> types = ((IntersectionType) node).types.stream();
String signature = Signature.createIntersectionTypeSignature(types.map(signer).toArray(String[]::new));

return builder.append(signature).toString();
}

public static ClassNode getWrapperTypeIfPrimitive(ClassNode type) {
if (type != null && ClassHelper.isPrimitiveType(type) && !ClassHelper.VOID_TYPE.equals(type)) {
return ClassHelper.getWrapper(type);
Expand Down Expand Up @@ -402,6 +423,24 @@ public static Expression getTraitFieldExpression(MethodCallExpression call) {
return null;
}

public static boolean implementsTrait(ClassNode concreteType) {
return concreteType.getNodeMetaData(Traits.class, x -> {
ClassNode type = concreteType.redirect();
do {
if (Traits.isTrait(type) || Arrays.stream(type.getInterfaces()).anyMatch(Traits::isTrait)) {
return Boolean.TRUE;
}
type = type.getSuperClass();
} while (type != null);
return Boolean.FALSE;
}).booleanValue();
}

public static ClassNode intersect(List<ClassNode> types) {
assert types != null && types.size() > 1;
return new IntersectionType(types);
}

public static boolean isAnonymous(ClassNode node) {
if (node instanceof InnerClassNode) {
return ((InnerClassNode) node).isAnonymous();
Expand Down Expand Up @@ -512,19 +551,6 @@ public static boolean isUsingGenerics(MethodNode node) {
return false;
}

public static boolean implementsTrait(ClassNode concreteType) {
return concreteType.getNodeMetaData(Traits.class, x -> {
ClassNode type = concreteType.redirect();
do {
if (Traits.isTrait(type) || Arrays.stream(type.getInterfaces()).anyMatch(Traits::isTrait)) {
return Boolean.TRUE;
}
type = type.getSuperClass();
} while (type != null);
return Boolean.FALSE;
}).booleanValue();
}

public static ClassNode makeType(String typeNameWithoutGenerics) {
int i = typeNameWithoutGenerics.lastIndexOf('[');
if (i < 0) {
Expand All @@ -533,10 +559,9 @@ public static ClassNode makeType(String typeNameWithoutGenerics) {
return makeType(typeNameWithoutGenerics.substring(0, i)).makeArray();
}

public static void updateClosureWithInferredTypes(ClassNode closure, ClassNode returnType, Parameter[] parameters) {
if (!"groovy.lang.Closure".equals(closure.getName()) || closure == closure.redirect()) {
return;
public static void updateClosureWithInferredTypes(ClassNode closureType, ClassNode returnType, Parameter[] parameters) {
if (closureType.getName().equals("groovy.lang.Closure") && closureType.isRedirectNode()) {
closureType.setGenericsTypes(new GenericsType[] {getWrapperTypeIfPrimitive(returnType).asGenericsType()});
}
closure.setGenericsTypes(new GenericsType[] {new GenericsType(getWrapperTypeIfPrimitive(returnType))});
}
}
Loading

0 comments on commit daae628

Please sign in to comment.