[java-decompiler] IDEA-379703 extends @Nullable Object is not shown in decompiler

GitOrigin-RevId: c2b80cba6397b1924fe1d655e3b1dbd9f36c2fe0
This commit is contained in:
Mikhail Pyltsin
2025-09-26 15:52:01 +00:00
committed by intellij-monorepo-bot
parent b7455f398f
commit dd78faedde
13 changed files with 174 additions and 3 deletions
@@ -25,6 +25,7 @@ jvm_library(
"@lib//:junit4",
"@lib//:assert_j",
"@lib//:jetbrains-annotations",
"@lib//:hamcrest",
]
)
### auto-generated section `build intellij.java.decompiler.engine` end
@@ -12,5 +12,6 @@
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
<orderEntry type="library" name="jetbrains-annotations" level="project" />
<orderEntry type="library" scope="TEST" name="hamcrest" level="project" />
</component>
</module>
@@ -1475,10 +1475,13 @@ public class ClassWriter {
TargetInfo.TypeParameterTarget.extract(typeAnnotations, i).forEach(typeAnnotation -> typeAnnotation.writeTo(buffer));
buffer.append(parameters.get(i));
List<VarType> parameterBounds = bounds.get(i);
if (parameterBounds.size() > 1 || !"java/lang/Object".equals(parameterBounds.get(0).getValue())) {
List<TypeAnnotation> firstTypeAnnotations = TargetInfo.TypeParameterBoundTarget.extract(typeAnnotations, i, 0);
if (parameterBounds.size() > 1 ||
(parameterBounds.size() == 1 && !"java/lang/Object".equals(parameterBounds.getFirst().getValue()) ||
!firstTypeAnnotations.isEmpty())) {
buffer.append(" extends ");
TargetInfo.TypeParameterBoundTarget.extract(typeAnnotations, i, 0).forEach(typeAnnotation -> typeAnnotation.writeTo(buffer));
buffer.append(ExprProcessor.getCastTypeName(parameterBounds.get(0), Collections.emptyList()));
firstTypeAnnotations.forEach(typeAnnotation -> typeAnnotation.writeTo(buffer));
buffer.append(ExprProcessor.getCastTypeName(parameterBounds.getFirst(), Collections.emptyList()));
for (int j = 1; j < parameterBounds.size(); j++) {
buffer.append(" & ");
TargetInfo.TypeParameterBoundTarget.extract(typeAnnotations, i, j).forEach(typeAnnotation -> typeAnnotation.writeTo(buffer));
@@ -264,4 +264,7 @@ public class SingleClassesTest extends SingleClassesTestBase {
"typeAnnotations/A", "typeAnnotations/B", "typeAnnotations/C", "typeAnnotations/D", "typeAnnotations/E",
"typeAnnotations/F", "typeAnnotations/Z", "typeAnnotations/P", "typeAnnotations/S", "typeAnnotations/T");
}
@Test public void testAnnotationExtendObjectStaticMethods() { doTest("pkg/TestAnnotationExtendObjectStaticMethods"); }
@Test public void testAnnotationExtendObjectClass() { doTest("pkg/TestAnnotationExtendObjectClass"); }
@Test public void testAnnotationExtendWildcard() { doTest("pkg/TestAnnotationExtendWildcard"); }
}
@@ -0,0 +1,17 @@
package org.example;
import org.jetbrains.annotations.Nullable;
public class TestAnnotationExtendObjectClass<T extends @Nullable Object, L extends @Nullable String, M> {
public static void main(String[] args) {
}// 8
}
class 'org/example/TestAnnotationExtendObjectClass' {
method 'main ([Ljava/lang/String;)V' {
0 6
}
}
Lines mapping:
8 <-> 7
@@ -0,0 +1,25 @@
package org.example;
import org.jetbrains.annotations.Nullable;
public class TestAnnotationExtendObjectStaticMethods {
public static void main(String[] args) {
}// 8
public static native <T extends @Nullable Object> Iterable<T> concat(Iterable<? extends T> var0, Iterable<? extends T> var1);
public static native <T extends @Nullable String> Iterable<T> concat2(Iterable<? extends T> var0, Iterable<? extends T> var1);
public static native <T extends String> Iterable<T> concat3(Iterable<? extends T> var0, Iterable<? extends T> var1);
public static native <T> Iterable<T> concat4(Iterable<? extends T> var0, Iterable<? extends T> var1);
}
class 'org/example/TestAnnotationExtendObjectStaticMethods' {
method 'main ([Ljava/lang/String;)V' {
0 6
}
}
Lines mapping:
8 <-> 7
@@ -0,0 +1,68 @@
package org.example;
import java.util.List;
import org.jetbrains.annotations.Nullable;
public class TestAnnotationExtendWildcard {
public static void main(String[] args) {
}// 10
List<? extends Object> getA() {
return null;// 13
}
List<?> getA5() {
return null;// 17
}
List<? extends String> getA3() {
return null;// 21
}
List<? extends @Nullable Object> getA2() {
return null;// 25
}
List<? extends @Nullable String> getA4() {
return null;// 29
}
}
class 'org/example/TestAnnotationExtendWildcard' {
method 'main ([Ljava/lang/String;)V' {
0 7
}
method 'getA ()Ljava/util/List;' {
0 10
1 10
}
method 'getA5 ()Ljava/util/List;' {
0 14
1 14
}
method 'getA3 ()Ljava/util/List;' {
0 18
1 18
}
method 'getA2 ()Ljava/util/List;' {
0 22
1 22
}
method 'getA4 ()Ljava/util/List;' {
0 26
1 26
}
}
Lines mapping:
10 <-> 8
13 <-> 11
17 <-> 15
21 <-> 19
25 <-> 23
29 <-> 27
@@ -0,0 +1,9 @@
package org.example;
import org.jetbrains.annotations.Nullable;
public class TestAnnotationExtendObjectClass<T extends @Nullable Object, L extends @Nullable String, M> {
public static void main(String[] args) {
}
}
@@ -0,0 +1,13 @@
package org.example;
import org.jetbrains.annotations.Nullable;
public class TestAnnotationExtendObjectStaticMethods {
public static void main(String[] args) {
}
public static native <T extends @Nullable Object> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b);
public static native <T extends @Nullable String> Iterable<T> concat2(Iterable<? extends T> a, Iterable<? extends T> b);
public static native <T extends String> Iterable<T> concat3(Iterable<? extends T> a, Iterable<? extends T> b);
public static native <T extends Object> Iterable<T> concat4(Iterable<? extends T> a, Iterable<? extends T> b);
}
@@ -0,0 +1,31 @@
package org.example;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class TestAnnotationExtendWildcard {
public static void main(String[] args) {
}
List<? extends Object> getA() {
return null;
}
List<?> getA5() {
return null;
}
List<? extends String> getA3() {
return null;
}
List<? extends @Nullable Object> getA2() {
return null;
}
List<? extends @Nullable String> getA4() {
return null;
}
}