mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: care about generic class when replacing constructor with builder (IDEA-359490)
GitOrigin-RevId: 7aab29e572eb6da07d2fec202c886500fd944f6a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
84a8688289
commit
ba54dfd721
+37
-8
@@ -13,6 +13,7 @@ import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -40,6 +41,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
@@ -146,7 +149,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
|
||||
super.performRefactoring(usageInfos);
|
||||
|
||||
final PsiMethod method = createMethodSignature(createMethodName());
|
||||
final PsiMethod method = createBuildMethod(createMethodName());
|
||||
if (builderClass.findMethodBySignature(method, false) == null) {
|
||||
builderClass.add(method);
|
||||
}
|
||||
@@ -225,18 +228,44 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
}
|
||||
}
|
||||
|
||||
private PsiMethod createMethodSignature(String createMethodName) {
|
||||
private PsiMethod createBuildMethod(String createMethodName) {
|
||||
JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myProject);
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
|
||||
final PsiClass aClass = myConstructors[0].getContainingClass();
|
||||
assert aClass != null;
|
||||
PsiType[] typeArguments = Stream.of(aClass.getTypeParameters())
|
||||
.map(myElementFactory::createType)
|
||||
.toArray(PsiType[]::new);
|
||||
PsiMethod method = myElementFactory.createMethod(createMethodName, myElementFactory.createType(aClass, typeArguments));
|
||||
|
||||
final StringBuilder bodyText = new StringBuilder();
|
||||
final PsiMethod constructor = getWorkingConstructor();
|
||||
bodyText.append("{\n return new ").append(constructor.getName());
|
||||
if (typeArguments.length > 0) {
|
||||
if (PsiUtil.isAvailable(JavaFeature.DIAMOND_TYPES, aClass)) {
|
||||
bodyText.append("<>");
|
||||
}
|
||||
else {
|
||||
bodyText.append('<');
|
||||
boolean comma = false;
|
||||
for (PsiType argument : typeArguments) {
|
||||
bodyText.append(comma ? ", " : "").append(argument.getCanonicalText());
|
||||
comma = true;
|
||||
}
|
||||
bodyText.append('>');
|
||||
}
|
||||
}
|
||||
bodyText.append("(");
|
||||
boolean comma = false;
|
||||
for (PsiParameter parameter : constructor.getParameterList().getParameters()) {
|
||||
final String pureParamName = styleManager.variableNameToPropertyName(parameter.getName(), VariableKind.PARAMETER);
|
||||
if (!buf.isEmpty()) buf.append(", ");
|
||||
buf.append(myParametersMap.get(pureParamName).getFieldName());
|
||||
bodyText.append(comma ? ", " : "").append(myParametersMap.get(pureParamName).getFieldName());
|
||||
comma = true;
|
||||
}
|
||||
return myElementFactory.createMethodFromText("public " + constructor.getName() + " " + createMethodName + "(){" +
|
||||
"\n return new " + constructor.getName() + "(" + buf + ");" +
|
||||
"\n}", constructor);
|
||||
bodyText.append(");\n}");
|
||||
PsiCodeBlock body = myElementFactory.createCodeBlockFromText(bodyText.toString(), method);
|
||||
Objects.requireNonNull(method.getBody()).replace(body);
|
||||
return method;
|
||||
}
|
||||
|
||||
private PsiMethod getWorkingConstructor() {
|
||||
|
||||
+7
-18
@@ -1,19 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
@@ -21,11 +6,13 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.PsiDiamondTypeUtil;
|
||||
import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReplaceConstructorWithSettersChainInfo extends FixableUsageInfo {
|
||||
private final String myBuilderClass;
|
||||
@@ -65,9 +52,11 @@ public class ReplaceConstructorWithSettersChainInfo extends FixableUsageInfo {
|
||||
buf.append(data.getSetterName()).append("(").append(arg).append(").");
|
||||
}
|
||||
}
|
||||
|
||||
PsiNewExpression expression = (PsiNewExpression)PsiDiamondTypeUtil.expandTopLevelDiamondsInside(expr);
|
||||
PsiReferenceParameterList typeArguments = Objects.requireNonNull(expression.getClassReference()).getParameterList();
|
||||
assert typeArguments != null;
|
||||
final PsiExpression settersChain = elementFactory.createExpressionFromText(
|
||||
"new " + myBuilderClass + "()." + buf + "create" + StringUtil.capitalize(constructor.getName()) + "()",
|
||||
"new " + myBuilderClass + typeArguments.getText() + "()." + buf + "create" + StringUtil.capitalize(constructor.getName()) + "()",
|
||||
null);
|
||||
|
||||
styleManager.shortenClassReferences(expr.replace(settersChain));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 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-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationTargetUtil;
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PropertyUtilBase {
|
||||
|
||||
@@ -604,9 +605,17 @@ public class PropertyUtilBase {
|
||||
VariableKind kind = codeStyleManager.getVariableKind(field);
|
||||
String propertyName = codeStyleManager.variableNameToPropertyName(name, kind);
|
||||
String setName = suggestSetterName(field);
|
||||
PsiMethod setMethod = factory
|
||||
.createMethodFromText(factory.createMethod(setName, returnSelf ? factory.createType(containingClass) : PsiTypes.voidType()).getText(),
|
||||
field);
|
||||
|
||||
PsiMethod setMethod;
|
||||
if (returnSelf) {
|
||||
PsiType[] typeArguments = Stream.of(containingClass.getTypeParameters())
|
||||
.map(factory::createType)
|
||||
.toArray(PsiType[]::new);
|
||||
setMethod = factory.createMethod(setName, factory.createType(containingClass, typeArguments));
|
||||
}
|
||||
else {
|
||||
setMethod = factory.createMethod(setName, PsiTypes.voidType());
|
||||
}
|
||||
String parameterName = codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER);
|
||||
PsiParameter param = factory.createParameter(parameterName, AnnotationTargetUtil.keepStrictlyTypeUseAnnotations(field.getModifierList(), field.getType()));
|
||||
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
public class Builder<T> {
|
||||
private T t;
|
||||
|
||||
public Builder setT(T t) {
|
||||
public Builder<T> setT(T t) {
|
||||
this.t = t;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Test createTest() {
|
||||
return new Test(t);
|
||||
public Test<T> createTest() {
|
||||
return new Test<>(t);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
public class Test<T> {
|
||||
public Test(T t){}
|
||||
void foo(){}
|
||||
public static void main(T args){
|
||||
new Builder().setT(args).createTest().foo();
|
||||
public static void main(String[] args){
|
||||
new Builder<String>().setT(args[0]).createTest().foo();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
public class Test<T> {
|
||||
public Test(T t){}
|
||||
void foo(){}
|
||||
public static void main(T args){
|
||||
new Test(args).foo();
|
||||
public static void main(String[] args){
|
||||
new Test<>(args[0]).foo();
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -4,17 +4,17 @@ public class Builder<T extends Serializable> {
|
||||
private String name;
|
||||
private Class<T> clazz;
|
||||
|
||||
public Builder setName(String name) {
|
||||
public Builder<T> setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setClazz(Class<T> clazz) {
|
||||
public Builder<T> setClazz(Class<T> clazz) {
|
||||
this.clazz = clazz;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Test createTest() {
|
||||
return new Test(name, clazz);
|
||||
public Test<T> createTest() {
|
||||
return new Test<>(name, clazz);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,5 +9,5 @@ public class Test<T extends Serializable> {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public static final Test<Boolean> BOOLEAN = new Builder().setName("b").setClazz(Boolean.class).createTest();
|
||||
public static final Test<Boolean> BOOLEAN = new Builder<Boolean>().setName("b").setClazz(Boolean.class).createTest();
|
||||
}
|
||||
Reference in New Issue
Block a user