Java: enable inlining on chaining vararg constructors (IDEA-376690, IDEA-376692)

GitOrigin-RevId: 2594b3ca241b7a4a0ca7e362482f5b606486f254
This commit is contained in:
Bas Leijdekkers
2025-08-07 16:25:03 +00:00
committed by intellij-monorepo-bot
parent da71af67ec
commit 7d5bd541d5
11 changed files with 122 additions and 70 deletions
@@ -1,5 +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.refactoring.inline;
import com.intellij.CommonBundle;
@@ -100,13 +99,7 @@ public final class InlineMethodHandler extends JavaInlineActionHandler {
}
if (method.isConstructor()) {
if (method.isVarArgs()) {
String message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.to.vararg.constructors", getRefactoringName());
CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.INLINE_CONSTRUCTOR);
return;
}
final boolean chainingConstructor = InlineUtil.isChainingConstructor(method);
if (!chainingConstructor) {
if (!InlineUtil.isChainingConstructor(method)) {
InlineObjectProcessor processor = InlineObjectProcessor.create(reference, method);
if (processor != null) {
if (Messages.showOkCancelDialog(JavaRefactoringBundle.message("inline.method.object.suggestion.message"),
@@ -565,28 +565,8 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
PsiMethod oldConstructor = constructorCall.resolveMethod();
LOG.assertTrue(oldConstructor != null);
oldConstructor = (PsiMethod)oldConstructor.getNavigationElement();
PsiExpression[] instanceCreationArguments = constructorCall.getArgumentList().getExpressions();
if (oldConstructor.isVarArgs()) { //wrap with explicit array
final PsiParameter[] parameters = oldConstructor.getParameterList().getParameters();
final PsiType varargType = parameters[parameters.length - 1].getType();
if (varargType instanceof PsiEllipsisType) {
final PsiType arrayType =
constructorCall.resolveMethodGenerics().getSubstitutor().substitute(((PsiEllipsisType)varargType).getComponentType());
final PsiExpression[] exprs = new PsiExpression[parameters.length];
System.arraycopy(instanceCreationArguments, 0, exprs, 0, parameters.length - 1);
StringBuilder varargs = new StringBuilder();
for (int i = parameters.length - 1; i < instanceCreationArguments.length; i++) {
if (!varargs.isEmpty()) varargs.append(", ");
varargs.append(instanceCreationArguments[i].getText());
}
exprs[parameters.length - 1] = JavaPsiFacade.getElementFactory(constructorCall.getProject())
.createExpressionFromText("new " + arrayType.getCanonicalText() + "[]{" + varargs + "}", constructorCall);
instanceCreationArguments = exprs;
}
}
PsiExpression[] arguments = CommonJavaRefactoringUtil.getNonVarargArguments(constructorCall);
PsiStatement[] statements = oldConstructor.getBody().getStatements();
LOG.assertTrue(statements.length == 1 && statements[0] instanceof PsiExpressionStatement);
PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
@@ -594,14 +574,16 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
ChangeContextUtil.encodeContextInfo(expression, true);
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression.copy();
final PsiExpression[] args = methodCall.getArgumentList().getExpressions();
for (PsiExpression arg : args) {
replaceParameterReferences(arg, oldConstructor, instanceCreationArguments);
for (PsiExpression arg : methodCall.getArgumentList().getExpressions()) {
replaceParameterReferences(arg, oldConstructor, arguments);
}
try {
final PsiExpressionList exprList = (PsiExpressionList) constructorCall.getArgumentList().replace(methodCall.getArgumentList());
ChangeContextUtil.decodeContextInfo(exprList, PsiTreeUtil.getParentOfType(constructorCall, PsiClass.class), null);
if (!exprList.isEmpty()) {
PsiExpression[] expressions = exprList.getExpressions();
CommonJavaRefactoringUtil.tryToInlineArrayCreationForVarargs(expressions[expressions.length - 1]);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
@@ -22,7 +22,6 @@ import com.intellij.refactoring.util.InlineUtil;
import com.intellij.util.CommonJavaRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -296,40 +295,15 @@ class InlineToAnonymousConstructorProcessor {
}
private PsiExpression[] initConstructorArguments() {
PsiExpressionList argumentList = myNewExpression.getArgumentList();
return argumentList != null ? argumentList.getExpressions() : PsiExpression.EMPTY_ARRAY;
return CommonJavaRefactoringUtil.getNonVarargArguments(myNewExpression);
}
private void generateLocalsForArguments() {
for (int i = 0; i < myConstructorArguments.length; i++) {
PsiExpression expr = myConstructorArguments[i];
PsiParameter parameter = myConstructorParameters.getParameters()[i];
if (parameter.isVarArgs()) {
PsiEllipsisType ellipsisType = (PsiEllipsisType)parameter.getType();
PsiType baseType = ellipsisType.getComponentType();
@NonNls StringBuilder exprBuilder = new StringBuilder("new ");
exprBuilder.append(baseType.getCanonicalText());
exprBuilder.append("[] { }");
try {
PsiNewExpression newExpr = (PsiNewExpression) myElementFactory.createExpressionFromText(exprBuilder.toString(), myClass);
PsiArrayInitializerExpression arrayInitializer = newExpr.getArrayInitializer();
assert arrayInitializer != null;
for(int j = i; j < myConstructorArguments.length; j++) {
arrayInitializer.add(myConstructorArguments[j]);
}
PsiLocalVariable variable = generateLocal(parameter.getName(), ellipsisType.toArrayType(), newExpr);
myLocalsForParameters.put(parameter, variable);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
break;
}
else if (!isConstant(expr)) {
PsiLocalVariable variable = generateLocal(parameter.getName(), parameter.getType(), expr);
myLocalsForParameters.put(parameter, variable);
if (!isConstant(expr)) {
myLocalsForParameters.put(parameter, generateLocal(parameter.getName(), parameter.getType(), expr));
}
}
}