mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-highlighting] checkVariableExpected; yield checks migrated
Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: e4261df8c429a46d6aa238b7dcb4a97fdc45f9eb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d50a093e84
commit
2b4707f2ef
@@ -212,6 +212,9 @@ break.out.of.switch.expression=Break out of switch expression is not allowed
|
||||
continue.outside.loop='continue' statement outside of loop
|
||||
continue.out.of.switch.expression=Continue out of switch expression is not allowed
|
||||
|
||||
yield.unexpected='yield' outside of a switch expression
|
||||
yield.void=Expression type should not be 'void'
|
||||
|
||||
foreach.not.applicable=Foreach not applicable to type ''{0}''
|
||||
|
||||
new.expression.qualified.malformed=Invalid qualified new
|
||||
@@ -322,6 +325,7 @@ expression.super.unqualified.default.method=Unqualified super reference is not a
|
||||
expression.qualified.class.expected=Class name expected here
|
||||
|
||||
assignment.declared.outside.guard=Cannot assign a value to variable ''{0}'', because it is declared outside the guard
|
||||
lvalue.variable.expected=Variable expected
|
||||
|
||||
binary.operator.not.applicable=Operator ''{0}'' cannot be applied to ''{1}'', ''{2}''
|
||||
unary.operator.not.applicable=Operator ''{0}'' cannot be applied to ''{1}''
|
||||
|
||||
+19
@@ -707,6 +707,25 @@ final class ExpressionChecker {
|
||||
}
|
||||
}
|
||||
|
||||
void checkVariableExpected(@NotNull PsiExpression expression) {
|
||||
PsiExpression lValue;
|
||||
if (expression instanceof PsiAssignmentExpression assignment) {
|
||||
lValue = assignment.getLExpression();
|
||||
}
|
||||
else if (PsiUtil.isIncrementDecrementOperation(expression)) {
|
||||
lValue = ((PsiUnaryExpression)expression).getOperand();
|
||||
}
|
||||
else {
|
||||
lValue = null;
|
||||
}
|
||||
if (lValue != null && !TypeConversionUtil.isLValue(lValue) && !PsiTreeUtil.hasErrorElements(expression) &&
|
||||
!(IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
PsiUtil.skipParenthesizedExprDown(lValue) instanceof PsiReferenceExpression ref &&
|
||||
IncompleteModelUtil.canBePendingReference(ref))) {
|
||||
myVisitor.report(JavaErrorKinds.LVALUE_VARIABLE_EXPECTED.create(lValue));
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isArrayDeclaration(@NotNull PsiVariable variable) {
|
||||
// Java-style 'var' arrays are prohibited by the parser; for C-style ones, looking for a bracket is enough
|
||||
return ContainerUtil.or(variable.getChildren(), e -> PsiUtil.isJavaToken(e, JavaTokenType.LBRACKET));
|
||||
|
||||
+32
@@ -4,6 +4,7 @@ package com.intellij.java.codeserver.highlighting;
|
||||
import com.intellij.codeInsight.UnhandledExceptions;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
@@ -14,6 +15,7 @@ import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
@@ -139,6 +141,30 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
if (!hasErrorResults()) myStatementChecker.checkBreakTarget(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYieldStatement(@NotNull PsiYieldStatement statement) {
|
||||
super.visitYieldStatement(statement);
|
||||
if (!hasErrorResults()) myStatementChecker.checkYieldOutsideSwitchExpression(statement);
|
||||
if (!hasErrorResults()) {
|
||||
PsiExpression expression = statement.getExpression();
|
||||
if (expression != null) {
|
||||
myStatementChecker.checkYieldExpressionType(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
|
||||
super.visitExpressionStatement(statement);
|
||||
PsiElement parent = statement.getParent();
|
||||
if (parent instanceof PsiSwitchLabeledRuleStatement ruleStatement) {
|
||||
PsiSwitchBlock switchBlock = ruleStatement.getEnclosingSwitchBlock();
|
||||
if (switchBlock instanceof PsiSwitchExpression expr && !PsiPolyExpressionUtil.isPolyExpression(expr)) {
|
||||
myStatementChecker.checkYieldExpressionType(statement.getExpression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitContinueStatement(@NotNull PsiContinueStatement statement) {
|
||||
super.visitContinueStatement(statement);
|
||||
@@ -788,6 +814,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
|
||||
@Override
|
||||
public void visitExpression(@NotNull PsiExpression expression) {
|
||||
ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
|
||||
super.visitExpression(expression);
|
||||
PsiElement parent = expression.getParent();
|
||||
// Method expression of the call should not be especially processed
|
||||
@@ -805,7 +832,12 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
if (!hasErrorResults() && expression.getParent() instanceof PsiThrowStatement statement && statement.getException() == expression) {
|
||||
myTypeChecker.checkMustBeThrowable(expression, expression.getType());
|
||||
}
|
||||
if (!hasErrorResults() && parent instanceof PsiNewExpression newExpression &&
|
||||
newExpression.getQualifier() != expression && newExpression.getArrayInitializer() != expression) {
|
||||
myExpressionChecker.checkAssignability(PsiTypes.intType(), expression.getType(), expression, expression); // like in 'new String["s"]'
|
||||
}
|
||||
if (!hasErrorResults()) myStatementChecker.checkForeachExpressionTypeIsIterable(expression);
|
||||
if (!hasErrorResults()) myExpressionChecker.checkVariableExpected(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
@@ -384,4 +384,16 @@ final class StatementChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkYieldOutsideSwitchExpression(@NotNull PsiYieldStatement statement) {
|
||||
if (statement.findEnclosingExpression() == null) {
|
||||
myVisitor.report(JavaErrorKinds.YIELD_UNEXPECTED.create(statement));
|
||||
}
|
||||
}
|
||||
|
||||
void checkYieldExpressionType(@NotNull PsiExpression expression) {
|
||||
if (PsiTypes.voidType().equals(expression.getType())) {
|
||||
myVisitor.report(JavaErrorKinds.YIELD_VOID.create(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -662,6 +662,8 @@ public final class JavaErrorKinds {
|
||||
public static final Simple<PsiBreakStatement> BREAK_OUT_OF_SWITCH_EXPRESSION = error("break.out.of.switch.expression");
|
||||
public static final Simple<PsiContinueStatement> CONTINUE_OUTSIDE_LOOP = error("continue.outside.loop");
|
||||
public static final Simple<PsiContinueStatement> CONTINUE_OUT_OF_SWITCH_EXPRESSION = error("continue.out.of.switch.expression");
|
||||
public static final Simple<PsiYieldStatement> YIELD_UNEXPECTED = error("yield.unexpected");
|
||||
public static final Simple<PsiExpression> YIELD_VOID = error("yield.void");
|
||||
|
||||
public static final Simple<PsiTypeElement> CATCH_TYPE_PARAMETER = error("catch.type.parameter");
|
||||
|
||||
@@ -708,6 +710,7 @@ public final class JavaErrorKinds {
|
||||
public static final Parameterized<PsiExpression, PsiVariable> ASSIGNMENT_DECLARED_OUTSIDE_GUARD =
|
||||
parameterized(PsiExpression.class, PsiVariable.class, "assignment.declared.outside.guard")
|
||||
.withRawDescription((expr, variable) -> message("assignment.declared.outside.guard", variable.getName()));
|
||||
public static final Simple<PsiExpression> LVALUE_VARIABLE_EXPECTED = error("lvalue.variable.expected");
|
||||
|
||||
public static final Parameterized<PsiJavaToken, JavaIncompatibleTypeErrorContext> BINARY_OPERATOR_NOT_APPLICABLE =
|
||||
parameterized(PsiJavaToken.class, JavaIncompatibleTypeErrorContext.class, "binary.operator.not.applicable")
|
||||
|
||||
-38
@@ -226,27 +226,6 @@ public final class HighlightUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkVariableExpected(@NotNull PsiExpression expression) {
|
||||
PsiExpression lValue;
|
||||
if (expression instanceof PsiAssignmentExpression assignment) {
|
||||
lValue = assignment.getLExpression();
|
||||
}
|
||||
else if (PsiUtil.isIncrementDecrementOperation(expression)) {
|
||||
lValue = ((PsiUnaryExpression)expression).getOperand();
|
||||
}
|
||||
else {
|
||||
lValue = null;
|
||||
}
|
||||
if (lValue != null && !TypeConversionUtil.isLValue(lValue) && !PsiTreeUtil.hasErrorElements(expression) &&
|
||||
!(IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
PsiUtil.skipParenthesizedExprDown(lValue) instanceof PsiReferenceExpression ref &&
|
||||
IncompleteModelUtil.canBePendingReference(ref))) {
|
||||
String description = JavaErrorBundle.message("variable.expected");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(lValue).descriptionAndTooltip(description);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkAssignability(@Nullable PsiType lType,
|
||||
@Nullable PsiType rType,
|
||||
@Nullable PsiExpression expression,
|
||||
@@ -469,23 +448,6 @@ public final class HighlightUtil {
|
||||
return PsiFormatUtil.formatVariable(field, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkYieldOutsideSwitchExpression(@NotNull PsiYieldStatement statement) {
|
||||
if (statement.findEnclosingExpression() == null) {
|
||||
String message = JavaErrorBundle.message("yield.unexpected");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkYieldExpressionType(@NotNull PsiExpression expression) {
|
||||
if (PsiTypes.voidType().equals(expression.getType())) {
|
||||
String message = JavaErrorBundle.message("yield.void");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static void checkSwitchExpressionReturnTypeCompatible(@NotNull PsiSwitchExpression switchExpression,
|
||||
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
||||
if (!PsiPolyExpressionUtil.isPolyExpression(switchExpression)) {
|
||||
|
||||
-30
@@ -383,30 +383,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYieldStatement(@NotNull PsiYieldStatement statement) {
|
||||
super.visitYieldStatement(statement);
|
||||
if (!hasErrorResults()) add(HighlightUtil.checkYieldOutsideSwitchExpression(statement));
|
||||
if (!hasErrorResults()) {
|
||||
PsiExpression expression = statement.getExpression();
|
||||
if (expression != null) {
|
||||
add(HighlightUtil.checkYieldExpressionType(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
|
||||
super.visitExpressionStatement(statement);
|
||||
PsiElement parent = statement.getParent();
|
||||
if (parent instanceof PsiSwitchLabeledRuleStatement ruleStatement) {
|
||||
PsiSwitchBlock switchBlock = ruleStatement.getEnclosingSwitchBlock();
|
||||
if (switchBlock instanceof PsiSwitchExpression expr && !PsiPolyExpressionUtil.isPolyExpression(expr)) {
|
||||
add(HighlightUtil.checkYieldExpressionType(statement.getExpression()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClass(@NotNull PsiClass aClass) {
|
||||
super.visitClass(aClass);
|
||||
@@ -463,7 +439,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
|
||||
@Override
|
||||
public void visitExpression(@NotNull PsiExpression expression) {
|
||||
ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
|
||||
super.visitExpression(expression);
|
||||
|
||||
PsiElement parent = expression.getParent();
|
||||
@@ -471,12 +446,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
if (parent instanceof PsiMethodCallExpression) return;
|
||||
PsiType type = expression.getType();
|
||||
|
||||
if (!hasErrorResults() && parent instanceof PsiNewExpression newExpression &&
|
||||
newExpression.getQualifier() != expression && newExpression.getArrayInitializer() != expression) {
|
||||
add(HighlightUtil.checkAssignability(PsiTypes.intType(), expression.getType(), expression, expression)); // like in 'new String["s"]'
|
||||
}
|
||||
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression, myFile));
|
||||
if (!hasErrorResults()) add(HighlightUtil.checkVariableExpected(expression));
|
||||
if (!hasErrorResults()) add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression, type));
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -2,12 +2,12 @@ class YieldStatements {
|
||||
static final int ref = -1;
|
||||
|
||||
void m(int i) {
|
||||
<error descr="Case statement outside switch">default:</error> <error descr="Yield outside of switch expression">yield 0;</error>
|
||||
<error descr="Case statement outside switch">default:</error> <error descr="'yield' outside of a switch expression">yield 0;</error>
|
||||
|
||||
l1: yield <error descr="Cannot resolve symbol 'l1'">l1</error>;
|
||||
|
||||
switch (i) {
|
||||
default: <error descr="Yield outside of switch expression">yield 0;</error>
|
||||
default: <error descr="'yield' outside of a switch expression">yield 0;</error>
|
||||
}
|
||||
|
||||
out: System.out.println(switch (i) {
|
||||
@@ -21,7 +21,7 @@ class YieldStatements {
|
||||
a: switch (0) { default: yield a; }
|
||||
}
|
||||
case 7 -> {
|
||||
Runnable r = () -> { <error descr="Yield outside of switch expression">yield 0;</error> };
|
||||
Runnable r = () -> { <error descr="'yield' outside of a switch expression">yield 0;</error> };
|
||||
r.run();
|
||||
yield 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ public class UnnecessaryParenthesesInspection
|
||||
}
|
||||
|
||||
public java.util.function.IntFunction context() {
|
||||
return <error descr="Incompatible types. Found: 'int', required: '<lambda expression>'">(a -> a)=1</error>;
|
||||
return <error descr="Variable expected">(a -> a)</error>=1;
|
||||
}
|
||||
|
||||
void conditionals(boolean prevConnect, boolean nextConnect) {
|
||||
|
||||
Reference in New Issue
Block a user