Sealed classes: restricted keyword/identifier -> contextual keyword (IDEA-257414)

GitOrigin-RevId: a3b7cb3c6eb3a65f78cf473fb93ddfa9946dea38
This commit is contained in:
Artemiy Sartakov
2021-01-19 15:02:29 +07:00
committed by intellij-monorepo-bot
parent 66ab33ff7c
commit 45d71a0820
11 changed files with 23 additions and 24 deletions

View File

@@ -42,7 +42,6 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.util.JavaPsiConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
@@ -312,11 +311,11 @@ public final class HighlightClassUtil {
firstChild.getText().startsWith("#!");
}
static HighlightInfo checkClassRestrictedKeyword(@NotNull LanguageLevel level, @NotNull PsiIdentifier identifier) {
static HighlightInfo checkClassContextualKeyword(@NotNull LanguageLevel level, @NotNull PsiIdentifier identifier) {
String className = identifier.getText();
if (isRestrictedIdentifier(className, level)) {
if (isContextualKeyword(className, level)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.descriptionAndTooltip(JavaErrorBundle.message("restricted.identifier", className))
.descriptionAndTooltip(JavaErrorBundle.message("contextual.keyword", className))
.range(identifier)
.create();
}
@@ -328,7 +327,7 @@ public final class HighlightClassUtil {
* @param level language level
* @return true if given name cannot be used as a type name at given language level
*/
public static boolean isRestrictedIdentifier(String typeName, @NotNull LanguageLevel level) {
public static boolean isContextualKeyword(String typeName, @NotNull LanguageLevel level) {
return PsiKeyword.VAR.equals(typeName) && HighlightingFeature.LVTI.isSufficient(level) ||
PsiKeyword.YIELD.equals(typeName) && HighlightingFeature.SWITCH_EXPRESSION.isSufficient(level) ||
PsiKeyword.RECORD.equals(typeName) && HighlightingFeature.RECORDS.isSufficient(level) ||

View File

@@ -423,12 +423,12 @@ public final class HighlightUtil {
return highlightInfo;
}
static HighlightInfo checkRestrictedIdentifierReference(@NotNull PsiJavaCodeReferenceElement ref,
@NotNull PsiClass resolved,
@NotNull LanguageLevel languageLevel) {
static HighlightInfo checkContextualKeywordReference(@NotNull PsiJavaCodeReferenceElement ref,
@NotNull PsiClass resolved,
@NotNull LanguageLevel languageLevel) {
String name = resolved.getName();
if (HighlightClassUtil.isRestrictedIdentifier(name, languageLevel)) {
String message = JavaErrorBundle.message("restricted.identifier.reference", name);
if (HighlightClassUtil.isContextualKeyword(name, languageLevel)) {
String message = JavaErrorBundle.message("contextual.keyword.reference", name);
PsiElement range = ObjectUtils.notNull(ref.getReferenceNameElement(), ref);
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(range).create();
}

View File

@@ -730,7 +730,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(HighlightNamesUtil.highlightClassName(aClass, identifier, colorsScheme));
}
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightClassUtil.checkClassRestrictedKeyword(myLanguageLevel, identifier));
myHolder.add(HighlightClassUtil.checkClassContextualKeyword(myLanguageLevel, identifier));
}
if (!myHolder.hasErrorResults() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
myHolder.add(GenericsHighlightUtil.checkUnrelatedDefaultMethods(aClass, identifier));
@@ -1317,7 +1317,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(HighlightUtil.checkPackageAndClassConflict(ref, myFile));
}
if (!myHolder.hasErrorResults() && resolved instanceof PsiClass) {
myHolder.add(HighlightUtil.checkRestrictedIdentifierReference(ref, (PsiClass)resolved, myLanguageLevel));
myHolder.add(HighlightUtil.checkContextualKeywordReference(ref, (PsiClass)resolved, myLanguageLevel));
}
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(ref, resolved, myFile, myInsideConstructorOfClass));

View File

@@ -62,8 +62,8 @@ public class CreateClassAction extends JavaCreateTemplateInPackageAction<PsiClas
return JavaErrorBundle.message("create.class.action.this.not.valid.java.qualified.name");
}
String shortName = StringUtil.getShortName(inputString);
if (HighlightClassUtil.isRestrictedIdentifier(shortName, level)) {
return JavaErrorBundle.message("restricted.identifier", shortName);
if (HighlightClassUtil.isContextualKeyword(shortName, level)) {
return JavaErrorBundle.message("contextual.keyword", shortName);
}
return null;
}

View File

@@ -25,6 +25,6 @@ public class JavaTypeRenameValidator implements RenameInputValidator {
Project project = element.getProject();
LanguageLevel level = PsiUtil.getLanguageLevel(element);
return PsiNameHelper.getInstance(project).isIdentifier(newName, level) &&
!HighlightClassUtil.isRestrictedIdentifier(newName, level);
!HighlightClassUtil.isContextualKeyword(newName, level);
}
}

View File

@@ -3,7 +3,7 @@
Reports the Java code constructs that may fail to compile in future Java versions. The following problems are reported:
<ul>
<li>Use of 'assert', 'enum' or '_' as an identifier</li>
<li>Use of restricted keyword 'var' as a type name</li>
<li>Use of contextual keyword 'var' as a type name</li>
<li>Unqualified calls to method named 'yield'</li>
<li>Modifiers on 'requires java.base' statement inside module-info.java</li>
</ul>

View File

@@ -411,8 +411,8 @@ module.access.does.not.read=Package ''{0}'' is declared in module ''{1}'', but m
module.access.not.in.graph=Package ''{0}'' is declared in module ''{1}'', which is not in the module graph
module.access.bad.name=Package ''{0}'' is declared in module with an invalid name (''{1}'')
restricted.identifier=''{0}'' is a restricted identifier and cannot be used for type declarations
restricted.identifier.reference=Illegal reference to restricted type ''{0}''
contextual.keyword=''{0}'' is a contextual keyword and cannot be used for type declarations
contextual.keyword.reference=Illegal reference to restricted type ''{0}''
lvti.no.initializer=Cannot infer type: 'var' on variable without initializer
lvti.lambda=Cannot infer type: lambda expression requires an explicit target type

View File

@@ -1,6 +1,6 @@
import java.lang.annotation.*;
class <error descr="'record' is a restricted identifier and cannot be used for type declarations">record</error> {
class <error descr="'record' is a contextual keyword and cannot be used for type declarations">record</error> {
void x(<error descr="Illegal reference to restricted type 'record'">record</error> r) {}
}
record <error descr="Record has no header declared">NoComponentList</error> {}

View File

@@ -1,2 +1,2 @@
class <error descr="'sealed' is a restricted identifier and cannot be used for type declarations">sealed</error> {}
class <error descr="'permits' is a restricted identifier and cannot be used for type declarations">permits</error> {}
class <error descr="'sealed' is a contextual keyword and cannot be used for type declarations">sealed</error> {}
class <error descr="'permits' is a contextual keyword and cannot be used for type declarations">permits</error> {}

View File

@@ -1,7 +1,7 @@
class Main {
class <error descr="'var' is a restricted identifier and cannot be used for type declarations">var</error> {}
class <error descr="'var' is a contextual keyword and cannot be used for type declarations">var</error> {}
<<error descr="'var' is a restricted identifier and cannot be used for type declarations">var</error> extends String> void foo() {}
<<error descr="'var' is a contextual keyword and cannot be used for type declarations">var</error> extends String> void foo() {}
class Usage {
<error descr="Illegal reference to restricted type 'var'">var</error> field = new <error descr="Illegal reference to restricted type 'var'">var</error>();

View File

@@ -48,7 +48,7 @@ class YieldStatements {
}
}
class <error descr="'yield' is a restricted identifier and cannot be used for type declarations">yield</error> {
class <error descr="'yield' is a contextual keyword and cannot be used for type declarations">yield</error> {
void test(<error descr="Illegal reference to restricted type 'yield'">yield</error> yield) {
}