Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvements type inference of type intersections (affects ValLambda.java, ValWeirdTypes.java tests) #2109

Merged
10 changes: 8 additions & 2 deletions src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
Expand Down Expand Up @@ -933,7 +934,12 @@ public static TypeReference makeType(TypeBinding binding, ASTNode pos, boolean a
WildcardBinding wildcard = (WildcardBinding) binding;
if (wildcard.boundKind == Wildcard.EXTENDS) {
if (!allowCompound) {
return makeType(wildcard.bound, pos, false);
TypeBinding bound = wildcard.bound;
boolean isObject = bound.id == TypeIds.T_JavaLangObject;
TypeBinding[] otherBounds = wildcard.otherBounds;
if (isObject && otherBounds != null && otherBounds.length > 0) {
return makeType(otherBounds[0], pos, false);
} else return makeType(bound, pos, false);
} else {
Wildcard out = new Wildcard(Wildcard.EXTENDS);
setGeneratedBy(out, pos);
Expand All @@ -960,7 +966,7 @@ public static TypeReference makeType(TypeBinding binding, ASTNode pos, boolean a
// Finally, add however many nullTypeArgument[] arrays as that are missing, inverse the list, toArray it, and use that as PTR's typeArgument argument.

List<TypeReference[]> params = new ArrayList<TypeReference[]>();
/* Calculate generics */ {
/* Calculate generics */ if(!(binding instanceof RawTypeBinding)) {
TypeBinding b = binding;
while (true) {
boolean isFinalStop = b.isLocalType() || !b.isMemberType() || b.enclosingType() == null;
Expand Down
6 changes: 5 additions & 1 deletion src/core/lombok/javac/JavacResolution.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allow
if (type instanceof ClassType) {
List<Type> ifaces = ((ClassType) type).interfaces_field;
Type supertype = ((ClassType) type).supertype_field;
if (ifaces != null && ifaces.length() == 1) {
if (isObject(supertype) && ifaces != null && ifaces.length() > 0) {
return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid);
}
if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid);
Expand Down Expand Up @@ -402,6 +402,10 @@ private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allow
return genericsToJCTreeNodes(generics, ast, replacement);
}

private static boolean isObject(Type supertype) {
return supertype.tsym.toString().equals("java.lang.Object");
}

private static JCExpression genericsToJCTreeNodes(List<Type> generics, JavacAST ast, JCExpression rawTypeNode) throws TypeNotConvertibleException {
if (generics != null && !generics.isEmpty()) {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
Expand Down
51 changes: 39 additions & 12 deletions src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
* Copyright (C) 2010-2019 The Project Lombok Authors.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -21,8 +21,11 @@
*/
package lombok.eclipse.agent;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
Expand All @@ -44,11 +47,13 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;

import lombok.permit.Permit;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;

import java.lang.reflect.Field;

import static lombok.eclipse.Eclipse.poss;
import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType;
import static org.eclipse.jdt.core.compiler.CategorizedProblem.CAT_TYPE;

public class PatchVal {

Expand Down Expand Up @@ -263,15 +268,11 @@ public static boolean handleValForLocalDeclaration(LocalDeclaration local, Block
resolved = null;
}
if (resolved != null) {
if (resolved.getClass().getSimpleName().startsWith("IntersectionTypeBinding")) {
// We intentionally deconstruct these into simply 'Object', because picking an arbitrary type amongst the intersection feels worse.
} else {
try {
replacement = makeType(resolved, local.type, false);
if (!decomponent) init.resolvedType = replacement.resolveType(scope);
} catch (Exception e) {
// Some type thing failed.
}
try {
replacement = makeType(resolved, local.type, false);
if (!decomponent) init.resolvedType = replacement.resolveType(scope);
} catch (Exception e) {
// Some type thing failed.
}
}
}
Expand Down Expand Up @@ -362,6 +363,32 @@ private static TypeBinding resolveForExpression(Expression collection, BlockScop
} catch (ArrayIndexOutOfBoundsException e) {
// Known cause of issues; for example: val e = mth("X"), where mth takes 2 arguments.
return null;
} catch (AbortCompilation e) {
if (collection instanceof ConditionalExpression) {
ConditionalExpression cexp = (ConditionalExpression) collection;
Expression ifTrue = cexp.valueIfTrue;
Expression ifFalse = cexp.valueIfFalse;
TypeBinding ifTrueResolvedType = ifTrue.resolvedType;
CategorizedProblem problem = e.problem;
if (ifTrueResolvedType != null && ifFalse.resolvedType == null && problem.getCategoryID() == CAT_TYPE) {
CompilationResult compilationResult = e.compilationResult;
CategorizedProblem[] problems = compilationResult.problems;
int problemCount = compilationResult.problemCount;
for (int i = 0; i < problemCount; ++i) {
if (problems[i] == problem) {
problems[i] = null;
if (i + 1 < problemCount) {
System.arraycopy(problems, i + 1, problems, i, problemCount - i + 1);
}
break;
}
}
compilationResult.removeProblem(problem);

return ifTrueResolvedType;
}
}
throw e;
}
}
}
12 changes: 8 additions & 4 deletions test/transform/resource/after-delombok/ValLambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ public void easyLambda() {
};
}
public void easyIntersectionLambda() {
final java.lang.Object foo = (Runnable & java.io.Serializable) () -> {
final java.lang.Runnable foo = (Runnable & java.io.Serializable) () -> {
};
final java.lang.Object bar = (java.io.Serializable & Runnable) () -> {
final java.io.Serializable bar = (java.io.Serializable & Runnable) () -> {
};
}
public void easyLubLambda() {
final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> {
} : (Runnable) System.out::println;
} : System.out::println;
final java.lang.Runnable foo1 = (System.currentTimeMillis() > 0) ? (Runnable) System.out::println : System.out::println;
final java.util.function.Function foo2 = (System.currentTimeMillis() < 0) ? (java.util.function.Function) r -> "" : r -> System.currentTimeMillis();
java.util.function.Function foo3 = (System.currentTimeMillis() < 0) ? (java.util.function.Function) r -> "" : r -> System.currentTimeMillis();
final java.util.function.Function<java.lang.String, java.lang.String> foo4 = (System.currentTimeMillis() < 0) ? (java.util.function.Function<String, String>) r -> "" : r -> String.valueOf(System.currentTimeMillis());
}
// public void castLubLambda() {
// Runnable foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
// lombok.val foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
// }
}
}
10 changes: 8 additions & 2 deletions test/transform/resource/after-delombok/ValWeirdTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ public void testArrays() {
final int singleInt = copy[0];
}
public void arraysAsList() {
final java.util.List<java.lang.Class<? extends java.lang.Object>> x = Arrays.asList(String.class, BigDecimal.class);
for (final java.lang.Class<?> y : x) {
final java.util.List<java.lang.Class<? extends java.io.Serializable>> x = Arrays.asList(String.class, BigDecimal.class);
for (final java.lang.Class<? extends java.io.Serializable> y : x) {
}
}
@SuppressWarnings("all")
public void arraysAsList2() {
final java.util.List<java.lang.Class<? extends java.lang.Comparable>> x = Arrays.asList(String.class, BigDecimal.class, Comparable.class);
for (final java.lang.Class<? extends java.lang.Comparable> y : x) {
}
}
}
10 changes: 7 additions & 3 deletions test/transform/resource/after-ecj/ValLambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ public void easyLambda() {
};
}
public void easyIntersectionLambda() {
final @lombok.val java.lang.Object foo = (Runnable & java.io.Serializable) () -> {
final @lombok.val java.lang.Runnable foo = (Runnable & java.io.Serializable) () -> {
};
final @lombok.val java.lang.Object bar = (java.io.Serializable & Runnable) () -> {
final @lombok.val java.io.Serializable bar = (java.io.Serializable & Runnable) () -> {
};
}
public void easyLubLambda() {
final @lombok.val java.lang.Runnable foo = ((System.currentTimeMillis() > 0) ? (Runnable) () -> {
} : (Runnable) System.out::println);
} : System.out::println);
final @lombok.val java.lang.Runnable foo1 = ((System.currentTimeMillis() > 0) ? (Runnable) System.out::println : System.out::println);
final @lombok.val java.util.function.Function foo2 = ((System.currentTimeMillis() < 0) ? (java.util.function.Function) (<no type> r) -> "" : (<no type> r) -> System.currentTimeMillis());
java.util.function.Function foo3 = ((System.currentTimeMillis() < 0) ? (java.util.function.Function) (<no type> r) -> "" : (<no type> r) -> System.currentTimeMillis());
final @lombok.val java.util.function.Function<java.lang.String, java.lang.String> foo4 = ((System.currentTimeMillis() < 0) ? (java.util.function.Function<String, String>) (<no type> r) -> "" : (<no type> r) -> String.valueOf(System.currentTimeMillis()));
}
}
10 changes: 8 additions & 2 deletions test/transform/resource/after-ecj/ValWeirdTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,14 @@ public void testArrays() {
final @val int singleInt = copy[0];
}
public void arraysAsList() {
final @val java.util.List<java.lang.Class<? extends java.lang.Object>> x = Arrays.asList(String.class, BigDecimal.class);
for (final @val java.lang.Class<? extends java.lang.Object> y : x)
final @val java.util.List<java.lang.Class<? extends java.io.Serializable>> x = Arrays.asList(String.class, BigDecimal.class);
for (final @val java.lang.Class<? extends java.io.Serializable> y : x)
{
}
}
public @SuppressWarnings("all") void arraysAsList2() {
final @val java.util.List<java.lang.Class<? extends java.lang.Comparable>> x = Arrays.asList(String.class, BigDecimal.class, Comparable.class);
for (final @val java.lang.Class<? extends java.lang.Comparable> y : x)
{
}
}
Expand Down
6 changes: 5 additions & 1 deletion test/transform/resource/before/ValLambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ public void easyIntersectionLambda() {
}

public void easyLubLambda() {
lombok.val foo = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : (Runnable)System.out::println;
lombok.val foo = (System.currentTimeMillis() > 0) ? (Runnable)()-> {} : System.out::println;
lombok.val foo1 = (System.currentTimeMillis() > 0) ? (Runnable)System.out::println : System.out::println;
lombok.val foo2 = (System.currentTimeMillis() < 0) ? (java.util.function.Function) r -> "" : r -> System.currentTimeMillis();
java.util.function.Function foo3 = (System.currentTimeMillis() < 0) ? (java.util.function.Function) r -> "" : r -> System.currentTimeMillis();
lombok.val foo4 = (System.currentTimeMillis() < 0) ? (java.util.function.Function<String, String>) r -> "" : r -> String.valueOf(System.currentTimeMillis());
}

// public void castLubLambda() {
Expand Down
8 changes: 8 additions & 0 deletions test/transform/resource/before/ValWeirdTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,12 @@ public void arraysAsList() {

}
}

@SuppressWarnings("all")
public void arraysAsList2() {
val x = Arrays.asList(String.class, BigDecimal.class, Comparable.class);
for (val y : x) {

}
}
}
2 changes: 2 additions & 0 deletions test/transform/resource/messages-ecj/ValLambda.java.messages
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
14 Function is a raw type. References to generic type Function<T,R> should be parameterized
15 Function is a raw type. References to generic type Function<T,R> should be parameterized