diff options
9 files changed, 166 insertions, 16 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index ec3d5029..8fd5b293 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -4,6 +4,7 @@ Lombok Changelog ### v1.18.17 "Edgy Guinea Pig" * BUGFIX: Various tools using ecj under the hood (including intellij) could cause corrupt class files to be generated. [PR #2637](https://github.com/rzwitserloot/lombok/pull/2637), [lombok-intellij-plugin issue #969](https://github.com/mplushnikov/lombok-intellij-plugin/issues/969). * BUGFIX: Netbeans would not work with 1.18.16 anymore. [Issue #2612](https://github.com/rzwitserloot/lombok/issues/2612) +* BUGFIX: `@ExtensionMethod` support in ecj improved when generics are involved. [Issue #2648](https://github.com/rzwitserloot/lombok/issues/2648), [PR #2658](https://github.com/rzwitserloot/lombok/pull/2658) thanks to __@Rawi01__. * PLATFORM: using `lombok.config` files when compiling with sbt 1.4 now works again. [Issue #2645](https://github.com/rzwitserloot/lombok/issues/2645) * (potential) BUGFIX: Using lombok with Maven Tycho now works. With assistance from [Rabea Gransberger](https://github.com/rgra). [Issue #285](https://github.com/rzwitserloot/lombok/issues/285) __UPDATE: This doesn't quite work yet, still investigating.__ @@ -15,6 +16,7 @@ Lombok Changelog * FEATURE: If using `@Synchronized("lockVar")`, if `lockVar` is referring to a static field, the code lombok generates no longer causes a warning about accessing a static entity incorrectly. [Issue #678](https://github.com/rzwitserloot/lombok/issues/678) * FEATURE: `@Jacksonized` on a `@Builder` or `@SuperBuilder` will configure [Jackson](https://github.com/FasterXML/jackson) to use this builder when deserializing. [Pull Request #2387](https://github.com/rzwitserloot/lombok/pull/2387) thanks to __@JanRieke__. [@Jacksonized documentation](https://projectlombok.org/features/experimental/Jacksonized). * FEATURE: The checkerframework support has been updated; the relevant annotations were renamed in checkerframework's APIs, lombok now generates the annotations according to their current API names. +* FEATURE: Add option to cache hashCode via `@EqualsAndHashCode(cacheStrategy = EqualsAndHashCode.CacheStrategy.LAZY)`. [Issue #784](https://github.com/rzwitserloot/lombok/issues/784) [Pull Request #2513](https://github.com/rzwitserloot/lombok/pull/2513) thanks to __@andrebrait__. * PLATFORM: Added support for compiling projects with OpenJ9 [Pull Request #2437](https://github.com/rzwitserloot/lombok/pull/2437) * PLATFORM: Improved support for recent JVM/javac versions (14 and 15) and new language features. * PERFORMANCE: Several performance improvements during parsing/compilation, both using javac and Eclipse. Thanks __@Rawi01__! @@ -128,7 +130,7 @@ Lombok Changelog ### v1.16.22 "Envious Ferret" (May 29th, 2018) * FEATURE: Private no-args constructor for `@Data` and `@Value` to enable deserialization frameworks (like Jackson) to operate out-of-the-box. Use `lombok.noArgsConstructor.extraPrivate = false` to disable this behavior. * FEATURE: Methods can now be marked for inclusion in `toString`, `equals`, and `hashCode` generation. There is a new mechanism to mark which fields (and now, methods) are to be included or excluded for the generation of these methods: mark the relevant member with for example `@ToString.Include` or `@EqualsAndHashCode.Exclude`. [ToString documentation](https://projectlombok.org/features/ToString) [EqualsAndHashCode documentation](https://projectlombok.org/features/EqualsAndHashCode) -* FEATURE: `@Getter` and `@Setter` also allow `onMethod` and `onParam` when put on a type. [Issue #1653](https://github.com/rzwitserloot/lombok/issues/1653) +* FEATURE: `@Getter` and `@Setter` also allow `onMethod` and `onParam` when put on a type. [Issue #1653](https://github.com/rzwitserloot/lombok/issues/1653) * FEATURE: `@FieldNameConstants` is a new feature that generates string constants for your field names. [Docs on @FieldNameConstants](https://projectlombok.org/features/experimental/FieldNameConstants). * PLATFORM: Lombok can be compiled on JDK10, and should run on JDK10. [Issue #1693](https://github.com/rzwitserloot/lombok/issues/1693) * PLATFORM: lombok now counts as an _incremental annotation processor_ for gradle. Should speed up your gradle builds considerably! [Issue #1580](https://github.com/rzwitserloot/lombok/issues/1580) @@ -171,7 +173,7 @@ Lombok Changelog * DEPRECATION: The configuration key `lombok.addGeneratedAnnotation` is now deprecated, use `lombok.addJavaxGeneratedAnnotation` instead. ### v1.16.12 (December 5th, 2016) -* FEATURE: `var` is the mutable sister of `val`. For now experimental, and opt-in using `ALLOW` in the flagUsage configuration key. Thanks for the contribution, Bulgakov Alexander. +* FEATURE: `var` is the mutable sister of `val`. For now experimental, and opt-in using `ALLOW` in the flagUsage configuration key. Thanks for the contribution, Bulgakov Alexander. * CHANGE: `@Value` and `@FieldDefaults` no longer touch static fields [Issue #1254](https://github.com/rzwitserloot/lombok/issues/1254) * BUGFIX: `val` in lambda expressions now work as expected [Issue #911](https://github.com/rzwitserloot/lombok/issues/911) * BUGFIX: `Getter(lazy=true)` now emits an error message when used on a transient field [Issue #1236](https://github.com/rzwitserloot/lombok/issues/1236) diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index b3e8930e..f58de60f 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -174,7 +174,14 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (sbtMappedVirtualFileRootsField == null) return null; String encodedPath = (String) sbtMappedVirtualFilePathField.get(mappedVirtualFile); - if (!encodedPath.startsWith("${")) return null; + if (!encodedPath.startsWith("${")) { + File maybeAbsoluteFile = new File(encodedPath); + if (maybeAbsoluteFile.exists()) { + return maybeAbsoluteFile.toURI(); + } else { + return null; + } + } int idx = encodedPath.indexOf('}'); if (idx == -1) return null; String base = encodedPath.substring(2, idx); diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java index c916ca26..5f229955 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 The Project Lombok Authors. + * Copyright (C) 2012-2020 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 @@ -58,7 +58,6 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; -import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; @@ -304,12 +303,13 @@ public class PatchExtensionMethod { argumentTypes.add(argumentType); } - // Copy generic information. This one covers a few simple cases, more complex cases are still broken - int typeVariables = extensionMethod.typeVariables.length; - if (typeVariables > 0 && methodCall.receiver.resolvedType instanceof ParameterizedTypeBinding) { - ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) methodCall.receiver.resolvedType; - if (parameterizedTypeBinding.arguments != null && parameterizedTypeBinding.arguments.length == typeVariables) { - methodCall.genericTypeArguments = parameterizedTypeBinding.arguments; + if (methodCall.receiver instanceof MessageSend) { + if (Reflection.inferenceContexts != null) { + try { + Permit.set(Reflection.inferenceContexts, methodCall.receiver, null); + } catch (IllegalAccessException ignore) { + // ignore + } } } @@ -402,6 +402,7 @@ public class PatchExtensionMethod { private static final class Reflection { public static final Field argumentTypes = Permit.permissiveGetField(MessageSend.class, "argumentTypes"); public static final Field argumentsHaveErrors = Permit.permissiveGetField(MessageSend.class, "argumentsHaveErrors"); + public static final Field inferenceContexts = Permit.permissiveGetField(MessageSend.class, "inferenceContexts"); private static final Class<?> functionalExpression; private static final Constructor<?> polyTypeBindingConstructor; diff --git a/test/transform/resource/after-delombok/ExtensionMethodFunctional.java b/test/transform/resource/after-delombok/ExtensionMethodFunctional.java index bd301543..fb58eb91 100644 --- a/test/transform/resource/after-delombok/ExtensionMethodFunctional.java +++ b/test/transform/resource/after-delombok/ExtensionMethodFunctional.java @@ -1,5 +1,8 @@ -import java.util.function.Function; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; class ExtensionMethodFunctional { public void test() { @@ -7,6 +10,8 @@ class ExtensionMethodFunctional { test = ExtensionMethodFunctional.Extensions.map(test, s -> ExtensionMethodFunctional.Extensions.reverse(s)); ExtensionMethodFunctional.Extensions.consume(test, s -> System.out.println("1: " + s), s -> System.out.println("2: " + s)); ExtensionMethodFunctional.Extensions.consume(test, System.out::println, System.out::println); + ExtensionMethodFunctional.Extensions.toList(Stream.of("a", "b", "c").map(String::toUpperCase)); + List<Integer> i2 = ExtensionMethodFunctional.Extensions.toList2(Stream.of("a", "b", "c").map(String::toUpperCase)); } static class Extensions { @@ -24,5 +29,13 @@ class ExtensionMethodFunctional { consumer[i].accept(o); } } + + public static <T> List<T> toList(Stream<T> stream) { + return (List<T>) stream.collect(Collectors.toList()); + } + + public static <T, U> List<U> toList2(Stream<T> stream) { + return null; + } } } diff --git a/test/transform/resource/after-delombok/ExtensionMethodGeneric.java b/test/transform/resource/after-delombok/ExtensionMethodGeneric.java new file mode 100644 index 00000000..8559b7ff --- /dev/null +++ b/test/transform/resource/after-delombok/ExtensionMethodGeneric.java @@ -0,0 +1,33 @@ +import java.util.List; +import java.util.Map; + +class ExtensionMethodGeneric { + public void test() { + List<String> stringList = null; + List<Number> numberList = null; + ExtensionMethodGeneric.Extensions.test(stringList); + ExtensionMethodGeneric.Extensions.test(stringList, numberList); + ExtensionMethodGeneric.Extensions.test(ExtensionMethodGeneric.Extensions.test(stringList, stringList), numberList); + Integer i = ExtensionMethodGeneric.Extensions.test2(stringList); + Map<String, Integer> map = null; + List<String> l = ExtensionMethodGeneric.Extensions.test(map, stringList, numberList); + } + + static class Extensions { + public static <T> List<T> test(List<String> obj, List<T> list) { + return null; + } + + public static <K, V> K test(Map<String, Integer> obj, K k, V v) { + return k; + } + + public static <T> T test(List<T> list) { + return null; + } + + public static <T, U> U test2(List<T> list) { + return null; + } + } +} diff --git a/test/transform/resource/after-ecj/ExtensionMethodFunctional.java b/test/transform/resource/after-ecj/ExtensionMethodFunctional.java index 0190eabb..e847c1f0 100644 --- a/test/transform/resource/after-ecj/ExtensionMethodFunctional.java +++ b/test/transform/resource/after-ecj/ExtensionMethodFunctional.java @@ -1,7 +1,10 @@ -import java.util.function.Function; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.experimental.ExtensionMethod; -@ExtensionMethod(ExtensionMethodFunctional.Extensions.class) class ExtensionMethodFunctional { +@ExtensionMethod(value = ExtensionMethodFunctional.Extensions.class,suppressBaseMethods = false) class ExtensionMethodFunctional { static class Extensions { Extensions() { super(); @@ -18,6 +21,12 @@ import lombok.experimental.ExtensionMethod; consumer[i].accept(o); } } + public static <T>List<T> toList(Stream<T> stream) { + return (List<T>) stream.collect(Collectors.toList()); + } + public static <T, U>List<U> toList2(Stream<T> stream) { + return null; + } } ExtensionMethodFunctional() { super(); @@ -27,5 +36,7 @@ import lombok.experimental.ExtensionMethod; test = ExtensionMethodFunctional.Extensions.map(test, (<no type> s) -> ExtensionMethodFunctional.Extensions.reverse(s)); ExtensionMethodFunctional.Extensions.consume(test, (<no type> s) -> System.out.println(("1: " + s)), (<no type> s) -> System.out.println(("2: " + s))); ExtensionMethodFunctional.Extensions.consume(test, System.out::println, System.out::println); + ExtensionMethodFunctional.Extensions.toList(Stream.of("a", "b", "c").map(String::toUpperCase)); + List<Integer> i2 = ExtensionMethodFunctional.Extensions.toList2(Stream.of("a", "b", "c").map(String::toUpperCase)); } } diff --git a/test/transform/resource/after-ecj/ExtensionMethodGeneric.java b/test/transform/resource/after-ecj/ExtensionMethodGeneric.java new file mode 100644 index 00000000..2bfab9cc --- /dev/null +++ b/test/transform/resource/after-ecj/ExtensionMethodGeneric.java @@ -0,0 +1,35 @@ +import java.util.List; +import java.util.Map; +import lombok.experimental.ExtensionMethod; +@ExtensionMethod(ExtensionMethodGeneric.Extensions.class) class ExtensionMethodGeneric { + static class Extensions { + Extensions() { + super(); + } + public static <T>List<T> test(List<String> obj, List<T> list) { + return null; + } + public static <K, V>K test(Map<String, Integer> obj, K k, V v) { + return k; + } + public static <T>T test(List<T> list) { + return null; + } + public static <T, U>U test2(List<T> list) { + return null; + } + } + ExtensionMethodGeneric() { + super(); + } + public void test() { + List<String> stringList = null; + List<Number> numberList = null; + ExtensionMethodGeneric.Extensions.test(stringList); + ExtensionMethodGeneric.Extensions.test(stringList, numberList); + ExtensionMethodGeneric.Extensions.test(ExtensionMethodGeneric.Extensions.test(stringList, stringList), numberList); + Integer i = ExtensionMethodGeneric.Extensions.test2(stringList); + Map<String, Integer> map = null; + List<String> l = ExtensionMethodGeneric.Extensions.test(map, stringList, numberList); + } +}
\ No newline at end of file diff --git a/test/transform/resource/before/ExtensionMethodFunctional.java b/test/transform/resource/before/ExtensionMethodFunctional.java index 19983258..a9e7dd9f 100644 --- a/test/transform/resource/before/ExtensionMethodFunctional.java +++ b/test/transform/resource/before/ExtensionMethodFunctional.java @@ -1,10 +1,13 @@ // version 8: -import java.util.function.Function; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.experimental.ExtensionMethod; -@ExtensionMethod(ExtensionMethodFunctional.Extensions.class) +@ExtensionMethod(value = ExtensionMethodFunctional.Extensions.class, suppressBaseMethods = false) class ExtensionMethodFunctional { public void test() { String test = "test"; @@ -12,6 +15,9 @@ class ExtensionMethodFunctional { test.consume(s -> System.out.println("1: " + s), s -> System.out.println("2: " + s)); test.consume(System.out::println, System.out::println); + + Stream.of("a", "b", "c").map(String::toUpperCase).toList(); + List<Integer> i2 = Stream.of("a", "b", "c").map(String::toUpperCase).toList2(); } static class Extensions { @@ -29,5 +35,13 @@ class ExtensionMethodFunctional { consumer[i].accept(o); } } + + public static <T> List<T> toList(Stream<T> stream) { + return (List<T>) stream.collect(Collectors.toList()); + } + + public static <T, U> List<U> toList2(Stream<T> stream) { + return null; + } } } diff --git a/test/transform/resource/before/ExtensionMethodGeneric.java b/test/transform/resource/before/ExtensionMethodGeneric.java new file mode 100644 index 00000000..d44c663b --- /dev/null +++ b/test/transform/resource/before/ExtensionMethodGeneric.java @@ -0,0 +1,34 @@ +import java.util.List; +import java.util.Map; + +import lombok.experimental.ExtensionMethod; + +@ExtensionMethod(ExtensionMethodGeneric.Extensions.class) +class ExtensionMethodGeneric { + public void test() { + List<String> stringList = null; + List<Number> numberList = null; + stringList.test(); + stringList.test(numberList); + stringList.test(stringList).test(numberList); + Integer i = stringList.test2(); + + Map<String, Integer> map = null; + List<String> l = map.test(stringList, numberList); + } + + static class Extensions { + public static <T> List<T> test(List<String> obj, List<T> list) { + return null; + } + public static <K,V> K test(Map<String, Integer> obj, K k, V v) { + return k; + } + public static <T> T test(List<T> list) { + return null; + } + public static <T,U> U test2(List<T> list) { + return null; + } + } +} |