mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-86826 Inline method with empty varargs
This commit is contained in:
+18
-7
@@ -368,19 +368,22 @@ public class GrClosureSignatureUtil {
|
||||
boolean partial) {
|
||||
if (checkForOnlyMapParam(signature, args.length)) return ArgInfo.empty_array();
|
||||
GrClosureParameter[] params = signature.getParameters();
|
||||
if (args.length > params.length && !signature.isVarargs()) return null;
|
||||
if (args.length > params.length && !signature.isVarargs() && !partial) return null;
|
||||
int optional = getOptionalParamCount(signature, false);
|
||||
int notOptional = params.length - optional;
|
||||
if (signature.isVarargs()) notOptional--;
|
||||
if (notOptional > args.length && !partial) return null;
|
||||
|
||||
final ArgInfo<Arg>[] map = mapSimple(params, args, typeComputer, context);
|
||||
final ArgInfo<Arg>[] map = mapSimple(params, args, typeComputer, context, false);
|
||||
if (map != null) return map;
|
||||
|
||||
if (signature.isVarargs()) {
|
||||
return new ParameterMapperForVararg<Arg>(context, params, args, typeComputer).isApplicable();
|
||||
}
|
||||
return null;
|
||||
|
||||
if (!partial) return null;
|
||||
|
||||
return mapSimple(params, args, typeComputer, context, true);
|
||||
}
|
||||
|
||||
private static boolean checkForOnlyMapParam(@NotNull GrClosureSignature signature, final int argCount) {
|
||||
@@ -395,19 +398,25 @@ public class GrClosureSignatureUtil {
|
||||
private static <Arg> ArgInfo<Arg>[] mapSimple(@NotNull GrClosureParameter[] params,
|
||||
@NotNull Arg[] args,
|
||||
@NotNull Function<Arg, PsiType> typeComputer,
|
||||
@NotNull GroovyPsiElement context) {
|
||||
@NotNull GroovyPsiElement context,
|
||||
boolean partial) {
|
||||
if (args.length > params.length && !partial) return null;
|
||||
|
||||
ArgInfo<Arg>[] map = new ArgInfo[params.length];
|
||||
int optional = getOptionalParamCount(params, false);
|
||||
int notOptional = params.length - optional;
|
||||
int optionalArgs = args.length - notOptional;
|
||||
|
||||
if (notOptional > args.length && !partial) return null;
|
||||
|
||||
int cur = 0;
|
||||
for (int i = 0; i < args.length; i++, cur++) {
|
||||
while (optionalArgs == 0 && cur < params.length && params[cur].isOptional()) {
|
||||
cur++;
|
||||
}
|
||||
if (cur == params.length) return null;
|
||||
if (cur == params.length) return partial ? map : null;
|
||||
if (params[cur].isOptional()) optionalArgs--;
|
||||
if (!isAssignableByConversion(params[cur].getType(), typeComputer.fun(args[i]), context)) return null;
|
||||
if (!isAssignableByConversion(params[cur].getType(), typeComputer.fun(args[i]), context)) return partial ? map : null;
|
||||
map[cur] = new ArgInfo<Arg>(args[i]);
|
||||
}
|
||||
for (int i = 0; i < map.length; i++) {
|
||||
@@ -668,7 +677,9 @@ public class GrClosureSignatureUtil {
|
||||
if (hasNamedArgs) {
|
||||
if (params.length == 0) return null;
|
||||
PsiType type = params[0].getType();
|
||||
if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) {
|
||||
if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP) ||
|
||||
type == null ||
|
||||
type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
innerArgs.add(new InnerArg(new GrMapType(context.getResolveScope()), namedArgs));
|
||||
}
|
||||
else {
|
||||
|
||||
+56
-70
@@ -32,18 +32,18 @@ import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.inline.InlineOptionsDialog;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
|
||||
@@ -53,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
|
||||
@@ -431,65 +432,76 @@ public class GroovyInlineMethodUtil {
|
||||
* @param method given method
|
||||
*/
|
||||
public static void replaceParametersWithArguments(GrCallExpression call, GrMethod method) throws IncorrectOperationException {
|
||||
GrParameter[] parameters = method.getParameters();
|
||||
if (parameters.length == 0) return;
|
||||
|
||||
GrArgumentList argumentList = call.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
setDefaultValuesToParameters(method, null, call);
|
||||
return;
|
||||
}
|
||||
// first parameter may have map type
|
||||
final GrNamedArgument[] namedArguments = argumentList.getNamedArguments();
|
||||
boolean firstParamIsMap = namedArguments.length > 0;
|
||||
|
||||
ArrayList<GrExpression> exprs = new ArrayList<GrExpression>();
|
||||
if (firstParamIsMap) {
|
||||
StringBuilder mapArg = new StringBuilder();
|
||||
mapArg.append('[');
|
||||
for (GrNamedArgument namedArgument : namedArguments) {
|
||||
mapArg.append(namedArgument.getText()).append(", ");
|
||||
}
|
||||
Project project = call.getProject();
|
||||
|
||||
mapArg.delete(mapArg.length() - 2, mapArg.length());
|
||||
mapArg.append(']');
|
||||
exprs.add(GroovyPsiElementFactory.getInstance(call.getProject()).createExpressionFromText(mapArg.toString()));
|
||||
GrClosureSignature signature = GrClosureSignatureUtil.createSignature(call);
|
||||
if (signature == null) {
|
||||
return;
|
||||
}
|
||||
GrClosureSignatureUtil.ArgInfo<PsiElement>[] infos = GrClosureSignatureUtil.mapParametersToArguments(
|
||||
signature,
|
||||
call.getNamedArguments(),
|
||||
call.getExpressionArguments(),
|
||||
call.getClosureArguments(),
|
||||
call, true, false
|
||||
);
|
||||
if (infos == null) return;
|
||||
|
||||
ContainerUtil.addAll(exprs, argumentList.getExpressionArguments());
|
||||
ContainerUtil.addAll(exprs, call.getClosureArguments());
|
||||
for (int i = 0; i < infos.length; i++) {
|
||||
GrClosureSignatureUtil.ArgInfo<PsiElement> argInfo = infos[i];
|
||||
GrParameter parameter = parameters[i];
|
||||
|
||||
GrParameter[] parameters = method.getParameters();
|
||||
if (parameters.length == 0) return;
|
||||
GrParameter firstParam = parameters[0];
|
||||
while (exprs.size() > parameters.length) {
|
||||
exprs.remove(exprs.size() - 1);
|
||||
}
|
||||
|
||||
int nonDefault = 0;
|
||||
for (GrParameter parameter : parameters) {
|
||||
if (!(firstParam == parameter && firstParamIsMap)) {
|
||||
if (parameter.getDefaultInitializer() == null) {
|
||||
nonDefault++;
|
||||
}
|
||||
final GrExpression arg = inferArg(signature, parameters, parameter, argInfo, project);
|
||||
if (arg != null) {
|
||||
replaceAllOccurrencesWithExpression(method, call, arg, parameter);
|
||||
}
|
||||
}
|
||||
nonDefault = exprs.size() - nonDefault - (firstParamIsMap ? 1 : 0);
|
||||
// Parameters that will be replaced by its default values
|
||||
Set<String> nameFilter = new HashSet<String>();
|
||||
for (GrParameter parameter : parameters) {
|
||||
if (!(firstParam == parameter && firstParamIsMap)) {
|
||||
GrExpression initializer = parameter.getDefaultInitializer();
|
||||
if (initializer != null) {
|
||||
if (nonDefault > 0) {
|
||||
nonDefault--;
|
||||
}
|
||||
else {
|
||||
nameFilter.add(parameter.getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrExpression inferArg(GrClosureSignature signature,
|
||||
GrParameter[] parameters,
|
||||
GrParameter parameter,
|
||||
GrClosureSignatureUtil.ArgInfo<PsiElement> argInfo,
|
||||
Project project) {
|
||||
if (argInfo == null) return null;
|
||||
List<PsiElement> arguments = argInfo.args;
|
||||
|
||||
if (argInfo.isMultiArg) { //arguments for Map and varArg
|
||||
final PsiType type = parameter.getDeclaredType();
|
||||
return GroovyRefactoringUtil.generateArgFromMultiArg(signature.getSubstitutor(), arguments, type, project);
|
||||
}
|
||||
else { //arguments for simple parameters
|
||||
if (arguments.size() == 1) { //arg exists
|
||||
PsiElement arg = arguments.iterator().next();
|
||||
if (isVararg(parameter, parameters)) {
|
||||
if (arg instanceof GrSafeCastExpression) {
|
||||
PsiElement expr = ((GrSafeCastExpression)arg).getOperand();
|
||||
if (expr instanceof GrListOrMap && !((GrListOrMap)expr).isMap()) {
|
||||
return ((GrListOrMap)expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (GrExpression)arg;
|
||||
}
|
||||
else { //arg is skipped. Parameter is optional
|
||||
return parameter.getDefaultInitializer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultValuesToParameters(method, nameFilter, call);
|
||||
setValuesToParameters(method, call, exprs, nameFilter);
|
||||
private static boolean isVararg(GrParameter p, GrParameter[] parameters) {
|
||||
return parameters[parameters.length - 1] == p && p.getType() instanceof PsiArrayType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -515,32 +527,6 @@ public class GroovyInlineMethodUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace first m parameters by given values, where m is length of given values vector
|
||||
*
|
||||
* @param method
|
||||
* @param call
|
||||
* @param values values vector
|
||||
* @param nameFilter
|
||||
*/
|
||||
private static void setValuesToParameters(GrMethod method, GrCallExpression call, List<GrExpression> values, Set<String> nameFilter)
|
||||
throws IncorrectOperationException {
|
||||
GrParameter[] parameters = method.getParameters();
|
||||
if (parameters.length == 0) return;
|
||||
|
||||
if (nameFilter == null) nameFilter = new HashSet<String>();
|
||||
|
||||
int i = 0;
|
||||
for (GrExpression value : values) {
|
||||
while (i < parameters.length && nameFilter.contains(parameters[i].getName())) i++;
|
||||
if (i < parameters.length) {
|
||||
GrParameter parameter = parameters[i];
|
||||
replaceAllOccurrencesWithExpression(method, call, value, parameter);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceAllOccurrencesWithExpression(GrMethod method,
|
||||
GrCallExpression call,
|
||||
GrExpression oldExpression,
|
||||
|
||||
+2
@@ -103,6 +103,8 @@ public class InlineMethodTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testSideEffectInitializer() {doTest();}
|
||||
|
||||
public void testVarargs() {doTest();}
|
||||
|
||||
public void testInlineAll() throws Throwable {
|
||||
doTest(new GroovyInlineHandler() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
def foo(String s, int... var) {
|
||||
bar(var)
|
||||
}
|
||||
|
||||
<selection>foo</selection>('a')
|
||||
-----
|
||||
def foo(String s, int... var) {
|
||||
bar(var)
|
||||
}
|
||||
|
||||
bar([] as int[])
|
||||
Reference in New Issue
Block a user