From 0b347898743d342c8110822f42891a34deb05d2d Mon Sep 17 00:00:00 2001 From: Srikanth Sankaran <131454720+srikanth-sankaran@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:33:45 +0530 Subject: [PATCH] [Sealed types] Duplicate diagnostics for illegal modifier combination (#3101) * Fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3100 --- .../eclipse/jdt/core/compiler/IProblem.java | 4 +++- .../compiler/lookup/SourceTypeBinding.java | 22 +++++++---------- .../compiler/problem/ProblemReporter.java | 9 ------- .../compiler/regression/SealedTypesTests.java | 24 +++++++++++++++---- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java index 3fc0a2bbf8d..6b534474b6f 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java @@ -2538,7 +2538,9 @@ public interface IProblem { int SealedPermittedTypeOutsideOfPackage = TypeRelated + 1859; /** @since 3.28 */ int SealedSealedTypeMissingPermits = TypeRelated + 1860; - /** @since 3.28 */ + /** @since 3.28 + * @deprecated problem no longer generated + */ int SealedInterfaceIsSealedAndNonSealed = TypeRelated + 1861; /** @since 3.28 */ int SealedDisAllowedNonSealedModifierInInterface = TypeRelated + 1862; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 703ce2d7d26..d62f5165843 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -1119,17 +1119,9 @@ private Map.Entry getFirstSealedSuperTypeOrInte } return null; } -// TODO: Optimize the multiple loops - defer until the feature becomes standard. + private void checkPermitsInType() { -// if (/* this.isRecordDeclaration || */this.isEnum()) -// return; // handled separately TypeDeclaration typeDecl = this.scope.referenceContext; - if (this.isInterface()) { - if (isSealed() && isNonSealed()) { - this.scope.problemReporter().sealedInterfaceIsSealedAndNonSealed(this, typeDecl); - return; - } - } boolean hasPermittedTypes = this.permittedTypes != null && this.permittedTypes.length > 0; if (hasPermittedTypes) { if (!this.isSealed()) @@ -1170,11 +1162,13 @@ private void checkPermitsInType() { return; } } else if (this.isNonSealed()) { - if (!foundSealedSuperTypeOrInterface) { - if (this.isClass() && !this.isRecord()) // record to give only illegal modifier error. - this.scope.problemReporter().sealedDisAllowedNonSealedModifierInClass(this, typeDecl); - else if (this.isInterface()) - this.scope.problemReporter().sealedDisAllowedNonSealedModifierInInterface(this, typeDecl); + if (!this.isSealed()) { // lest we bark again. + if (!foundSealedSuperTypeOrInterface) { + if (this.isClass() && !this.isRecord()) // record to give only illegal modifier error. + this.scope.problemReporter().sealedDisAllowedNonSealedModifierInClass(this, typeDecl); + else if (this.isInterface()) + this.scope.problemReporter().sealedDisAllowedNonSealedModifierInInterface(this, typeDecl); + } } } if (foundSealedSuperTypeOrInterface) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 3bb721eb34f..4f2b75af875 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -12397,15 +12397,6 @@ public void sealedSealedTypeMissingPermits(SourceTypeBinding type, ASTNode node) node.sourceEnd); } -public void sealedInterfaceIsSealedAndNonSealed(SourceTypeBinding type, ASTNode node) { - String name = new String(type.sourceName()); - this.handle(IProblem.SealedInterfaceIsSealedAndNonSealed, - new String[] { name }, - new String[] { name }, - node.sourceStart, - node.sourceEnd); -} - public void sealedDisAllowedNonSealedModifierInInterface(SourceTypeBinding type, TypeDeclaration typeDecl) { String name = new String(type.sourceName()); this.handle( diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java index 7089df6ed0f..470cc748475 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java @@ -1071,11 +1071,6 @@ public void testBug563806_032() { " public sealed non-sealed interface X {\n" + " ^\n" + "Sealed class or interface lacks the permits clause and no class or interface from the same compilation unit declares X as its direct superclass or superinterface\n" + - "----------\n" + - "3. ERROR in p1\\X.java (at line 2)\n" + - " public sealed non-sealed interface X {\n" + - " ^\n" + - "An interface X is declared both sealed and non-sealed\n" + "----------\n"); } public void testBug563806_033() { @@ -6400,4 +6395,23 @@ final non-sealed class Y extends X {} "The type Y may have only one modifier out of sealed, non-sealed, and final\n" + "----------\n"); } + + // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3100 + // [Sealed types] Duplicate diagnostics for illegal modifier combination + public void testIssue3100() { + runNegativeTest( + new String[] { + "X.java", + """ + public sealed non-sealed interface X {} + final class Y implements X {} + """ + }, + "----------\n" + + "1. ERROR in X.java (at line 1)\n" + + " public sealed non-sealed interface X {}\n" + + " ^\n" + + "The type X may have only one modifier out of sealed, non-sealed, and final\n" + + "----------\n"); + } }