From 1fa4233a0033a01d48a7da2509e7d4cd4395ae9a Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 23 Jun 2016 11:21:53 +0300 Subject: [PATCH] IDEA-157321 Debugger and Runtime Java Varargs inconsistent --- .../debugger/engine/DebugProcessImpl.java | 39 +++++++++++++------ .../expression/EvaluatorBuilderImpl.java | 30 -------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 0a46fc0d296f..27db49144b97 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1041,20 +1041,37 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb // See IDEA-63581 // if vararg parameter array is of interface type and Object[] is expected, JDI wrap it into another array, // in this case we have to unroll the array manually and pass its elements to the method instead of array object - int lastIndex = myArgs.size() - 1; - if (lastIndex >= 0) { - final Object lastArg = myArgs.get(lastIndex); - if (lastArg instanceof ArrayReference) { - final ArrayReference arrayRef = (ArrayReference)lastArg; - if (((ArrayType)arrayRef.referenceType()).componentType() instanceof InterfaceType) { - List argTypes = myMethod.argumentTypeNames(); - if (argTypes.size() > lastIndex && argTypes.get(lastIndex).startsWith(CommonClassNames.JAVA_LANG_OBJECT)) { - // unwrap array of interfaces for vararg param - myArgs.remove(lastIndex); - myArgs.addAll(arrayRef.getValues()); + int lastIndex = myMethod.argumentTypeNames().size() - 1; + if (lastIndex >= 0 && myArgs.size() > lastIndex) { // at least one varargs param + Object firstVararg = myArgs.get(lastIndex); + if (myArgs.size() == lastIndex + 1) { // only one vararg param + if (firstVararg instanceof ArrayReference) { + ArrayReference arrayRef = (ArrayReference)firstVararg; + if (((ArrayType)arrayRef.referenceType()).componentType() instanceof InterfaceType) { + List argTypes = myMethod.argumentTypeNames(); + if (argTypes.size() > lastIndex && argTypes.get(lastIndex).startsWith(CommonClassNames.JAVA_LANG_OBJECT)) { + // unwrap array of interfaces for vararg param + myArgs.remove(lastIndex); + myArgs.addAll(arrayRef.getValues()); + } } } } + else if (firstVararg == null) { // more than one vararg params and the first one is null + // this is a workaround for a bug in jdi, see IDEA-157321 + int argCount = myArgs.size(); + List paramTypes = myMethod.argumentTypes(); + int paramCount = paramTypes.size(); + ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1); + + int count = argCount - paramCount + 1; + ArrayReference argArray = lastParamType.newInstance(count); + argArray.setValues(0, myArgs, paramCount - 1, count); + myArgs.set(paramCount - 1, argArray); + for (int ii = paramCount; ii < argCount; ii++) { + myArgs.remove(paramCount); + } + } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 3f0cdea76c4a..ff8f550b6d71 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -1089,7 +1089,6 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { if (psiMethod != null) { processBoxingConversions(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators); - argumentEvaluators = wrapVarargs(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators); defaultInterfaceMethod = psiMethod.hasModifierProperty(PsiModifier.DEFAULT); mustBeVararg = psiMethod.isVarArgs(); } @@ -1319,7 +1318,6 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { if (constructor != null) { processBoxingConversions(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators); - argumentEvaluators = wrapVarargs(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators); } if (aClass != null && aClass.getContainingClass() != null && !aClass.hasModifierProperty(PsiModifier.STATIC)) { @@ -1410,34 +1408,6 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } } - private static Evaluator[] wrapVarargs(final PsiParameter[] declaredParams, - final PsiExpression[] actualArgumentExpressions, - final PsiSubstitutor methodResolveSubstitutor, - final Evaluator[] argumentEvaluators) { - int lastParam = declaredParams.length - 1; - if (lastParam >= 0 && declaredParams[lastParam].isVarArgs() && argumentEvaluators.length > lastParam) { - // only wrap if the first varargs parameter is null for now - if (!TypeConversionUtil.isNullType(actualArgumentExpressions[lastParam].getType())) { - return argumentEvaluators; - } - // do not wrap arrays twice - if (argumentEvaluators.length - lastParam == 1 && actualArgumentExpressions[lastParam].getType() instanceof PsiArrayType) { - return argumentEvaluators; - } - PsiEllipsisType declaredParamType = (PsiEllipsisType)methodResolveSubstitutor.substitute(declaredParams[lastParam].getType()); - ArrayInitializerEvaluator varargArrayEvaluator = - new ArrayInitializerEvaluator(Arrays.copyOfRange(argumentEvaluators, lastParam, argumentEvaluators.length)); - NewArrayInstanceEvaluator evaluator = - new NewArrayInstanceEvaluator(new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(declaredParamType.toArrayType())), null, - varargArrayEvaluator); - Evaluator[] res = new Evaluator[declaredParams.length]; - System.arraycopy(argumentEvaluators, 0, res, 0, lastParam); - res[lastParam] = new DisableGC(evaluator); - return res; - } - return argumentEvaluators; - } - private static void processBoxingConversions(final PsiParameter[] declaredParams, final PsiExpression[] actualArgumentExpressions, final PsiSubstitutor methodResolveSubstitutor,