[java-highlighting] type-related errors, lvti-related errors, TypeChecker introduced

Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only)

GitOrigin-RevId: 126dfbfe5a1046072d520e9a8f57261ff7add384
This commit is contained in:
Tagir Valeev
2025-01-29 11:35:29 +00:00
committed by intellij-monorepo-bot
parent f912c93cec
commit a157ee801e
18 changed files with 371 additions and 291 deletions
@@ -186,6 +186,18 @@ type.incompatible.reason.inference=<br/>reason: {0}
type.void.not.allowed='void' type is not allowed here
type.void.illegal=Illegal type: 'void'
type.inaccessible=''{0}'' is inaccessible here
type.unknown.class=Unknown class: ''{0}''
type.argument.primitive=Type argument cannot be of a primitive type
type.wildcard.cannot.be.instantiated=Wildcard type ''{0}'' cannot be instantiated directly
type.wildcard.not.expected=No wildcard expected
type.wildcard.may.be.used.only.as.reference.parameters=Wildcards may be used only as reference parameters
lvti.no.initializer=Cannot infer type: 'var' on variable without initializer
lvti.lambda=Cannot infer type: lambda expression requires an explicit target type
lvti.method.reference=Cannot infer type: method reference requires an explicit target type
lvti.array='var' is not allowed as an element type of an array
lvti.null=Cannot infer type: variable initializer is 'null'
lvti.void=Cannot infer type: variable initializer is 'void'
label.without.statement=Label without statement
label.duplicate=Label ''{0}'' already in use
@@ -197,6 +209,8 @@ 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
foreach.not.applicable=Foreach not applicable to type ''{0}''
new.expression.qualified.malformed=Invalid qualified new
new.expression.qualified.static.class=Qualified new of static class
new.expression.qualified.anonymous.implements.interface=Anonymous class implements interface; cannot have qualifier for new
@@ -282,6 +296,7 @@ array.type.expected=Array type expected; found: ''{0}''
array.generic=Generic array creation not allowed
array.empty.diamond=Array creation with '<>' not allowed
array.type.arguments=Array creation with type arguments not allowed
array.too.many.dimensions=Too many array dimensions
pattern.type.pattern.expected=Type pattern expected
@@ -155,31 +155,6 @@ final class ExpressionChecker {
}
}
void checkIllegalVoidType(@NotNull PsiKeyword type) {
if (!PsiKeyword.VOID.equals(type.getText())) return;
PsiElement parent = type.getParent();
if (parent instanceof PsiErrorElement) return;
if (parent instanceof PsiTypeElement) {
PsiElement typeOwner = parent.getParent();
if (typeOwner != null) {
// do not highlight incomplete declarations
if (PsiUtilCore.hasErrorElementChild(typeOwner)) return;
}
if (typeOwner instanceof PsiMethod method) {
if (method.getReturnTypeElement() == parent && PsiTypes.voidType().equals(method.getReturnType())) return;
}
else if (typeOwner instanceof PsiClassObjectAccessExpression classAccess) {
if (TypeConversionUtil.isVoidType(classAccess.getOperand().getType())) return;
}
else if (typeOwner instanceof JavaCodeFragment) {
if (typeOwner.getUserData(PsiUtil.VALID_VOID_TYPE_IN_CODE_FRAGMENT) != null) return;
}
}
myVisitor.report(JavaErrorKinds.TYPE_VOID_ILLEGAL.create(type));
}
void checkMustBeBoolean(@NotNull PsiExpression expr) {
PsiElement parent = expr.getParent();
if (parent instanceof PsiIfStatement ||
@@ -199,31 +174,6 @@ final class ExpressionChecker {
}
}
void checkAssertOperatorTypes(@NotNull PsiExpression expression) {
if (!(expression.getParent() instanceof PsiAssertStatement assertStatement)) return;
PsiType type = expression.getType();
if (type == null) return;
if (expression == assertStatement.getAssertCondition() && !TypeConversionUtil.isBooleanType(type)) {
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(
expression, new JavaIncompatibleTypeErrorContext(PsiTypes.booleanType(), type)));
}
else if (expression == assertStatement.getAssertDescription() && TypeConversionUtil.isVoidType(type)) {
myVisitor.report(JavaErrorKinds.TYPE_VOID_NOT_ALLOWED.create(expression));
}
}
void checkSynchronizedExpressionType(@NotNull PsiExpression expression) {
if (expression.getParent() instanceof PsiSynchronizedStatement synchronizedStatement &&
expression == synchronizedStatement.getLockExpression()) {
PsiType type = expression.getType();
if (type == null) return;
if (type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type)) {
PsiClassType objectType = PsiType.getJavaLangObject(myVisitor.file().getManager(), expression.getResolveScope());
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expression, new JavaIncompatibleTypeErrorContext(objectType, type)));
}
}
}
void checkArrayInitializer(@NotNull PsiExpression initializer, @NotNull PsiArrayInitializerExpression initializerList) {
PsiType arrayType = initializerList.getType();
if (!(arrayType instanceof PsiArrayType theArrayType)) return;
@@ -754,7 +704,7 @@ final class ExpressionChecker {
myVisitor.report(JavaErrorKinds.EXCEPTION_UNHANDLED_CLOSE.create(resource, unhandled));
}
private static boolean isArrayDeclaration(@NotNull PsiVariable variable) {
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));
}
@@ -384,6 +384,42 @@ final class GenericsChecker {
}
}
void checkReferenceTypeUsedAsTypeArgument(@NotNull PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
PsiType wildCardBind = type instanceof PsiWildcardType wildcardType ? wildcardType.getBound() : null;
if (type != PsiTypes.nullType() && type instanceof PsiPrimitiveType || wildCardBind instanceof PsiPrimitiveType) {
if (!(typeElement.getParent() instanceof PsiReferenceParameterList list)) return;
PsiElement parent = list.getParent();
if (!(parent instanceof PsiJavaCodeReferenceElement) && !(parent instanceof PsiNewExpression)) return;
myVisitor.report(JavaErrorKinds.TYPE_ARGUMENT_PRIMITIVE.create(typeElement));
}
}
void checkWildcardUsage(@NotNull PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
if (type instanceof PsiWildcardType) {
if (typeElement.getParent() instanceof PsiReferenceParameterList) {
PsiElement parent = typeElement.getParent().getParent();
PsiElement refParent = parent.getParent();
if (refParent instanceof PsiAnonymousClass) refParent = refParent.getParent();
if (refParent instanceof PsiNewExpression newExpression) {
if (!(newExpression.getType() instanceof PsiArrayType)) {
myVisitor.report(JavaErrorKinds.TYPE_WILDCARD_CANNOT_BE_INSTANTIATED.create(typeElement));
}
}
else if (refParent instanceof PsiReferenceList) {
PsiElement refPParent = refParent.getParent();
if (!(refPParent instanceof PsiTypeParameter typeParameter) || refParent != typeParameter.getExtendsList()) {
myVisitor.report(JavaErrorKinds.TYPE_WILDCARD_NOT_EXPECTED.create(typeElement));
}
}
}
else if (!typeElement.isInferredType()){
myVisitor.report(JavaErrorKinds.TYPE_WILDCARD_MAY_BE_USED_ONLY_AS_REFERENCE_PARAMETERS.create(typeElement));
}
}
}
private static PsiType detectExpectedType(@NotNull PsiReferenceParameterList referenceParameterList) {
PsiNewExpression newExpression = requireNonNull(PsiTreeUtil.getParentOfType(referenceParameterList, PsiNewExpression.class));
PsiElement parent = newExpression.getParent();
@@ -47,6 +47,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
private final @NotNull RecordChecker myRecordChecker = new RecordChecker(this);
private final @NotNull ImportChecker myImportChecker = new ImportChecker(this);
final @NotNull GenericsChecker myGenericsChecker = new GenericsChecker(this);
final @NotNull TypeChecker myTypeChecker = new TypeChecker(this);
final @NotNull MethodChecker myMethodChecker = new MethodChecker(this);
private final @NotNull ReceiverChecker myReceiverChecker = new ReceiverChecker(this);
final @NotNull ModifierChecker myModifierChecker = new ModifierChecker(this);
@@ -147,6 +148,16 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults()) myStatementChecker.checkContinueTarget(statement);
}
@Override
public void visitTypeElement(@NotNull PsiTypeElement type) {
super.visitTypeElement(type);
if (!hasErrorResults()) myTypeChecker.checkIllegalType(type);
if (!hasErrorResults()) myTypeChecker.checkVarTypeApplicability(type);
if (!hasErrorResults()) myTypeChecker.checkArrayType(type);
if (!hasErrorResults()) myGenericsChecker.checkReferenceTypeUsedAsTypeArgument(type);
if (!hasErrorResults()) myGenericsChecker.checkWildcardUsage(type);
}
@Override
public void visitParameter(@NotNull PsiParameter parameter) {
super.visitParameter(parameter);
@@ -160,7 +171,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults() && parameter.getType() instanceof PsiDisjunctionType) {
checkFeature(parameter, JavaFeature.MULTI_CATCH);
}
if (!hasErrorResults()) myStatementChecker.checkMustBeThrowable(parameter, parameter.getType());
if (!hasErrorResults()) myTypeChecker.checkMustBeThrowable(parameter, parameter.getType());
if (!hasErrorResults()) myStatementChecker.checkCatchTypeIsDisjoint(parameter);
if (!hasErrorResults()) myGenericsChecker.checkCatchParameterIsClass(parameter);
}
@@ -461,7 +472,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
public void visitKeyword(@NotNull PsiKeyword keyword) {
super.visitKeyword(keyword);
if (!hasErrorResults()) myClassChecker.checkStaticDeclarationInInnerClass(keyword);
if (!hasErrorResults()) myExpressionChecker.checkIllegalVoidType(keyword);
if (!hasErrorResults()) myTypeChecker.checkIllegalVoidType(keyword);
PsiElement parent = keyword.getParent();
if (parent instanceof PsiModifierList psiModifierList) {
if (!hasErrorResults()) myModifierChecker.checkNotAllowedModifier(keyword, psiModifierList);
@@ -750,15 +761,18 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (parent instanceof PsiMethodCallExpression) return;
if (!hasErrorResults()) myAnnotationChecker.checkConstantExpression(expression);
if (!hasErrorResults()) myExpressionChecker.checkMustBeBoolean(expression);
if (!hasErrorResults()) myExpressionChecker.checkAssertOperatorTypes(expression);
if (!hasErrorResults()) myExpressionChecker.checkSynchronizedExpressionType(expression);
if (!hasErrorResults()) myStatementChecker.checkAssertStatementTypes(expression);
if (!hasErrorResults()) myStatementChecker.checkSynchronizedStatementType(expression);
if (expression.getParent() instanceof PsiArrayInitializerExpression arrayInitializer) {
if (!hasErrorResults()) myExpressionChecker.checkArrayInitializer(expression, arrayInitializer);
}
if (!hasErrorResults() && expression instanceof PsiArrayAccessExpression accessExpression) {
myExpressionChecker.checkValidArrayAccessExpression(accessExpression);
}
if (!hasErrorResults()) myStatementChecker.checkThrowExceptionType(expression);
if (!hasErrorResults() && expression.getParent() instanceof PsiThrowStatement statement && statement.getException() == expression) {
myTypeChecker.checkMustBeThrowable(expression, expression.getType());
}
if (!hasErrorResults()) myStatementChecker.checkForeachExpressionTypeIsIterable(expression);
}
@Override
@@ -2,6 +2,7 @@
package com.intellij.java.codeserver.highlighting;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.core.JavaPsiBundle;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
@@ -81,6 +82,26 @@ final class StatementChecker {
}
}
void checkForeachExpressionTypeIsIterable(@NotNull PsiExpression expression) {
if (!shouldReportForeachNotApplicable(expression)) return;
if (expression.getType() == null) return;
PsiType itemType = JavaGenericsUtil.getCollectionItemType(expression);
if (itemType == null) {
myVisitor.report(JavaErrorKinds.FOREACH_NOT_APPLICABLE.create(expression));
}
}
private static boolean shouldReportForeachNotApplicable(@NotNull PsiExpression expression) {
if (!(expression.getParent() instanceof PsiForeachStatementBase parentForEach)) return false;
PsiExpression iteratedValue = parentForEach.getIteratedValue();
if (iteratedValue != expression) return false;
// Ignore if the type of the value which is being iterated over is not resolved yet
PsiType iteratedValueType = iteratedValue.getType();
return iteratedValueType == null || !PsiTypesUtil.hasUnresolvedComponents(iteratedValueType);
}
void checkCatchTypeIsDisjoint(@NotNull PsiParameter parameter) {
if (!(parameter.getType() instanceof PsiDisjunctionType)) return;
@@ -339,20 +360,27 @@ final class StatementChecker {
myVisitor.report(kind.create(statement));
}
void checkThrowExceptionType(@NotNull PsiExpression expression) {
if (expression.getParent() instanceof PsiThrowStatement statement && statement.getException() == expression) {
PsiType type = expression.getType();
checkMustBeThrowable(expression, type);
void checkAssertStatementTypes(@NotNull PsiExpression expression) {
if (!(expression.getParent() instanceof PsiAssertStatement assertStatement)) return;
PsiType type = expression.getType();
if (type == null) return;
if (expression == assertStatement.getAssertCondition() && !TypeConversionUtil.isBooleanType(type)) {
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(
expression, new JavaIncompatibleTypeErrorContext(PsiTypes.booleanType(), type)));
}
else if (expression == assertStatement.getAssertDescription() && TypeConversionUtil.isVoidType(type)) {
myVisitor.report(JavaErrorKinds.TYPE_VOID_NOT_ALLOWED.create(expression));
}
}
void checkMustBeThrowable(@NotNull PsiElement context, PsiType type) {
if (type != null && !InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_THROWABLE)) {
PsiElementFactory factory = myVisitor.factory();
PsiClassType throwable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, context.getResolveScope());
if (!(IncompleteModelUtil.isIncompleteModel(context) &&
IncompleteModelUtil.isPotentiallyConvertible(throwable, type, context))) {
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(context, new JavaIncompatibleTypeErrorContext(throwable, type)));
void checkSynchronizedStatementType(@NotNull PsiExpression expression) {
if (expression.getParent() instanceof PsiSynchronizedStatement synchronizedStatement &&
expression == synchronizedStatement.getLockExpression()) {
PsiType type = expression.getType();
if (type == null) return;
if (type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type)) {
PsiClassType objectType = PsiType.getJavaLangObject(myVisitor.file().getManager(), expression.getResolveScope());
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(expression, new JavaIncompatibleTypeErrorContext(objectType, type)));
}
}
}
@@ -0,0 +1,176 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeserver.highlighting;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
import com.intellij.psi.*;
import com.intellij.psi.impl.IncompleteModelUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import static com.intellij.util.ObjectUtils.tryCast;
final class TypeChecker {
private final @NotNull JavaErrorVisitor myVisitor;
TypeChecker(@NotNull JavaErrorVisitor visitor) { myVisitor = visitor; }
void checkIllegalType(@NotNull PsiTypeElement typeElement) {
PsiElement parent = typeElement.getParent();
if (parent instanceof PsiTypeElement) return;
if (PsiUtil.isInsideJavadocComment(typeElement)) return;
PsiType type = typeElement.getType();
PsiType componentType = type.getDeepComponentType();
if (componentType instanceof PsiClassType) {
PsiClass aClass = PsiUtil.resolveClassInType(componentType);
if (aClass == null) {
if (typeElement.isInferredType() && parent instanceof PsiLocalVariable localVariable) {
PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(localVariable.getInitializer());
if (initializer instanceof PsiNewExpression) {
// The problem is already reported on the initializer
return;
}
}
if (IncompleteModelUtil.isIncompleteModel(myVisitor.file())) return;
myVisitor.report(JavaErrorKinds.TYPE_UNKNOWN_CLASS.create(typeElement));
}
}
}
void checkVarTypeApplicability(@NotNull PsiTypeElement typeElement) {
if (!typeElement.isInferredType()) return;
PsiElement parent = typeElement.getParent();
PsiVariable variable = tryCast(parent, PsiVariable.class);
if (variable instanceof PsiLocalVariable localVariable) {
PsiExpression initializer = variable.getInitializer();
if (initializer == null) {
if (PsiUtilCore.hasErrorElementChild(variable)) return;
myVisitor.report(JavaErrorKinds.LVTI_NO_INITIALIZER.create(localVariable));
return;
}
PsiExpression deparen = PsiUtil.skipParenthesizedExprDown(initializer);
if (deparen instanceof PsiFunctionalExpression) {
var kind = deparen instanceof PsiLambdaExpression ? JavaErrorKinds.LVTI_LAMBDA : JavaErrorKinds.LVTI_METHOD_REFERENCE;
myVisitor.report(kind.create(localVariable));
return;
}
if (ExpressionChecker.isArrayDeclaration(variable)) {
myVisitor.report(JavaErrorKinds.LVTI_ARRAY.create(localVariable));
return;
}
PsiType lType = variable.getType();
if (PsiTypes.nullType().equals(lType) && allChildrenAreNullLiterals(initializer)) {
myVisitor.report(JavaErrorKinds.LVTI_NULL.create(localVariable));
return;
}
if (PsiTypes.voidType().equals(lType)) {
myVisitor.report(JavaErrorKinds.LVTI_VOID.create(localVariable));
}
}
else if (variable instanceof PsiParameter && variable.getParent() instanceof PsiParameterList &&
ExpressionChecker.isArrayDeclaration(variable)) {
myVisitor.report(JavaErrorKinds.LVTI_ARRAY.create(variable));
}
}
private static boolean allChildrenAreNullLiterals(PsiExpression expression) {
expression = PsiUtil.skipParenthesizedExprDown(expression);
if (expression == null) return false;
if (expression instanceof PsiLiteralExpression literal && PsiTypes.nullType().equals(literal.getType())) return true;
if (expression instanceof PsiTypeCastExpression cast) {
return allChildrenAreNullLiterals(cast.getOperand());
}
if (expression instanceof PsiConditionalExpression conditional) {
return allChildrenAreNullLiterals(conditional.getThenExpression()) &&
allChildrenAreNullLiterals(conditional.getElseExpression());
}
if (expression instanceof PsiSwitchExpression switchExpression) {
PsiCodeBlock switchBody = switchExpression.getBody();
if (switchBody == null) return false;
PsiStatement[] statements = switchBody.getStatements();
for (PsiStatement statement : statements) {
if (statement instanceof PsiSwitchLabeledRuleStatement rule) {
PsiStatement ruleBody = rule.getBody();
if (ruleBody instanceof PsiBlockStatement blockStatement) {
for (PsiYieldStatement yield : PsiTreeUtil.findChildrenOfType(blockStatement, PsiYieldStatement.class)) {
if (yield.findEnclosingExpression() == switchExpression && !allChildrenAreNullLiterals(yield.getExpression())) {
return false;
}
}
}
else if (ruleBody instanceof PsiExpressionStatement expr) {
if (!allChildrenAreNullLiterals(expr.getExpression())) return false;
}
}
else if (statement instanceof PsiYieldStatement yield) {
if (!allChildrenAreNullLiterals(yield.getExpression())) return false;
}
else {
for (PsiYieldStatement yield : PsiTreeUtil.findChildrenOfType(statement, PsiYieldStatement.class)) {
if (yield.findEnclosingExpression() == switchExpression && !allChildrenAreNullLiterals(yield.getExpression())) {
return false;
}
}
}
}
return true;
}
return false;
}
void checkArrayType(@NotNull PsiTypeElement type) {
int dimensions = 0;
for (PsiElement child = type.getFirstChild(); child != null; child = child.getNextSibling()) {
if (PsiUtil.isJavaToken(child, JavaTokenType.LBRACKET)) {
dimensions++;
}
}
if (dimensions > 255) {
// JVM Specification, 4.3.2: no more than 255 dimensions allowed
myVisitor.report(JavaErrorKinds.ARRAY_TOO_MANY_DIMENSIONS.create(type));
}
}
void checkIllegalVoidType(@NotNull PsiKeyword type) {
if (!PsiKeyword.VOID.equals(type.getText())) return;
PsiElement parent = type.getParent();
if (parent instanceof PsiErrorElement) return;
if (parent instanceof PsiTypeElement) {
PsiElement typeOwner = parent.getParent();
if (typeOwner != null) {
// do not highlight incomplete declarations
if (PsiUtilCore.hasErrorElementChild(typeOwner)) return;
}
if (typeOwner instanceof PsiMethod method) {
if (method.getReturnTypeElement() == parent && PsiTypes.voidType().equals(method.getReturnType())) return;
}
else if (typeOwner instanceof PsiClassObjectAccessExpression classAccess) {
if (TypeConversionUtil.isVoidType(classAccess.getOperand().getType())) return;
}
else if (typeOwner instanceof JavaCodeFragment) {
if (typeOwner.getUserData(PsiUtil.VALID_VOID_TYPE_IN_CODE_FRAGMENT) != null) return;
}
}
myVisitor.report(JavaErrorKinds.TYPE_VOID_ILLEGAL.create(type));
}
void checkMustBeThrowable(@NotNull PsiElement context, PsiType type) {
PsiElementFactory factory = myVisitor.factory();
PsiClassType throwable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, context.getResolveScope());
if (type != null && !TypeConversionUtil.isAssignable(throwable, type)) {
if (!(IncompleteModelUtil.isIncompleteModel(context) &&
IncompleteModelUtil.isPotentiallyConvertible(throwable, type, context))) {
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(context, new JavaIncompatibleTypeErrorContext(throwable, type)));
}
}
}
}
@@ -8,6 +8,8 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
/**
* A concrete instance of a Java compilation error. Note that the instance is bound to a PSI element, so it should not
* outlive the read-action. Otherwise it may become invalid.
@@ -75,4 +77,23 @@ public record JavaCompilationError<Psi extends PsiElement, Context>(@NotNull Jav
public @NotNull HtmlChunk tooltip() {
return kind.tooltip(psi, context);
}
/**
* A helper method to match wanted error message and extract PSI without doing unchecked casts in client code.
*
* @param kinds wanted error kinds
* @return an optional containing typed {@link #psi()} if the current error is one of supplied kinds;
* empty optional otherwise
* @param <WantedPsi> the common PSI type of wanted kinds
*/
@SafeVarargs
public final <WantedPsi extends PsiElement> @NotNull Optional<WantedPsi> psiForKind(JavaErrorKind<? extends WantedPsi, ?>... kinds) {
for (JavaErrorKind<? extends WantedPsi, ?> errorKind : kinds) {
if (errorKind.equals(kind)) {
//noinspection unchecked
return Optional.of((WantedPsi)psi);
}
}
return Optional.empty();
}
}
@@ -613,6 +613,31 @@ public final class JavaErrorKinds {
public static final Parameterized<PsiElement, PsiClass> TYPE_INACCESSIBLE =
parameterized(PsiElement.class, PsiClass.class, "type.inaccessible")
.withRawDescription((psi, cls) -> message("type.inaccessible", formatClass(cls)));
public static final Simple<PsiTypeElement> TYPE_UNKNOWN_CLASS = error(PsiTypeElement.class, "type.unknown.class")
.withRawDescription(type -> message("type.unknown.class", type.getType().getDeepComponentType().getCanonicalText()));
public static final Simple<PsiTypeElement> TYPE_ARGUMENT_PRIMITIVE = error(PsiTypeElement.class, "type.argument.primitive");
public static final Simple<PsiTypeElement> TYPE_WILDCARD_NOT_EXPECTED = error(PsiTypeElement.class, "type.wildcard.not.expected");
public static final Simple<PsiTypeElement> TYPE_WILDCARD_MAY_BE_USED_ONLY_AS_REFERENCE_PARAMETERS =
error(PsiTypeElement.class, "type.wildcard.may.be.used.only.as.reference.parameters");
public static final Simple<PsiTypeElement> TYPE_WILDCARD_CANNOT_BE_INSTANTIATED =
error(PsiTypeElement.class, "type.wildcard.cannot.be.instantiated")
.withRawDescription(type -> message("type.wildcard.cannot.be.instantiated", formatType(type.getType())));
public static final Simple<PsiExpression> FOREACH_NOT_APPLICABLE = error(PsiExpression.class, "foreach.not.applicable")
.withRawDescription(expression -> message("foreach.not.applicable", formatType(expression.getType())));
public static final Simple<PsiLocalVariable> LVTI_NO_INITIALIZER = error(PsiLocalVariable.class, "lvti.no.initializer")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiLocalVariable> LVTI_VOID = error(PsiLocalVariable.class, "lvti.void")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiLocalVariable> LVTI_NULL = error(PsiLocalVariable.class, "lvti.null")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiLocalVariable> LVTI_LAMBDA = error(PsiLocalVariable.class, "lvti.lambda")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiLocalVariable> LVTI_METHOD_REFERENCE = error(PsiLocalVariable.class, "lvti.method.reference")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiVariable> LVTI_ARRAY = error(PsiVariable.class, "lvti.array")
.withAnchor(var -> var.getTypeElement());
public static final Simple<PsiLabeledStatement> LABEL_WITHOUT_STATEMENT = error(PsiLabeledStatement.class, "label.without.statement")
.withAnchor(label -> label.getLabelIdentifier());
@@ -642,6 +667,7 @@ public final class JavaErrorKinds {
public static final Simple<PsiElement> ARRAY_GENERIC = error("array.generic");
public static final Simple<PsiReferenceParameterList> ARRAY_EMPTY_DIAMOND = error("array.empty.diamond");
public static final Simple<PsiReferenceParameterList> ARRAY_TYPE_ARGUMENTS = error("array.type.arguments");
public static final Simple<PsiTypeElement> ARRAY_TOO_MANY_DIMENSIONS = error("array.too.many.dimensions");
public static final Parameterized<PsiReferenceExpression, PsiClass> PATTERN_TYPE_PATTERN_EXPECTED =
parameterized("pattern.type.pattern.expected");
@@ -644,79 +644,6 @@ public final class GenericsHighlightUtil {
return null;
}
static HighlightInfo.Builder checkWildcardUsage(@NotNull PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
if (type instanceof PsiWildcardType) {
if (typeElement.getParent() instanceof PsiReferenceParameterList) {
PsiElement parent = typeElement.getParent().getParent();
LOG.assertTrue(parent instanceof PsiJavaCodeReferenceElement, parent);
PsiElement refParent = parent.getParent();
if (refParent instanceof PsiAnonymousClass) refParent = refParent.getParent();
if (refParent instanceof PsiNewExpression newExpression) {
if (!(newExpression.getType() instanceof PsiArrayType)) {
String description = JavaErrorBundle.message("wildcard.type.cannot.be.instantiated", JavaHighlightUtil.formatType(type));
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description);
}
}
else if (refParent instanceof PsiReferenceList) {
PsiElement refPParent = refParent.getParent();
if (!(refPParent instanceof PsiTypeParameter typeParameter) || refParent != typeParameter.getExtendsList()) {
String description = JavaErrorBundle.message("generics.wildcard.not.expected");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description);
}
}
}
else if (!typeElement.isInferredType()){
String description = JavaErrorBundle.message("generics.wildcards.may.be.used.only.as.reference.parameters");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description);
}
}
return null;
}
static HighlightInfo.Builder checkReferenceTypeUsedAsTypeArgument(@NotNull PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
PsiType wildCardBind = type instanceof PsiWildcardType wildcardType ? wildcardType.getBound() : null;
if (type != PsiTypes.nullType() && type instanceof PsiPrimitiveType || wildCardBind instanceof PsiPrimitiveType) {
PsiElement element = new PsiMatcherImpl(typeElement)
.parent(PsiMatchers.hasClass(PsiReferenceParameterList.class))
.parent(PsiMatchers.hasClass(PsiJavaCodeReferenceElement.class, PsiNewExpression.class))
.getElement();
if (element == null) return null;
String text = JavaErrorBundle.message("generics.type.argument.cannot.be.of.primitive.type");
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(text);
PsiPrimitiveType toConvert = (PsiPrimitiveType)(type instanceof PsiWildcardType ? wildCardBind : type);
PsiClassType boxedType = toConvert.getBoxedType(typeElement);
if (boxedType != null) {
IntentionAction action = QuickFixFactory.getInstance().createReplacePrimitiveWithBoxedTypeAction(
typeElement, toConvert.getPresentableText(), toConvert.getBoxedTypeName());
builder.registerFix(action, null, null, null, null);
}
return builder;
}
return null;
}
static HighlightInfo.Builder checkForeachExpressionTypeIsIterable(@NotNull PsiExpression expression) {
if (expression.getType() == null) return null;
PsiType itemType = JavaGenericsUtil.getCollectionItemType(expression);
if (itemType == null) {
String description = JavaErrorBundle.message("foreach.not.applicable",
JavaHighlightUtil.formatType(expression.getType()));
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description);
IntentionAction action = QuickFixFactory.getInstance().createNotIterableForEachLoopFix(expression);
if (action != null) {
builder.registerFix(action, null, null, null, null);
}
return builder;
}
return null;
}
//http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
static HighlightInfo.Builder checkAccessStaticFieldFromEnumConstructor(@NotNull PsiReferenceExpression expr,
@NotNull JavaResolveResult result) {
@@ -417,7 +417,7 @@ public final class HighlightFixUtil {
return copyType != null && returnType.isAssignableFrom(copyType);
}
static void registerSpecifyVarTypeFix(@NotNull PsiLocalVariable variable, @NotNull HighlightInfo.Builder info) {
static void registerSpecifyVarTypeFix(@NotNull PsiLocalVariable variable, @NotNull Consumer<? super CommonIntentionAction> info) {
PsiElement block = PsiUtil.getVariableCodeBlock(variable, null);
if (block == null) return;
PsiTreeUtil.processElements(block, PsiReferenceExpression.class, ref -> {
@@ -435,8 +435,7 @@ public final class HighlightFixUtil {
if (type != null) {
type = GenericsUtil.getVariableTypeByExpressionType(type);
if (PsiTypesUtil.isDenotableType(type, variable) && !PsiTypes.voidType().equals(type)) {
IntentionAction fix = QuickFixFactory.getInstance().createSetVariableTypeFix(variable, type);
info.registerFix(fix, null, null, null, null);
info.accept(QuickFixFactory.getInstance().createSetVariableTypeFix(variable, type));
}
return false;
}
@@ -51,7 +51,6 @@ import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.NamedColorUtil;
import com.intellij.util.ui.UIUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.InstanceOfUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.Contract;
@@ -297,61 +296,6 @@ public final class HighlightUtil {
return null;
}
static HighlightInfo.Builder checkVarTypeApplicability(@NotNull PsiTypeElement typeElement) {
if (!typeElement.isInferredType()) {
return null;
}
PsiElement parent = typeElement.getParent();
PsiVariable variable = tryCast(parent, PsiVariable.class);
if (variable instanceof PsiLocalVariable localVariable) {
PsiExpression initializer = variable.getInitializer();
if (initializer == null) {
if (PsiUtilCore.hasErrorElementChild(variable)) return null;
String message = JavaErrorBundle.message("lvti.no.initializer");
HighlightInfo.Builder info =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(typeElement);
HighlightFixUtil.registerSpecifyVarTypeFix(localVariable, info);
return info;
}
PsiExpression deparen = PsiUtil.skipParenthesizedExprDown(initializer);
if (deparen instanceof PsiFunctionalExpression) {
boolean lambda = deparen instanceof PsiLambdaExpression;
String message = JavaErrorBundle.message(lambda ? "lvti.lambda" : "lvti.method.ref");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(typeElement);
}
if (isArrayDeclaration(variable)) {
String message = JavaErrorBundle.message("lvti.array");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(typeElement);
}
PsiType lType = variable.getType();
if (PsiTypes.nullType().equals(lType) &&
ExpressionUtils.nonStructuralChildren(initializer).allMatch(ExpressionUtils::isNullLiteral)) {
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.descriptionAndTooltip(JavaErrorBundle.message("lvti.null"))
.range(typeElement);
HighlightFixUtil.registerSpecifyVarTypeFix(localVariable, info);
return info;
}
if (PsiTypes.voidType().equals(lType)) {
String message = JavaErrorBundle.message("lvti.void");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(typeElement);
}
}
else if (variable instanceof PsiParameter && variable.getParent() instanceof PsiParameterList && isArrayDeclaration(variable)) {
String message = JavaErrorBundle.message("lvti.array");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message).range(typeElement);
}
return null;
}
private 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));
}
static HighlightInfo.Builder checkAssignability(@Nullable PsiType lType,
@Nullable PsiType rType,
@Nullable PsiExpression expression,
@@ -870,41 +814,6 @@ public final class HighlightUtil {
}
static HighlightInfo.Builder checkIllegalType(@NotNull PsiTypeElement typeElement, @NotNull PsiFile containingFile) {
PsiElement parent = typeElement.getParent();
if (parent instanceof PsiTypeElement) return null;
if (PsiUtil.isInsideJavadocComment(typeElement)) return null;
PsiType type = typeElement.getType();
PsiType componentType = type.getDeepComponentType();
if (componentType instanceof PsiClassType) {
PsiClass aClass = PsiUtil.resolveClassInType(componentType);
if (aClass == null) {
if (typeElement.isInferredType() && parent instanceof PsiLocalVariable localVariable) {
PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(localVariable.getInitializer());
if (initializer instanceof PsiNewExpression) {
// The problem is already reported on the initializer
return null;
}
}
if (IncompleteModelUtil.isIncompleteModel(containingFile)) {
return null;
}
String canonicalText = componentType.getCanonicalText();
String description = JavaErrorBundle.message("unknown.class", canonicalText);
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description);
PsiJavaCodeReferenceElement referenceElement = typeElement.getInnermostComponentReferenceElement();
if (referenceElement != null) {
UnresolvedReferenceQuickFixUpdater.getInstance(containingFile.getProject()).registerQuickFixesLater(referenceElement, info);
}
return info;
}
}
return null;
}
static HighlightInfo.Builder checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression,
@Nullable PsiElement resolved,
@NotNull Function<? super PsiElement, ? extends PsiMethod> surroundingConstructor) {
@@ -1191,21 +1100,6 @@ public final class HighlightUtil {
.navigationShift(navigationShift);
}
public static HighlightInfo.Builder checkArrayType(PsiTypeElement type) {
int dimensions = 0;
for (PsiElement child = type.getFirstChild(); child != null; child = child.getNextSibling()) {
if (PsiUtil.isJavaToken(child, JavaTokenType.LBRACKET)) {
dimensions++;
}
}
if (dimensions > 255) {
// JVM Specification, 4.3.2: no more than 255 dimensions allowed
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(type.getTextRange())
.description(JavaErrorBundle.message("too.many.array.dimensions"));
}
return null;
}
static HighlightInfo.Builder checkExtraSemicolonBetweenImportStatements(@NotNull PsiJavaToken token,
IElementType type,
@NotNull LanguageLevel level) {
@@ -64,6 +64,7 @@ import java.util.function.Function;
import static com.intellij.psi.PsiModifier.SEALED;
import static com.intellij.util.ObjectUtils.tryCast;
import static java.util.Objects.*;
// java highlighting: problems in java code like unresolved/incompatible symbols/methods etc.
public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor {
@@ -250,10 +251,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
info.range(anchor);
}
errorFixProvider.processFixes(error, fix -> info.registerFix(fix.asIntention(), null, null, null, null));
if (error.kind() == JavaErrorKinds.EXPRESSION_EXPECTED || error.kind() == JavaErrorKinds.REFERENCE_UNRESOLVED ||
error.kind() == JavaErrorKinds.REFERENCE_AMBIGUOUS) {
UnresolvedReferenceQuickFixUpdater.getInstance(getProject()).registerQuickFixesLater((PsiReference)error.psi(), info);
}
error.psiForKind(JavaErrorKinds.EXPRESSION_EXPECTED, JavaErrorKinds.REFERENCE_UNRESOLVED, JavaErrorKinds.REFERENCE_AMBIGUOUS)
.or(() -> error.psiForKind(JavaErrorKinds.TYPE_UNKNOWN_CLASS).map(PsiTypeElement::getInnermostComponentReferenceElement))
.ifPresent(ref -> UnresolvedReferenceQuickFixUpdater.getInstance(getProject()).registerQuickFixesLater(ref, info));
add(info);
}
@@ -478,20 +478,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression, myFile));
if (!hasErrorResults()) add(HighlightUtil.checkVariableExpected(expression));
if (!hasErrorResults()) add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression, type));
if (!hasErrorResults() && shouldReportForeachNotApplicable(expression)) {
add(GenericsHighlightUtil.checkForeachExpressionTypeIsIterable(expression));
}
}
private static boolean shouldReportForeachNotApplicable(@NotNull PsiExpression expression) {
if (!(expression.getParent() instanceof PsiForeachStatementBase parentForEach)) return false;
PsiExpression iteratedValue = parentForEach.getIteratedValue();
if (iteratedValue != expression) return false;
// Ignore if the type of the value which is being iterated over is not resolved yet
PsiType iteratedValueType = iteratedValue.getType();
return iteratedValueType == null || !PsiTypesUtil.hasUnresolvedComponents(iteratedValueType);
}
@Override
@@ -1024,8 +1010,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType)) {
return;
}
String t1 = HighlightUtil.format(Objects.requireNonNull(results[0].getElement()));
String t2 = HighlightUtil.format(Objects.requireNonNull(results[1].getElement()));
String t1 = HighlightUtil.format(requireNonNull(results[0].getElement()));
String t2 = HighlightUtil.format(requireNonNull(results[1].getElement()));
description = JavaErrorBundle.message("ambiguous.reference", expression.getReferenceName(), t1, t2);
}
else {
@@ -1148,11 +1134,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitTypeElement(@NotNull PsiTypeElement type) {
if (!hasErrorResults()) add(HighlightUtil.checkIllegalType(type, myFile));
if (!hasErrorResults()) add(HighlightUtil.checkVarTypeApplicability(type));
if (!hasErrorResults()) add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
if (!hasErrorResults()) add(GenericsHighlightUtil.checkWildcardUsage(type));
if (!hasErrorResults()) add(HighlightUtil.checkArrayType(type));
super.visitTypeElement(type);
if (!hasErrorResults()) {
PreviewFeatureUtil.checkPreviewFeature(type, myPreviewFeatureVisitor);
}
@@ -158,6 +158,7 @@ final class JavaErrorFixProvider {
}
}
});
fix(FOREACH_NOT_APPLICABLE, error -> myFactory.createNotIterableForEachLoopFix(error.psi()));
}
private void createMethodFixes() {
@@ -302,6 +303,8 @@ final class JavaErrorFixProvider {
private void createVariableFixes() {
fix(UNNAMED_VARIABLE_BRACKETS, error -> new NormalizeBracketsFix(error.psi()));
fix(UNNAMED_VARIABLE_WITHOUT_INITIALIZER, error -> myFactory.createAddVariableInitializerFix(error.psi()));
fixes(LVTI_NO_INITIALIZER, (error, sink) -> HighlightFixUtil.registerSpecifyVarTypeFix(error.psi(), sink));
fixes(LVTI_NULL, (error, sink) -> HighlightFixUtil.registerSpecifyVarTypeFix(error.psi(), sink));
}
private void createExpressionFixes() {
@@ -545,6 +548,18 @@ final class JavaErrorFixProvider {
HighlightFixUtil.registerMethodReturnFixAction(sink, candidate, constructorCall);
}
});
fix(TYPE_ARGUMENT_PRIMITIVE, error -> {
PsiTypeElement typeElement = error.psi();
PsiType type = typeElement.getType();
PsiPrimitiveType toConvert =
(PsiPrimitiveType)(type instanceof PsiWildcardType wildcardType ? requireNonNull(wildcardType.getBound()) : type);
PsiClassType boxedType = toConvert.getBoxedType(typeElement);
if (boxedType != null) {
return QuickFixFactory.getInstance().createReplacePrimitiveWithBoxedTypeAction(
typeElement, toConvert.getPresentableText(), boxedType.getCanonicalText());
}
return null;
});
}
private void createClassFixes() {
@@ -24,7 +24,6 @@ generics.methods.have.same.erasure.hide={0}; both methods have same erasure, yet
generics.type.parameter.cannot.be.instantiated=Type parameter ''{0}'' cannot be instantiated directly
wildcard.type.cannot.be.instantiated=Wildcard type ''{0}'' cannot be instantiated directly
generics.wildcard.not.expected=No wildcard expected
generics.wildcards.may.be.used.only.as.reference.parameters=Wildcards may be used only as reference parameters
generics.type.argument.cannot.be.of.primitive.type=Type argument cannot be of primitive type
generics.unchecked.assignment=Unchecked assignment: ''{0}'' to ''{1}''
generics.unchecked.cast=Unchecked cast: ''{0}'' to ''{1}''
@@ -371,11 +370,9 @@ module.bad.name=Module ''{0}'' has an invalid name
restricted.identifier=''{0}'' is a restricted identifier and cannot be used for type declarations
restricted.identifier.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
lvti.method.ref=Cannot infer type: method reference requires an explicit target type
lvti.compound='var' is not allowed in a compound declaration
lvti.array='var' is not allowed as an element type of an array
lvti.null=Cannot infer type: variable initializer is 'null'
lvti.void=Cannot infer type: variable initializer is 'void'
lvti.selfReferenced=Cannot infer type for ''{0}'', it is used in its own variable initializer
@@ -2,14 +2,14 @@ class A {
<T> A() {}
{
new <<error descr="Type argument cannot be of primitive type">int</error>>A();
new <<error descr="Type argument cannot be of a primitive type">int</error>>A();
}
}
class B<T> {
{
new B<<error descr="Type argument cannot be of primitive type">int</error>>();
B.<<error descr="Type argument cannot be of primitive type">int</error>>m();
new B<<error descr="Type argument cannot be of a primitive type">int</error>>();
B.<<error descr="Type argument cannot be of a primitive type">int</error>>m();
}
<S> void m(){}
@@ -27,10 +27,10 @@ class D<T extends C> {
}
class Primitives<T> {
Object a = new Primitives<<error descr="Type argument cannot be of primitive type">? extends int</error>>();
Object o = new Primitives<<error descr="Type argument cannot be of primitive type">int</error>>();
void f(Primitives<<error descr="Type argument cannot be of primitive type">boolean</error>> param) {
if (this instanceof Primitives<<error descr="Type argument cannot be of primitive type">double</error>>) {
Object a = new Primitives<<error descr="Type argument cannot be of a primitive type">? extends int</error>>();
Object o = new Primitives<<error descr="Type argument cannot be of a primitive type">int</error>>();
void f(Primitives<<error descr="Type argument cannot be of a primitive type">boolean</error>> param) {
if (this instanceof Primitives<<error descr="Type argument cannot be of a primitive type">double</error>>) {
return;
}
}
@@ -2,14 +2,14 @@ class A {
<T> A() {}
{
new <<error descr="Type argument cannot be of primitive type">int</error>>A();
new <<error descr="Type argument cannot be of a primitive type">int</error>>A();
}
}
class B<T> {
{
new B<<error descr="Type argument cannot be of primitive type">int</error>>();
B.<<error descr="Type argument cannot be of primitive type">int</error>>m();
new B<<error descr="Type argument cannot be of a primitive type">int</error>>();
B.<<error descr="Type argument cannot be of a primitive type">int</error>>m();
}
<S> void m(){}
@@ -27,10 +27,10 @@ class D<T extends C> {
}
class Primitives<T> {
Object a = new Primitives<<error descr="Type argument cannot be of primitive type">? extends int</error>>();
Object o = new Primitives<<error descr="Type argument cannot be of primitive type">int</error>>();
void f(Primitives<<error descr="Type argument cannot be of primitive type">boolean</error>> param) {
if (this instanceof Primitives<<error descr="Type argument cannot be of primitive type">double</error>>) {
Object a = new Primitives<<error descr="Type argument cannot be of a primitive type">? extends int</error>>();
Object o = new Primitives<<error descr="Type argument cannot be of a primitive type">int</error>>();
void f(Primitives<<error descr="Type argument cannot be of a primitive type">boolean</error>> param) {
if (this instanceof Primitives<<error descr="Type argument cannot be of a primitive type">double</error>>) {
return;
}
}