diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java index b5905da4203..507ef0cf780 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java @@ -244,7 +244,7 @@ private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) { if (this.annotations != null) rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]); if (typeIsConsistent && currentType.isStatic() - && (qualifyingType.isParameterizedTypeWithActualArguments() || qualifyingType.isGenericType())) { + && (qualifyingType.isParameterizedType() || qualifyingType.isGenericType())) { scope.problemReporter().staticMemberOfParameterizedType(this, currentType, qualifyingType, i); typeIsConsistent = false; qualifyingType = qualifyingType.actualType(); // avoid raw/parameterized enclosing of static member diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java index 776f7d68919..dbf92160ef3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java @@ -139,7 +139,7 @@ protected TypeBinding getTypeBinding(Scope scope) { rejectAnnotationsOnPackageQualifiers(scope, packageBinding); boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; - ReferenceBinding qualifiedType = null; + ReferenceBinding qualifyingType = null; for (int i = typeStart, max = this.tokens.length, last = max-1; i < max; i++) { findNextTypeBinding(i, scope, packageBinding); if (!this.resolvedType.isValidBinding()) @@ -155,34 +155,41 @@ protected TypeBinding getTypeBinding(Scope scope) { if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this)) // must connect hierarchy to find inherited member types return null; ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; - if (qualifiedType != null) { + if (qualifyingType != null) { if (this.annotations != null) { rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]); } + if (currentType.isStatic() && (qualifyingType.isParameterizedType() || qualifyingType.isGenericType())) { + scope.problemReporter().staticMemberOfParameterizedType(this, currentType, qualifyingType, i); + qualifyingType = qualifyingType.actualType(); // avoid raw/parameterized enclosing of static member + } ReferenceBinding enclosingType = currentType.enclosingType(); - if (enclosingType != null && TypeBinding.notEquals(enclosingType.erasure(), qualifiedType.erasure())) { - qualifiedType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype + if (enclosingType != null && TypeBinding.notEquals(enclosingType.erasure(), qualifyingType.erasure())) { + qualifyingType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype } if (currentType.isGenericType()) { - qualifiedType = scope.environment().createRawType(currentType, qualifiedType); + qualifyingType = scope.environment().createRawType(currentType, qualifyingType); } else if (!currentType.hasEnclosingInstanceContext()) { - qualifiedType = currentType; // parameterization of enclosing is irrelevant in this case + qualifyingType = currentType; // parameterization of enclosing is irrelevant in this case } else { - boolean rawQualified = qualifiedType.isRawType(); + boolean rawQualified = qualifyingType.isRawType(); if (rawQualified) { - qualifiedType = scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType); - } else if (qualifiedType.isParameterizedType() && TypeBinding.equalsEquals(qualifiedType.erasure(), currentType.enclosingType().erasure())) { - qualifiedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType); + qualifyingType = scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifyingType); + } else if (qualifyingType.isParameterizedType() && TypeBinding.equalsEquals(qualifyingType.erasure(), currentType.enclosingType().erasure())) { + qualifyingType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifyingType); } else { - qualifiedType = currentType; + qualifyingType = currentType; } } } else { - qualifiedType = currentType.isGenericType() ? (ReferenceBinding)scope.environment().convertToRawType(currentType, false /*do not force conversion of enclosing types*/) : currentType; + qualifyingType = currentType.isGenericType() ? + (ReferenceBinding)scope.environment().convertToRawType(currentType, false /*do not force conversion of enclosing types*/) : + scope.environment().convertToParameterizedType(currentType); + } - recordResolution(scope.environment(), qualifiedType); + recordResolution(scope.environment(), qualifyingType); } - this.resolvedType = qualifiedType; + this.resolvedType = qualifyingType; return this.resolvedType; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java index 7dbaddfb8aa..b106f220556 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java @@ -2034,6 +2034,113 @@ interface MyCallable extends Callable { }); } +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4702 +// ecj ignores error "cannot select a static class from a parameterized type" +public void testIssue4702() { + if (this.complianceLevel < ClassFileConstants.JDK16) + return; + runNegativeTest(new String[] { + "OuterStaticNestedDemo.java", + """ + public class OuterStaticNestedDemo { + class Outer { + static class StaticNested {} + } + + void qualifiedNew(Outer outer) { + new OuterStaticNestedDemo.Outer.StaticNested(); + } + } + """ + }, + "----------\n" + + "1. ERROR in OuterStaticNestedDemo.java (at line 7)\n" + + " new OuterStaticNestedDemo.Outer.StaticNested();\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The member type OuterStaticNestedDemo.Outer.StaticNested cannot be qualified with a parameterized type, since it is static. Remove arguments from qualifying type OuterStaticNestedDemo.Outer\n" + + "----------\n"); +} +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4702 +// ecj ignores error "cannot select a static class from a parameterized type" +public void testIssue4702_1() { + if (this.complianceLevel < ClassFileConstants.JDK16) + return; + runNegativeTest(new String[] { + "OuterStaticNestedDemo.java", + """ + public class OuterStaticNestedDemo { + class Outer { + static class StaticNested {} + } + + void qualifiedNew(Outer outer) { + new Outer.StaticNested(); + } + } + """ + }, + "----------\n" + + "1. ERROR in OuterStaticNestedDemo.java (at line 7)\n" + + " new Outer.StaticNested();\n" + + " ^^^^^^^^^^^^^^^^^^\n" + + "The member type OuterStaticNestedDemo.Outer.StaticNested cannot be qualified with a parameterized type, since it is static. Remove arguments from qualifying type OuterStaticNestedDemo.Outer\n" + + "----------\n"); +} +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4702 +// ecj ignores error "cannot select a static class from a parameterized type" +public void testIssue4702_2() { + if (this.complianceLevel < ClassFileConstants.JDK16) + return; + runNegativeTest(new String[] { + "OuterStaticNestedDemo.java", + """ + class OuterStaticNestedBase { + class Outer { + static class StaticNested {} + } + } + class OuterStaticNestedDemo extends OuterStaticNestedBase { + + + void qualifiedNew(Outer outer) { + new Outer.StaticNested(); + } + } + """ + }, + "----------\n" + + "1. ERROR in OuterStaticNestedDemo.java (at line 10)\n" + + " new Outer.StaticNested();\n" + + " ^^^^^^^^^^^^^^^^^^\n" + + "The member type OuterStaticNestedBase.Outer.StaticNested cannot be qualified with a parameterized type, since it is static. Remove arguments from qualifying type OuterStaticNestedBase.Outer\n" + + "----------\n"); +} +// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4702 +// ecj ignores error "cannot select a static class from a parameterized type" +public void testIssue4702_3() { + if (this.complianceLevel < ClassFileConstants.JDK16) + return; + runNegativeTest(new String[] { + "OuterStaticNestedDemo.java", + """ + public class OuterStaticNestedDemo { + class Outer { + static class StaticNested {} + } + + void qualifiedNew(Outer outer) { + new Outer.StaticNested(); + } + } + """ + }, + "----------\n" + + "1. WARNING in OuterStaticNestedDemo.java (at line 6)\n" + + " void qualifiedNew(Outer outer) {\n" + + " ^^^^^\n" + + "OuterStaticNestedDemo.Outer is a raw type. References to generic type OuterStaticNestedDemo.Outer should be parameterized\n" + + "----------\n"); +} public static Class testClass() { return GenericsRegressionTest_9.class; }