mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-highlighting] IDEA-352187 Support JEP 455: highlighting for instanceof with primitives
GitOrigin-RevId: cbd688d0945b03bffb05af85825c610889383fc4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
882dbec1fb
commit
c8995f3cc8
+11
-4
@@ -206,19 +206,26 @@ public final class HighlightUtil {
|
||||
PsiType checkType = typeElement.getType();
|
||||
PsiType operandType = operand.getType();
|
||||
if (operandType == null) return;
|
||||
if (TypeConversionUtil.isPrimitiveAndNotNull(operandType)
|
||||
|| TypeConversionUtil.isPrimitiveAndNotNull(checkType)
|
||||
|| !TypeConversionUtil.areTypesConvertible(operandType, checkType)) {
|
||||
boolean operandIsPrimitive = TypeConversionUtil.isPrimitiveAndNotNull(operandType);
|
||||
boolean checkIsPrimitive = TypeConversionUtil.isPrimitiveAndNotNull(checkType);
|
||||
boolean convertible = TypeConversionUtil.areTypesConvertible(operandType, checkType);
|
||||
boolean primitiveInPatternsEnabled = JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS.isSufficient(PsiUtil.getLanguageLevel(expression));
|
||||
if (((operandIsPrimitive || checkIsPrimitive) && !primitiveInPatternsEnabled) || !convertible) {
|
||||
String message = JavaErrorBundle.message("inconvertible.type.cast", JavaHighlightUtil.formatType(operandType), JavaHighlightUtil
|
||||
.formatType(checkType));
|
||||
HighlightInfo.Builder info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
|
||||
if (TypeConversionUtil.isPrimitiveAndNotNull(checkType)) {
|
||||
if (checkIsPrimitive) {
|
||||
IntentionAction action = getFixFactory().createReplacePrimitiveWithBoxedTypeAction(operandType, typeElement);
|
||||
if (action != null) {
|
||||
info.registerFix(action, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (((operandIsPrimitive || checkIsPrimitive) && !primitiveInPatternsEnabled) && convertible) {
|
||||
registerIncreaseLanguageLevelFixes(expression, JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, info);
|
||||
}
|
||||
|
||||
errorSink.accept(info);
|
||||
return;
|
||||
}
|
||||
|
||||
+12
-5
@@ -12,6 +12,8 @@ import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.modcommand.ModCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiClassType.ClassResolveResult;
|
||||
import com.intellij.psi.util.*;
|
||||
@@ -66,12 +68,16 @@ final class PatternHighlightingModel {
|
||||
PsiType recordComponentType = recordComponents[i].getType();
|
||||
PsiType substitutedRecordComponentType = substitutor.substitute(recordComponentType);
|
||||
PsiType deconstructionComponentType = JavaPsiPatternUtil.getPatternType(deconstructionComponent);
|
||||
if (!isApplicable(substitutedRecordComponentType, deconstructionComponentType)) {
|
||||
if (!isApplicable(substitutedRecordComponentType, deconstructionComponentType, PsiUtil.getLanguageLevel(deconstructionPattern))) {
|
||||
hasMismatchedPattern = true;
|
||||
if (recordComponents.length == deconstructionComponents.length) {
|
||||
HighlightInfo.Builder
|
||||
builder = HighlightUtil.createIncompatibleTypeHighlightInfo(substitutedRecordComponentType, deconstructionComponentType,
|
||||
deconstructionComponent.getTextRange(), 0);
|
||||
if (isApplicable(substitutedRecordComponentType, deconstructionComponentType,
|
||||
JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS.getMinimumLevel())) {
|
||||
HighlightUtil.registerIncreaseLanguageLevelFixes(deconstructionComponent, JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, builder);
|
||||
}
|
||||
errorSink.accept(builder);
|
||||
reported = true;
|
||||
}
|
||||
@@ -121,8 +127,9 @@ final class PatternHighlightingModel {
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(pattern).descriptionAndTooltip(message);
|
||||
}
|
||||
|
||||
private static boolean isApplicable(@NotNull PsiType recordType, @Nullable PsiType patternType) {
|
||||
if (recordType instanceof PsiPrimitiveType || patternType instanceof PsiPrimitiveType) {
|
||||
private static boolean isApplicable(@NotNull PsiType recordType, @Nullable PsiType patternType, @NotNull LanguageLevel languageLevel) {
|
||||
if ((recordType instanceof PsiPrimitiveType || patternType instanceof PsiPrimitiveType) &&
|
||||
!JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS.isSufficient(languageLevel)) {
|
||||
return recordType.equals(patternType);
|
||||
}
|
||||
return patternType != null && TypeConversionUtil.areTypesConvertible(recordType, patternType);
|
||||
@@ -921,8 +928,8 @@ final class PatternHighlightingModel {
|
||||
}
|
||||
|
||||
static class RecordExhaustivenessResult {
|
||||
private boolean isExhaustive;
|
||||
private boolean canBeAdded;
|
||||
private final boolean isExhaustive;
|
||||
private final boolean canBeAdded;
|
||||
|
||||
final Map<PsiType, Set<List<PsiType>>> missedBranchesByType = new HashMap<>();
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ feature.patterns.in.switch=Patterns in switch
|
||||
feature.javadoc.snippets=@snippet in Javadoc
|
||||
feature.pattern.guard.and.record.patterns=Pattern guards and record patterns
|
||||
feature.record.patterns.in.for.each=Record patterns in for-each loops
|
||||
feature.primitive.types.in.patterns=Primitive types in patterns, instanceof and switch
|
||||
feature.enum.qualified.name.in.switch=Qualified enum as a constant in switch
|
||||
feature.string.templates=String templates
|
||||
feature.unnamed.vars=Unnamed patterns and variables
|
||||
|
||||
@@ -97,6 +97,10 @@ public enum JavaFeature {
|
||||
*/
|
||||
RECORD_PATTERNS_IN_FOR_EACH(LanguageLevel.JDK_X, "feature.record.patterns.in.for.each",
|
||||
LanguageLevel.JDK_20_PREVIEW),
|
||||
/**
|
||||
* Implementation for java 23
|
||||
*/
|
||||
PRIMITIVE_TYPES_IN_PATTERNS(LanguageLevel.JDK_X, "feature.primitive.types.in.patterns"),
|
||||
;
|
||||
|
||||
private final @NotNull LanguageLevel myLevel;
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package dfa;
|
||||
|
||||
public class InstanceofPrimitivesNotAllowed {
|
||||
public static void main(String[] args) {
|
||||
testPrimitiveToPrimitive();
|
||||
testPrimitiveToObject();
|
||||
testObjectToPrimitive();
|
||||
}
|
||||
|
||||
private static void testObjectToPrimitive() {
|
||||
Integer i = 1;
|
||||
Object l = 1;
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'double'">i instanceof double</error>) { //error
|
||||
System.out.println("double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'int'">i instanceof int</error>) { //error
|
||||
System.out.println("int");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'int'">i instanceof int ii</error>) { //error
|
||||
System.out.println("int pattern");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Object' to 'double'">l instanceof double</error>) { //error
|
||||
System.out.println("double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Object' to 'int'">l instanceof int</error>) { //error
|
||||
System.out.println("int");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'java.lang.Object' to 'int'">l instanceof int ii</error>) { //error
|
||||
System.out.println("int pattern");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testPrimitiveToPrimitive() {
|
||||
int i = 1;
|
||||
long l = 1;
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'double'">i instanceof double</error>) { //error
|
||||
System.out.println("double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'int'">i instanceof int</error>) { //error
|
||||
System.out.println("int");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'int'">i instanceof int ii</error>) { //error
|
||||
System.out.println("int pattern");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'double'">l instanceof double</error>) { //error
|
||||
System.out.println("double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'int'">l instanceof int</error>) { //error
|
||||
System.out.println("int");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'int'">l instanceof int ii</error>) { //error
|
||||
System.out.println("int pattern");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testPrimitiveToObject() {
|
||||
int i = 1;
|
||||
long l = 1;
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'java.lang.Double'">i instanceof Double</error>) { //error
|
||||
System.out.println("Double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'java.lang.Integer'">i instanceof Integer</error>) { //error
|
||||
System.out.println("Integer");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'java.lang.Object'">i instanceof Object</error>) { //error
|
||||
System.out.println("Object");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'int' to 'java.lang.Integer'">i instanceof Integer ii</error>) { //error
|
||||
System.out.println("Integer ii");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'java.lang.Double'">l instanceof Double</error>) { //error
|
||||
System.out.println("Double");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'java.lang.Integer'">l instanceof Integer</error>) { //error
|
||||
System.out.println("Integer");
|
||||
}
|
||||
if (<error descr="Inconvertible types; cannot cast 'long' to 'java.lang.Object'">l instanceof Object</error>) { //error
|
||||
System.out.println("Object");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1137
File diff suppressed because it is too large
Load Diff
+1137
File diff suppressed because it is too large
Load Diff
+1068
File diff suppressed because it is too large
Load Diff
+1068
File diff suppressed because it is too large
Load Diff
+9
-1
@@ -103,7 +103,15 @@ public class LightPatternsHighlightingTest extends LightJavaCodeInsightFixtureTe
|
||||
|
||||
public void testUnnamedPatternsUnavailable() {
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_20, this::doTest);
|
||||
}
|
||||
}
|
||||
|
||||
public void testInstanceofPrimitivesNotAllowed() {
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_22, this::doTest);
|
||||
}
|
||||
|
||||
public void testRecordPrimitiveInstanceOfPatternNotAllowed() {
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_22, this::doTest);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight.daemon;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LightPrimitivePatternsHighlightingTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/advHighlightingPatterns";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
//todo change after new Java
|
||||
return JAVA_X;
|
||||
}
|
||||
|
||||
public void testRecordPrimitiveInstanceOfPattern() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimplePrimitiveInstanceOf() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimplePrimitiveInstanceOfPattern() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user