Java: add synthetic default constructor on resolve (IDEA-376799)

GitOrigin-RevId: 71d783efd5095b0995ac1788863c8a50de759f77
This commit is contained in:
Bas Leijdekkers
2025-10-07 18:33:10 +00:00
committed by intellij-monorepo-bot
parent f0b97cbcd3
commit cd8ada5c65
41 changed files with 271 additions and 253 deletions
@@ -287,7 +287,6 @@ new.expression.diamond.not.applicable=Diamond operator is not applicable to non-
new.expression.diamond.inference.failure={0}
new.expression.diamond.anonymous.inner.non.private=Cannot use '<>' due to a non-private method which doesn't override or implement a method from a supertype
new.expression.anonymous.implements.interface.with.type.arguments=Anonymous class implements interface; cannot have type arguments
new.expression.arguments.to.default.constructor.call=Default constructor is invoked with arguments
new.expression.unresolved.constructor=Cannot resolve constructor ''{0}''
new.expression.type.parameter=Type parameter ''{0}'' cannot be instantiated directly
@@ -19,7 +19,6 @@ import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.IncompleteModelUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ImplicitClassSearch;
@@ -259,13 +258,11 @@ final class ExpressionChecker {
void checkMethodCall(@NotNull PsiMethodCallExpression methodCall) {
PsiExpressionList list = methodCall.getArgumentList();
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
JavaResolveResult[] results = referenceToMethod.multiResolve(true);
JavaResolveResult resolveResult = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
PsiElement resolved = resolveResult.getElement();
boolean isDummy = isDummyConstructorCall(methodCall, list, referenceToMethod);
if (isDummy) return;
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (resolved instanceof PsiMethod psiMethod && resolveResult.isValidResult()) {
checkUnhandledExceptions(methodCall);
@@ -411,13 +408,12 @@ final class ExpressionChecker {
if (!(type instanceof PsiClassType classType)) return;
PsiClassType.ClassResolveResult typeResult = classType.resolveGenerics();
PsiClass aClass = typeResult.getElement();
if (aClass == null) return;
if (aClass instanceof PsiAnonymousClass anonymousClass) {
classType = anonymousClass.getBaseClassType();
typeResult = classType.resolveGenerics();
aClass = typeResult.getElement();
if (aClass == null) return;
}
if (aClass == null || aClass instanceof PsiTypeParameter) return;
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
checkConstructorCall(typeResult, expression, classReference);
@@ -1126,23 +1122,6 @@ final class ExpressionChecker {
myVisitor.report(JavaErrorKinds.EXCEPTION_UNHANDLED.create(element, unhandled));
}
boolean isDummyConstructorCall(@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiExpressionList list,
@NotNull PsiReferenceExpression referenceToMethod) {
boolean isThisOrSuper = referenceToMethod.getReferenceNameElement() instanceof PsiKeyword;
if (isThisOrSuper) {
// super(..) or this(..)
if (list.isEmpty()) { // implicit ctr call
CandidateInfo[] candidates = PsiResolveHelper.getInstance(myVisitor.project())
.getReferencedMethodCandidates(methodCall, true);
if (candidates.length == 1 && !candidates[0].getElement().isPhysical()) {
return true; // dummy constructor
}
}
}
return false;
}
void checkConstructorCall(@NotNull PsiClassType.ClassResolveResult typeResolveResult,
@NotNull PsiConstructorCall constructorCall,
@Nullable PsiJavaCodeReferenceElement classReference) {
@@ -1163,11 +1142,8 @@ final class ExpressionChecker {
}
PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length == 0) {
if (!list.isEmpty()) {
myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL.create(constructorCall));
}
else if (classReference != null && aClass.hasModifierProperty(PsiModifier.PROTECTED) &&
callingProtectedConstructorFromDerivedClass(constructorCall, aClass)) {
if (classReference != null && aClass.hasModifierProperty(PsiModifier.PROTECTED) &&
callingProtectedConstructorFromDerivedClass(constructorCall, aClass)) {
myVisitor.myModifierChecker.reportAccessProblem(classReference, aClass, typeResolveResult);
}
else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression newExpression) {
@@ -1175,8 +1151,8 @@ final class ExpressionChecker {
if (typeArgumentList.getTypeArguments().length > 0) {
myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_ANONYMOUS_IMPLEMENTS_INTERFACE_WITH_TYPE_ARGUMENTS.create(typeArgumentList));
}
return;
}
return;
}
JavaResolveResult[] results = constructorCall.multiResolve(false);
MethodCandidateInfo result = null;
@@ -1216,7 +1192,7 @@ final class ExpressionChecker {
constructorCall, new JavaErrorKinds.UnresolvedConstructorContext(aClass, results)));
return;
}
if (classReference != null &&
if (classReference != null && !constructor.isDefaultConstructor() &&
(!result.isAccessible() ||
constructor.hasModifierProperty(PsiModifier.PROTECTED) && callingProtectedConstructorFromDerivedClass(constructorCall, aClass))) {
myVisitor.myModifierChecker.reportAccessProblem(classReference, constructor, result);
@@ -313,7 +313,9 @@ final class GenericsChecker {
if (targetParametersNum == 0) {
boolean shouldSuppress = PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
typeParameterListOwner instanceof PsiMethod psiMethod &&
(myVisitor.sdkVersion().isAtLeast(JavaSdkVersion.JDK_1_7) || hasSuperMethodsWithTypeParams(psiMethod));
(myVisitor.sdkVersion().isAtLeast(JavaSdkVersion.JDK_1_7)
|| hasSuperMethodsWithTypeParams(psiMethod)
|| psiMethod.isDefaultConstructor());
if (!shouldSuppress) {
if (typeParameterListOwner instanceof PsiMethod psiMethod) {
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_ABSENT_METHOD.create(referenceParameterList, psiMethod));
@@ -827,14 +827,11 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (parent instanceof PsiMethodCallExpression methodCallExpression &&
methodCallExpression.getMethodExpression() == expression &&
(!result.isAccessible() || !result.isStaticsScopeCorrect())) {
PsiExpressionList list = methodCallExpression.getArgumentList();
if (!myExpressionChecker.isDummyConstructorCall(methodCallExpression, list, expression)) {
myExpressionChecker.checkAmbiguousMethodCallIdentifier(results, result, methodCallExpression);
if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
PsiElement nameElement = expression.getReferenceNameElement();
if (nameElement != null) {
myExpressionChecker.checkAmbiguousMethodCallArguments(results, result, methodCallExpression);
}
myExpressionChecker.checkAmbiguousMethodCallIdentifier(results, result, methodCallExpression);
if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
PsiElement nameElement = expression.getReferenceNameElement();
if (nameElement != null) {
myExpressionChecker.checkAmbiguousMethodCallArguments(results, result, methodCallExpression);
}
}
}
@@ -1221,7 +1218,6 @@ final class JavaErrorVisitor extends JavaElementVisitor {
JavaResolveResult result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
if ((!result.isAccessible() || !result.isStaticsScopeCorrect()) &&
!myExpressionChecker.isDummyConstructorCall(expression, list, referenceExpression) &&
// this check is for fake expression from JspMethodCallImpl
referenceExpression.getParent() == expression &&
PsiTreeUtil.findChildrenOfType(expression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
@@ -1126,10 +1126,6 @@ public final class JavaErrorKinds {
parameterized(PsiReferenceParameterList.class, PsiDiamondType.DiamondInferenceResult.class, "new.expression.diamond.inference.failure")
.withDescription(
(list, inferenceResult) -> message("new.expression.diamond.inference.failure", inferenceResult.getErrorMessage()));
public static final Simple<PsiConstructorCall> NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL =
error(PsiConstructorCall.class, "new.expression.arguments.to.default.constructor.call")
.withAnchor(call -> call.getArgumentList())
.withNavigationShift(1);
public static final Parameterized<PsiConstructorCall, UnresolvedConstructorContext> NEW_EXPRESSION_UNRESOLVED_CONSTRUCTOR =
parameterized(PsiConstructorCall.class, UnresolvedConstructorContext.class, "new.expression.unresolved.constructor")
.withAnchor(PsiCall::getArgumentList)
@@ -536,16 +536,6 @@ public final class DefaultJavaErrorFixProvider extends AbstractJavaErrorFixProvi
}
return null;
});
fixes(NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL, (error, sink) -> {
PsiConstructorCall constructorCall = error.psi();
PsiJavaCodeReferenceElement classReference =
constructorCall instanceof PsiNewExpression newExpression ? newExpression.getClassOrAnonymousClassReference() : null;
if (classReference != null) {
ConstructorParametersFixer.registerFixActions(constructorCall, sink);
}
QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall).forEach(sink);
RemoveRedundantArgumentsFix.registerIntentions(requireNonNull(constructorCall.getArgumentList()), sink);
});
fixes(NEW_EXPRESSION_UNRESOLVED_CONSTRUCTOR, (error, sink) -> {
PsiConstructorCall constructorCall = error.psi();
PsiExpressionList list = constructorCall.getArgumentList();
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.QuickFixBundle;
@@ -437,7 +437,7 @@ public final class HighlightFixUtil {
}
PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(methodCall.getProject());
CandidateInfo[] methodCandidates = resolveHelper.getReferencedMethodCandidates(methodCall, false);
CandidateInfo[] methodCandidates = resolveHelper.getReferencedMethodCandidates(methodCall, true);
IntentionAction action2 = QuickFixFactory.getInstance().createSurroundWithArrayFix(methodCall, null);
info.accept(action2);
@@ -88,13 +88,6 @@ public final class RemoveRedundantArgumentsFix extends PsiUpdateModCommandAction
}
}
public static void registerIntentions(@NotNull PsiExpressionList arguments,
@NotNull Consumer<? super CommonIntentionAction> info) {
if (!arguments.isEmpty()) {
info.accept(new ForImplicitConstructorAction(arguments));
}
}
private static void registerIntention(@NotNull PsiExpressionList arguments,
@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull JavaResolveResult candidate) {
@@ -110,27 +103,4 @@ public final class RemoveRedundantArgumentsFix extends PsiUpdateModCommandAction
}
info.accept(new RemoveRedundantArgumentsFix(method, arguments, substitutor));
}
private static class ForImplicitConstructorAction extends PsiUpdateModCommandAction<PsiExpressionList> {
ForImplicitConstructorAction(@NotNull PsiExpressionList list) {
super(list);
}
@Override
public @NotNull String getFamilyName() {
return QuickFixBundle.message("remove.redundant.arguments.family");
}
@Override
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiExpressionList args) {
return args.isEmpty() ? null : Presentation.of(getFamilyName());
}
@Override
protected void invoke(@NotNull ActionContext context, @NotNull PsiExpressionList args, @NotNull ModPsiUpdater updater) {
PsiExpression[] expressions = args.getExpressions();
if (expressions.length == 0) return;
args.deleteChildRange(expressions[0], expressions[expressions.length - 1]);
}
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.jvm.SpecialField;
@@ -281,7 +281,7 @@ public final class MutationSignature {
public static @NotNull MutationSignature fromCall(@Nullable PsiCall call) {
if (call == null) return UNKNOWN;
PsiMethod method = call.resolveMethod();
if (method != null) {
if (method != null && !method.isDefaultConstructor()) {
if (SpecialField.findSpecialField(method) != null) {
return PURE;
}
@@ -291,9 +291,7 @@ public final class MutationSignature {
if (newExpression.isArrayCreation()) return PURE;
if (newExpression.getArgumentList() == null || !newExpression.getArgumentList().isEmpty()) return UNKNOWN;
PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference();
if (classReference == null) return UNKNOWN;
PsiClass clazz = ObjectUtils.tryCast(classReference.resolve(), PsiClass.class);
if (clazz == null) return UNKNOWN;
if (classReference == null || !(classReference.resolve() instanceof PsiClass clazz)) return UNKNOWN;
Set<PsiClass> visited = new HashSet<>();
while (true) {
for (PsiField field : clazz.getFields()) {
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.codeInspection.deprecation;
import com.intellij.codeInsight.ExternalAnnotationsManager;
@@ -72,11 +72,12 @@ public final class DeprecatedApiUsageProcessor implements ApiUsageProcessor {
@NotNull PsiClass instantiatedClass,
@Nullable PsiMethod constructor,
@Nullable UClass subclassDeclaration) {
if (constructor != null) {
if (JavaDeprecationUtils.isDeprecated(constructor, sourceNode.getSourcePsi()) && myForRemoval == isForRemovalAttributeSet(constructor)) {
checkTargetDeprecated(sourceNode, constructor);
return;
}
if (constructor != null
&& !constructor.isDefaultConstructor()
&& JavaDeprecationUtils.isDeprecated(constructor, sourceNode.getSourcePsi())
&& myForRemoval == isForRemovalAttributeSet(constructor)) {
checkTargetDeprecated(sourceNode, constructor);
return;
}
if (isDefaultConstructorDeprecated(instantiatedClass)) {
@@ -85,8 +86,8 @@ public final class DeprecatedApiUsageProcessor implements ApiUsageProcessor {
return;
}
String description = JavaErrorBundle.message(myForRemoval
? "marked.for.removal.default.constructor"
: "deprecated.default.constructor",
? "marked.for.removal.default.constructor"
: "deprecated.default.constructor",
instantiatedClass.getQualifiedName());
myHolder.registerProblem(elementToHighlight, description);
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.refactoring.util.duplicates;
import com.intellij.codeInsight.AnnotationUtil;
@@ -300,10 +300,9 @@ public final class DuplicatesFinder {
if (type1 instanceof PsiImmediateClassType && type2 instanceof PsiImmediateClassType) {
final PsiClass psiClass1 = ((PsiImmediateClassType)type1).resolve();
final PsiClass psiClass2 = ((PsiImmediateClassType)type2).resolve();
if (!(psiClass1 instanceof PsiAnonymousClass anonymousClass1 &&
psiClass2 instanceof PsiAnonymousClass anonymousClass2 &&
anonymousClass1.getBaseClassType().equals(anonymousClass2.getBaseClassType())
)) {
if (!(psiClass1 instanceof PsiAnonymousClass anonymousClass1) ||
!(psiClass2 instanceof PsiAnonymousClass anonymousClass2) ||
!anonymousClass1.getBaseClassType().equals(anonymousClass2.getBaseClassType())) {
return false;
}
}
@@ -548,11 +547,9 @@ public final class DuplicatesFinder {
final PsiMethod constructor2 = candidate.resolveConstructor();
if (constructor1 != null && constructor2 != null) {
if (!pattern.getManager().areElementsEquivalent(constructor1, constructor2)) return false;
if (pattern.getAnonymousClass() == null && candidate.getAnonymousClass() == null) return true;
}
else {
if (!canTypesBeEquivalent(type1, type2)) return false;
}
return true;
return canTypesBeEquivalent(type1, type2);
}
private static boolean matchObjectAccess(@NotNull PsiClassObjectAccessExpression pattern,
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2021 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -343,7 +343,7 @@ public final class SideEffectChecker {
if (qualifiedName == null) return ThreeState.UNSURE;
if (ourSideEffectFreeClasses.contains(qualifiedName)) return ThreeState.NO;
PsiMethod method = newExpression.resolveConstructor();
if (method != null) {
if (method != null && !method.isDefaultConstructor()) {
MutationSignature signature = MutationSignature.fromMethod(method);
if (signature.isPure()) {
return ThreeState.NO;
@@ -364,7 +364,7 @@ public final class SideEffectChecker {
return ThreeState.NO;
}
}
if (method == null) {
if (method == null || method.isDefaultConstructor()) {
PsiClass superClass = aClass.getSuperClass();
if (superClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
for (PsiClassInitializer initializer : aClass.getInitializers()) {
@@ -68,7 +68,7 @@ class InlineToAnonymousConstructorProcessor {
JavaResolveResult classResolveResult = myNewExpression.getClassReference().advancedResolve(false);
JavaResolveResult methodResolveResult = myNewExpression.resolveMethodGenerics();
final PsiElement element = methodResolveResult.getElement();
myConstructor = element != null ? (PsiMethod) element.getNavigationElement() : null;
myConstructor = (element == null || element instanceof SyntheticElement) ? null : (PsiMethod)element.getNavigationElement();
myConstructorArguments = initConstructorArguments();
PsiSubstitutor classResolveSubstitutor = classResolveResult.getSubstitutor();
@@ -116,7 +116,8 @@ class InlineToAnonymousConstructorProcessor {
for (PsiElement child : classCopy.getChildren()) {
if ((child instanceof PsiMethod method && !method.isConstructor()) ||
child instanceof PsiClassInitializer || child instanceof PsiClass) {
if (!myFieldInitializers.isEmpty() || !myLocalsForParameters.isEmpty() || classResolveSubstitutor != PsiSubstitutor.EMPTY || outerClassLocal != null) {
if (!myFieldInitializers.isEmpty() || !myLocalsForParameters.isEmpty()
|| classResolveSubstitutor != PsiSubstitutor.EMPTY || outerClassLocal != null) {
replaceReferences((PsiMember) child, substitutedParameters, outerClassLocal);
}
anonymousClass.addBefore(child, token);
@@ -138,11 +139,13 @@ class InlineToAnonymousConstructorProcessor {
anonymousClass.deleteChildRange(anonymousClass.getLBrace(), anonymousClass.getRBrace());
}
PsiNewExpression superNewExpression = (PsiNewExpression) myNewExpression.replace(superNewExpressionTemplate);
superNewExpression = (PsiNewExpression)ChangeContextUtil.decodeContextInfo(superNewExpression, superNewExpression.getAnonymousClass(), null);
superNewExpression = (PsiNewExpression)
ChangeContextUtil.decodeContextInfo(superNewExpression, superNewExpression.getAnonymousClass(), null);
PsiAnonymousClass newExpressionAnonymousClass = superNewExpression.getAnonymousClass();
if (newExpressionAnonymousClass != null &&
AnonymousCanBeLambdaInspection.isLambdaForm(newExpressionAnonymousClass, false, Collections.emptySet())) {
PsiExpression lambda = AnonymousCanBeLambdaInspection.replaceAnonymousWithLambda(superNewExpression, newExpressionAnonymousClass.getBaseClassType());
PsiExpression lambda =
AnonymousCanBeLambdaInspection.replaceAnonymousWithLambda(superNewExpression, newExpressionAnonymousClass.getBaseClassType());
JavaCodeStyleManager.getInstance(newExpressionAnonymousClass.getProject()).shortenClassReferences(superNewExpression.replace(lambda));
}
else {
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.codeInsight;
import com.intellij.openapi.application.ApplicationManager;
@@ -6,6 +6,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiExtensionMethod;
import com.intellij.psi.impl.light.LightDefaultConstructor;
import com.intellij.psi.impl.light.LightRecordCanonicalConstructor;
import com.intellij.psi.impl.light.LightRecordMember;
import com.intellij.psi.javadoc.PsiDocTag;
@@ -161,6 +162,9 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
if (refElement instanceof LightRecordCanonicalConstructor) {
return ((LightRecordCanonicalConstructor)refElement).getContainingClass();
}
if (refElement instanceof LightDefaultConstructor def) {
return def.getContainingClass();
}
}
return super.adjustReferenceOrReferencedElement(file, editor, offset, flags, refElement);
}
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.dependency;
import com.intellij.codeInsight.intention.IntentionAction;
@@ -138,6 +138,7 @@ public final class SuspiciousPackagePrivateAccessInspection extends AbstractBase
}
private void checkPackageLocalAccess(@NotNull UElement sourceNode, PsiJvmMember targetElement, final String accessType) {
if (targetElement instanceof SyntheticElement) return;
PsiElement sourcePsi = sourceNode.getSourcePsi();
if (sourcePsi != null) {
SuspiciousPackagePrivateAccess suspiciousAccess = verifyPackagePrivateAccess(sourcePsi, targetElement);
@@ -164,6 +165,7 @@ public final class SuspiciousPackagePrivateAccessInspection extends AbstractBase
}
private void checkOverridePackageLocal(@NotNull UMethod sourceNode, @NotNull PsiJvmMember targetElement) {
if (targetElement instanceof SyntheticElement) return;
PsiElement sourcePsi = sourceNode.getSourcePsi();
PsiElement nameIdentifier = UElementKt.getSourcePsiElement(sourceNode.getUastAnchor());
if (sourcePsi != null && nameIdentifier != null && targetElement.hasModifier(JvmModifier.PACKAGE_LOCAL)) {
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.psi;
import com.intellij.lang.jvm.JvmMethod;
@@ -87,6 +87,18 @@ public interface PsiMethod extends PsiMember, PsiNameIdentifierOwner, PsiModifie
@Override
boolean isConstructor();
/**
* Checks if the method is a default constructor.
* When a class contains no explicit constructor declarations, a default constructor is implicitly declared.
*
* @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-8.html#jls-8.8.9">JLS 8.8.9 Default Constructor</a>
* @see #isConstructor()
* @return true if the method is a default constructor, false otherwise
*/
default boolean isDefaultConstructor() {
return false;
}
/**
* Checks if the method accepts a variable number of arguments.
* The method is considered to be a variable arity method only if its last
@@ -0,0 +1,100 @@
// 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.psi.impl.light;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.impl.ElementPresentationUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.ui.IconManager;
import com.intellij.ui.PlatformIcons;
import com.intellij.ui.icons.RowIcon;
import com.intellij.util.BitUtil;
import com.intellij.util.VisibilityIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/// @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-8.html#jls-8.8.9">JLS 8.8.9 Default Constructor</a>
public class LightDefaultConstructor extends LightMethod implements SyntheticElement {
private static final Key<PsiMethod> DEFAULT_CONSTRUCTOR = new Key<>("default_constructor");
private LightDefaultConstructor(@NotNull PsiMethod method, @NotNull PsiClass containingClass) {
super(method.getManager(), method, containingClass);
}
@Override
public PsiElement getParent() {
return getContainingClass();
}
@Override
public PsiIdentifier getNameIdentifier() {
return getContainingClass().getNameIdentifier();
}
@Override
public int getTextOffset() {
return getNavigationElement().getTextOffset();
}
@NotNull
@Override
public PsiElement getNavigationElement() {
return getContainingClass();
}
@Override
public PsiFile getContainingFile() {
return getContainingClass().getContainingFile();
}
@Override
public Icon getElementIcon(int flags) {
Icon icon = IconManager.getInstance().getPlatformIcon(PlatformIcons.Method);
final RowIcon baseIcon = IconManager.getInstance().createLayeredIcon(this, icon, ElementPresentationUtil.getFlags(this, false));
if (BitUtil.isSet(flags, ICON_FLAG_VISIBILITY)) {
VisibilityIcons.setVisibilityIcon(getContainingClass().getModifierList(), baseIcon);
}
return baseIcon;
}
@Override
public boolean isDefaultConstructor() {
return true;
}
@Override
public String toString() {
return "LightDefaultConstructor:" + getName();
}
@Nullable
public static PsiMethod create(PsiClass aClass) {
PsiMethod constructor = aClass.getUserData(DEFAULT_CONSTRUCTOR);
if (constructor != null) return constructor;
if (aClass.isInterface()
|| aClass.isRecord()
|| aClass instanceof PsiCompiledElement // default constructor is physically present in compiled classes already
|| aClass instanceof PsiAnonymousClass
|| aClass instanceof PsiImplicitClass
|| aClass instanceof PsiTypeParameter
|| aClass.getClass().getSimpleName().contains("Decompiled") // Hack because Kotlin library classes are not PsiCompiledElements
) {
return null;
}
String className = aClass.getName();
if (className == null || aClass.getConstructors().length > 0) return null;
PsiMethod nonPhysical = JavaPsiFacade.getElementFactory(aClass.getProject()).createConstructor(className, aClass);
PsiModifierList classModifierList = aClass.getModifierList();
if (classModifierList != null) {
String modifier = PsiUtil.getAccessModifier(PsiUtil.getAccessLevel(classModifierList));
nonPhysical.getModifierList().setModifierProperty(modifier, true);
}
LightDefaultConstructor defaultConstructor = new LightDefaultConstructor(nonPhysical, aClass);
aClass.putUserData(DEFAULT_CONSTRUCTOR, defaultConstructor);
return defaultConstructor;
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.psi.impl.source.resolve;
import com.intellij.openapi.diagnostic.Logger;
@@ -7,6 +7,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
import com.intellij.psi.impl.light.LightDefaultConstructor;
import com.intellij.psi.impl.source.resolve.graphInference.PsiGraphInferenceHelper;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
@@ -67,9 +68,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, substitutor);
for (PsiMethod constructor : aClass.getConstructors()) {
PsiMethod[] constructors = aClass.getConstructors();
for (PsiMethod constructor : constructors) {
if (!processor.execute(constructor, state)) break;
}
if (constructors.length == 0) {
PsiMethod defaultConstructor = LightDefaultConstructor.create(aClass);
if (defaultConstructor != null) processor.execute(defaultConstructor, state);
}
return processor.getResult();
}
@@ -306,7 +306,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)getParent();
MethodResolverProcessor processor = new MethodResolverProcessor(methodCall, containingFile);
try {
PsiScopesUtil.setupAndRunProcessor(processor, methodCall, false);
PsiScopesUtil.setupAndRunProcessor(processor, methodCall, true);
}
catch (MethodProcessorSetupFailedException e) {
return JavaResolveResult.EMPTY_ARRAY;
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.psi.scope.processor;
import com.intellij.pom.java.LanguageLevel;
@@ -87,7 +87,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
}
protected @NotNull MethodCandidateInfo createCandidateInfo(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor,
final boolean staticProblem, final boolean accessible, final boolean varargs) {
boolean staticProblem, boolean accessible, boolean varargs) {
return new VarargsAwareMethodCandidateInfo(method, substitutor, accessible, staticProblem, getArgumentList(), myCurrentFileContext,
getTypeArguments(), getLanguageLevel(), varargs);
}
@@ -162,4 +162,9 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
return myVarargs;
}
}
@Override
public void forceAddResult(@NotNull PsiMethod method) {
add(createCandidateInfo(method, PsiSubstitutor.EMPTY, false, true, method.isVarArgs()));
}
}
@@ -1,5 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.psi.scope.util;
import com.intellij.lang.jvm.types.JvmReferenceType;
@@ -9,6 +8,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.light.LightDefaultConstructor;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
@@ -21,14 +21,12 @@ import com.intellij.psi.scope.processor.MethodsProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class PsiScopesUtil {
private static final Logger LOG = Logger.getInstance(PsiScopesUtil.class);
@@ -36,16 +34,14 @@ public final class PsiScopesUtil {
private PsiScopesUtil() {
}
public static boolean treeWalkUp(@NotNull PsiScopeProcessor processor,
@NotNull PsiElement entrance,
@Nullable PsiElement maxScope) {
public static boolean treeWalkUp(@NotNull PsiScopeProcessor processor, @NotNull PsiElement entrance, @Nullable PsiElement maxScope) {
return treeWalkUp(processor, entrance, maxScope, ResolveState.initial());
}
public static boolean treeWalkUp(final @NotNull PsiScopeProcessor processor,
final @NotNull PsiElement entrance,
final @Nullable PsiElement maxScope,
final @NotNull ResolveState state) {
public static boolean treeWalkUp(@NotNull PsiScopeProcessor processor,
@NotNull PsiElement entrance,
@Nullable PsiElement maxScope,
@NotNull ResolveState state) {
if (!entrance.isValid()) {
LOG.error(new PsiInvalidElementAccessException(entrance));
}
@@ -215,7 +211,7 @@ public final class PsiScopesUtil {
public static void setupAndRunProcessor(@NotNull MethodsProcessor processor,
@NotNull PsiCallExpression call,
boolean dummyImplicitConstructor)
throws MethodProcessorSetupFailedException {
throws MethodProcessorSetupFailedException {
if (call instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)call;
final PsiJavaCodeReferenceElement ref = methodCall.getMethodExpression();
@@ -240,7 +236,7 @@ public final class PsiScopesUtil {
aClass.processDeclarations(processor, ResolveState.initial(), null, call);
if (dummyImplicitConstructor) {
processDummyConstructor(processor, aClass);
processDefaultConstructor(processor, aClass);
}
}
else if (keyword.getTokenType() == JavaTokenType.SUPER_KEYWORD) {
@@ -279,7 +275,7 @@ public final class PsiScopesUtil {
if (!processor.execute(constructor, state)) return;
}
if (dummyImplicitConstructor) processDummyConstructor(processor, superClass);
if (dummyImplicitConstructor) processDefaultConstructor(processor, superClass);
}
}
else {
@@ -370,7 +366,7 @@ public final class PsiScopesUtil {
aClass.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, result.getSubstitutor()), null, call);
if (dummyImplicitConstructor) {
processDummyConstructor(processor, aClass);
processDefaultConstructor(processor, aClass);
}
}
}
@@ -425,8 +421,8 @@ public final class PsiScopesUtil {
return false;
}
private static boolean processQualifierType(final @NotNull PsiType type,
final MethodsProcessor processor,
private static boolean processQualifierType(@NotNull PsiType type,
MethodsProcessor processor,
PsiManager manager,
PsiMethodCallExpression call) throws MethodProcessorSetupFailedException {
PsiUtil.ensureValidType(type);
@@ -479,23 +475,11 @@ public final class PsiScopesUtil {
return resolve.processDeclarations(processor, state, methodCall, methodCall);
}
private static void processDummyConstructor(MethodsProcessor processor, PsiClass aClass) {
if (aClass instanceof PsiAnonymousClass) return;
try {
PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length != 0) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject());
final PsiMethod dummyConstructor = factory.createConstructor();
PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
if (nameIdentifier != null) {
Objects.requireNonNull(dummyConstructor.getNameIdentifier()).replace(nameIdentifier);
}
processor.forceAddResult(dummyConstructor);
}
catch (IncorrectOperationException e) {
LOG.error(e);
private static void processDefaultConstructor(MethodsProcessor processor, PsiClass aClass) {
if (aClass.getConstructors().length != 0) {
return;
}
PsiMethod defaultConstructor = LightDefaultConstructor.create(aClass);
if (defaultConstructor != null) processor.forceAddResult(defaultConstructor);
}
}
@@ -1,6 +1,9 @@
import java.util.function.Consumer;
class WrongNumberOfArguments {
WrongNumberOfArguments() {
super<error descr="Expected no arguments but found 1">(1)</error>;
}
void fun1(String str, Consumer<String> onFinish) { }
void getStr(String asd) { }
@@ -1,4 +1,4 @@
// "Remove redundant arguments" "true-preview"
// "Remove redundant argument to call 'A()'" "true-preview"
class A {
private void method() {
new A();
@@ -1,4 +1,4 @@
// "Remove redundant arguments" "true-preview"
// "Remove redundant argument to call 'A()'" "true-preview"
class A {
private void method() {
new A("<caret>");
@@ -2,8 +2,9 @@
import java.io.*;
class a {
int k;
boolean k = new File("1.tmp").delete();
private int run() {
new a();
return 0;
}
@@ -2,7 +2,7 @@
import java.io.*;
class a {
int k;
boolean k = new File("1.tmp").delete();
private int run() {
Object <caret>oo = (Object) new a();
@@ -0,0 +1,6 @@
public class UtilityClassWithDefaultConstructor {
public static int util() {
return 1;
}
}
@@ -12,4 +12,19 @@ public class CatchTypeReference {
private static class TypeReference<T> {
}
}
class CatchTypeReference2 {
void foo(int i) {
TypeReference<?> targetType = switch (i) {
case 2231 -> new TypeReference<List<Boolean>>() {
};
default -> new TypeReference<List<String>>() {
};
};
}
private static class TypeReference<T> {
private TypeReference() {
}
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// 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.codeInsight.navigation;
import com.intellij.openapi.actionSystem.IdeActions;
@@ -9,8 +9,8 @@ public class GotoEnumConstructorTest extends LightJavaCodeInsightFixtureTestCase
public void testGotoDeclarationOnEnumConstantDoesntNavigateToEnumClass() {
doTest(
"enum A { G<caret>; }",
"enum A { G<caret>; }"
"enum A { G<caret>G; }",
"enum A { G<caret>G; }"
);
}
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.psi.resolve;
import com.intellij.openapi.application.WriteAction;
@@ -209,6 +209,27 @@ public class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase {
assertNotNull(file.getStub());
}
public void testLibraryClassWithoutConstructors() {
VirtualFile lib =
LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/libResolve/classWithoutConstructors");
PsiTestUtil.addLibrary(getModule(), "lib", lib.getPath(), new String[] {"/test.jar!/"}, ArrayUtil.EMPTY_STRING_ARRAY);
myFixture.configureByText("p/Generous.java", """
package p;
import com.pack.HiddenConstructor;
import com.pack.ValueClass;
class Generous {
static void main(){
HiddenConstructor h = new HiddenConstructor<error descr="Cannot resolve constructor 'HiddenConstructor()'">()</error>;
ValueClass v = new ValueClass<error descr="Cannot resolve constructor 'ValueClass()'">()</error>;
}
}
""");
myFixture.checkHighlighting();
}
public void testDirectoryWithClassFilesInsideProjectContent() {
String testData = PathManagerEx.getTestDataPath() + "/codeInsight/interJarDependencies";
myFixture.setTestDataPath(testData);
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.classlayout;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -23,10 +23,7 @@ public class UtilityClassWithPublicConstructorInspectionTest extends LightJavaCo
myFixture.testHighlighting(getTestName(false) + ".java");
}
public void testUtilityClassWithPublicConstructorInspection() {
doTest();
}
public void testUtilityClassWithInheritor() {
doTest();
}
public void testUtilityClassWithPublicConstructorInspection() { doTest(); }
public void testUtilityClassWithInheritor() { doTest(); }
public void testUtilityClassWithDefaultConstructor() { doTest(); }
}
@@ -1,11 +1,9 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.jdk;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.module.LanguageLevelUtil;
import com.intellij.openapi.module.Module;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -36,17 +34,17 @@ public class ForwardCompatibilityInspectionTest extends LightJavaInspectionTestC
}
public void testAssert() {
withLevel(LanguageLevel.JDK_1_3, this::doTest);
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_3, this::doTest);
}
public void testEnum() {
withLevel(LanguageLevel.JDK_1_3, this::doTest);
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_3, this::doTest);
}
public void testUnqualifiedYield() { doTest(); }
public void testQualifiedYieldWithUnexpectedToken() {
withLevel(LanguageLevel.JDK_1_8, () -> {
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_8, () -> {
myFixture.configureByFile(getTestName(false) + ".java");
List<HighlightInfo> list = ContainerUtil.filter(myFixture.doHighlighting(HighlightSeverity.WARNING), it -> it.getSeverity().equals(HighlightSeverity.WARNING));
assertEquals(1, list.size());
@@ -65,24 +63,12 @@ public class ForwardCompatibilityInspectionTest extends LightJavaInspectionTestC
public void testRestrictedKeywordWarning() { doTest(); }
public void testLoneSemicolon() { withLevel(LanguageLevel.JDK_20, this::doTest); }
public void testLoneSemicolon() { IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_20, this::doTest); }
public void testModuleInfoWarning() {
withLevel(LanguageLevel.JDK_1_9, () -> {
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_9, () -> {
myFixture.configureByFile("module-info.java");
myFixture.testHighlighting(true, false, false);
});
}
public void withLevel(LanguageLevel languageLevel, Runnable runnable) {
Module module = getModule();
LanguageLevel prev = LanguageLevelUtil.getCustomLanguageLevel(module);
IdeaTestUtil.setModuleLanguageLevel(module, languageLevel);
try {
runnable.run();
}
finally {
IdeaTestUtil.setModuleLanguageLevel(module, prev);
}
}
}
@@ -13,7 +13,6 @@ import de.plushnikov.intellij.plugin.problem.LombokProblemInstance;
import de.plushnikov.intellij.plugin.processor.LombokProcessorManager;
import de.plushnikov.intellij.plugin.processor.Processor;
import de.plushnikov.intellij.plugin.processor.ValProcessor;
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
import de.plushnikov.intellij.plugin.quickfix.PsiQuickFixFactory;
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
import org.jetbrains.annotations.NotNull;
@@ -112,32 +111,5 @@ public final class LombokInspection extends LombokJavaInspectionBase {
}
}
}
/**
* Check MethodCallExpressions for calls for default (argument less) constructor
* Produce an error if resolved constructor method is build by lombok and contains some arguments
*/
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression methodCall) {
super.visitMethodCallExpression(methodCall);
PsiExpressionList list = methodCall.getArgumentList();
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
boolean isThisOrSuper = referenceToMethod.getReferenceNameElement() instanceof PsiKeyword;
final int parameterCount = list.getExpressions().length;
if (isThisOrSuper && parameterCount == 0) {
JavaResolveResult[] results = referenceToMethod.multiResolve(true);
JavaResolveResult resolveResult = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof LombokLightMethodBuilder &&
((LombokLightMethodBuilder)resolved).getParameterList().getParameters().length != 0) {
holder.registerProblem(methodCall, LombokBundle.message("inspection.message.default.constructor.doesn.t.exist"),
ProblemHighlightType.ERROR);
}
}
}
}
}
@@ -9,7 +9,6 @@ dialog.message.logger.field.s.not.private.sfinal.field.named.s.refactor.anyway=L
dialog.title.attention=Attention!
dialog.message.this.element.cannot.be.renamed=This element cannot be renamed.
inspection.message.lombok.annotation.deprecated.not.supported=Lombok''s annotation ''{0}'' is deprecated and not supported by Lombok plugin anymore. Use ''{1}'' instead.
inspection.message.default.constructor.doesn.t.exist=Default constructor doesn't exist
inspection.message.slf4j.logger.defined.explicitly=Slf4j Logger is defined explicitly. Use Lombok @Slf4j annotation instead.
intention.name.replace.with.lombok=Replace with Lombok
color.settings.comment=Comment
@@ -9,7 +9,7 @@ public class ClassWithData {
public static class B extends A {
public B() {
<error descr="Default constructor doesn't exist">super()</error>;
super<error descr="Expected 2 arguments but found 0">()</error>;
}
public B(int i) {
@@ -10,7 +10,7 @@ public class ClassWithLombokConstructor {
public static class B extends A {
public B() {
<error descr="Default constructor doesn't exist">super()</error>;
super<error descr="Expected 2 arguments but found 0">()</error>;
}
public B(int i) {
@@ -212,16 +212,7 @@ class JavaConstructorUCallExpression(
get() = null
override fun resolve(): PsiMethod? = sourcePsi.resolveMethod()
override fun multiResolve(): Iterable<ResolveResult> {
val methodResolve = sourcePsi.resolveMethodGenerics()
if (methodResolve != JavaResolveResult.EMPTY) {
// if there is a non-default constructor
return listOf<ResolveResult>(methodResolve)
}
// unable to resolve constructor method - resolve to class
val classResolve = sourcePsi.classReference?.multiResolve(false) ?: emptyArray()
return classResolve.asIterable()
}
override fun multiResolve() = sourcePsi.multiResolve(false).asIterable()
}
@ApiStatus.Internal
@@ -14,7 +14,7 @@ UClass (name = A) -> USimpleNameReferenceExpression (identifier = B) -> PsiClass
UField (name = a) -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:A: null
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> USimpleNameReferenceExpression (identifier = A) -> PsiClass:A: A
UTypeReferenceExpression (name = C) -> USimpleNameReferenceExpression (identifier = C) -> PsiClass:C: C
UField (name = c) -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> null: null
UField (name = c) -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> LightDefaultConstructor:C: null
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> USimpleNameReferenceExpression (identifier = C) -> PsiClass:C: C
UTypeReferenceExpression (name = A) -> USimpleNameReferenceExpression (identifier = A) -> PsiClass:A: A
UReturnExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> PsiMethod:A: null
@@ -1,5 +1,5 @@
UMethod (name = test) -> UTypeReferenceExpression (name = void) -> [] ~= []
UMethod (name = test) -> UBlockExpression -> [] ~= []
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] PsiClassImpl ~= []
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] PsiClassImpl ~= []
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] LightDefaultConstructor ~= LightDefaultConstructor:Foo
UBlockExpression -> UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> [M] LightDefaultConstructor ~= LightDefaultConstructor:Foo
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) -> USimpleNameReferenceExpression (identifier = Foo) -> [M] PsiClassImpl ~= PsiClass:Foo
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.uast.test.java
import com.intellij.psi.*
@@ -190,7 +176,7 @@ class JavaUastApiTest : AbstractJavaUastTest() {
fun testDefaultConstructorRef() = doTest("Simple/ComplexCalls.java") { _, file ->
val call = file.findElementByTextFromPsi<UCallExpression>("new C()")
TestCase.assertEquals(UastCallKind.CONSTRUCTOR_CALL, call.kind)
TestCase.assertEquals(null, call.resolve())
TestCase.assertEquals("C", call.resolve()?.name)
TestCase.assertEquals("C", (call.classReference?.resolve() as? PsiClass)?.qualifiedName)
}