Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2017-06-14 16:51:50 +03:00
14 changed files with 218 additions and 220 deletions

View File

@@ -160,7 +160,7 @@
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="com.intellij.application.options.ModulesComboBox"/>
<componentClass value="com.intellij.application.options.ModuleDescriptionsComboBox"/>
<labelLocation value="West"/>
<text value="Search sources using m&amp;odule's classpath:" noi18n="true"/>
<visible value="true"/>

View File

@@ -20,7 +20,7 @@
*/
package com.intellij.execution.remote;
import com.intellij.application.options.ModulesComboBox;
import com.intellij.application.options.ModuleDescriptionsComboBox;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.ui.ConfigurationArgumentsHelpArea;
@@ -53,7 +53,7 @@ public class RemoteConfigurable extends SettingsEditor<RemoteConfiguration> {
private ConfigurationArgumentsHelpArea myHelpArea;
@NonNls private ConfigurationArgumentsHelpArea myJDK13HelpArea;
private ConfigurationArgumentsHelpArea myJDK14HelpArea;
private LabeledComponent<ModulesComboBox> myModule;
private LabeledComponent<ModuleDescriptionsComboBox> myModule;
private String myHostName = "";
@NonNls
protected static final String LOCALHOST = "localhost";
@@ -128,8 +128,9 @@ public class RemoteConfigurable extends SettingsEditor<RemoteConfiguration> {
};
myAddressField.addFocusListener(fieldFocusListener);
myPortField.addFocusListener(fieldFocusListener);
myModuleSelector = new ConfigurationModuleSelector(project, myModule.getComponent(), "<whole project>");
myModule.getComponent().allowEmptySelection("<whole project>");
myModuleSelector = new ConfigurationModuleSelector(project, myModule.getComponent());
}
public void applyEditorTo(@NotNull final RemoteConfiguration configuration) throws ConfigurationException {

View File

@@ -37,6 +37,7 @@ import java.util.Collection;
import java.util.List;
public class ConfigurationModuleSelector {
public static final String NO_MODULE_TEXT = "<no module>";
private final Project myProject;
/** this field is {@code null} if and only if {@link #myModulesList} is not null */
private final ModuleDescriptionsComboBox myModulesDescriptionsComboBox;
@@ -47,17 +48,22 @@ public class ConfigurationModuleSelector {
* @deprecated use {@link #ConfigurationModuleSelector(Project, ModulesComboBox)} instead
*/
public ConfigurationModuleSelector(final Project project, final JComboBox<Module> modulesList) {
this(project, modulesList, "<no module>");
this(project, modulesList, NO_MODULE_TEXT);
}
public ConfigurationModuleSelector(Project project, ModulesComboBox modulesComboBox) {
this(project, modulesComboBox, "<no module>");
this(project, modulesComboBox, NO_MODULE_TEXT);
}
public ConfigurationModuleSelector(Project project, ModuleDescriptionsComboBox modulesDescriptionsComboBox) {
this(project, modulesDescriptionsComboBox, NO_MODULE_TEXT);
}
public ConfigurationModuleSelector(Project project, ModuleDescriptionsComboBox modulesDescriptionsComboBox, String emptySelectionText) {
myProject = project;
myModulesDescriptionsComboBox = modulesDescriptionsComboBox;
myModulesList = null;
modulesDescriptionsComboBox.allowEmptySelection(emptySelectionText);
}
public ConfigurationModuleSelector(Project project, ModulesComboBox modulesComboBox, String noModule) {

View File

@@ -46,6 +46,10 @@ abstract class DefaultJreSelector {
fun fromModuleDependencies(moduleComboBox: ModulesComboBox, productionOnly: Boolean): DefaultJreSelector
= SdkFromModuleDependencies(moduleComboBox, ModulesComboBox::getSelectedModule, {productionOnly})
@JvmStatic
fun fromModuleDependencies(moduleComboBox: ModuleDescriptionsComboBox, productionOnly: Boolean): DefaultJreSelector
= SdkFromModuleDependencies(moduleComboBox, ModuleDescriptionsComboBox::getSelectedModule, {productionOnly})
@JvmStatic
fun fromSourceRootsDependencies(moduleComboBox: ModulesComboBox, classSelector: EditorTextFieldWithBrowseButton): DefaultJreSelector
= SdkFromSourceRootDependencies(moduleComboBox, ModulesComboBox::getSelectedModule, classSelector)

View File

@@ -23,7 +23,6 @@ import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -35,7 +34,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.intellij.codeInspection.reflectiveAccess.JavaLangReflectVarHandleInvocationChecker.ARRAY_ELEMENT_VAR_HANDLE;
@@ -304,86 +302,6 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
.anyMatch(expectedMethodSignature::equals);
}
/**
* Take method's return type and parameter types
* from arguments of MethodType.methodType(Class...) and MethodType.genericMethodType(int, boolean?)
*/
@Nullable
public static ReflectiveSignature composeMethodSignature(@Nullable PsiExpression methodTypeExpression) {
final PsiExpression typeDefinition = findDefinition(methodTypeExpression);
if (typeDefinition instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)typeDefinition;
final String referenceName = methodCallExpression.getMethodExpression().getReferenceName();
Function<PsiExpression[], ReflectiveSignature> composer = null;
if (METHOD_TYPE.equals(referenceName)) {
composer = JavaLangInvokeHandleSignatureInspection::composeMethodSignatureFromTypes;
}
else if (GENERIC_METHOD_TYPE.equals(referenceName)) {
composer = JavaLangInvokeHandleSignatureInspection::composeGenericMethodSignature;
}
if (composer != null) {
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null) {
final PsiClass psiClass = method.getContainingClass();
if (psiClass != null && JAVA_LANG_INVOKE_METHOD_TYPE.equals(psiClass.getQualifiedName())) {
final PsiExpression[] arguments = methodCallExpression.getArgumentList().getExpressions();
return composer.apply(arguments);
}
}
}
}
return null;
}
@Nullable
private static ReflectiveSignature composeMethodSignatureFromTypes(@NotNull PsiExpression[] returnAndParameterTypes) {
final List<String> typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText);
return ReflectiveSignature.create(typeTexts);
}
@Nullable
static Pair.NonNull<Integer, Boolean> getGenericSignature(@NotNull PsiExpression[] genericSignatureShape) {
if (genericSignatureShape.length == 0 || genericSignatureShape.length > 2) {
return null;
}
final Integer objectArgCount = computeConstantExpression(genericSignatureShape[0], Integer.class);
final Boolean finalArray = // there's an additional parameter which is an ellipsis or an array
genericSignatureShape.length > 1 ? computeConstantExpression(genericSignatureShape[1], Boolean.class) : false;
if (objectArgCount == null || objectArgCount < 0 || objectArgCount > 255) {
return null;
}
if (finalArray == null || finalArray && objectArgCount > 254) {
return null;
}
return Pair.createNonNull(objectArgCount, finalArray);
}
/**
* All the types in the method signature are either unbounded type parameters or java.lang.Object (with possible vararg)
*/
@Nullable
private static ReflectiveSignature composeGenericMethodSignature(@NotNull PsiExpression[] genericSignatureShape) {
final Pair.NonNull<Integer, Boolean> signature = getGenericSignature(genericSignatureShape);
if (signature == null) return null;
final int objectArgCount = signature.getFirst();
final boolean finalArray = signature.getSecond();
final List<String> typeNames = new ArrayList<>();
typeNames.add(JAVA_LANG_OBJECT); // return type
for (int i = 0; i < objectArgCount; i++) {
typeNames.add(JAVA_LANG_OBJECT);
}
if (finalArray) {
typeNames.add(JAVA_LANG_OBJECT + "[]");
}
return ReflectiveSignature.create(typeNames);
}
private static class FieldTypeQuickFix implements LocalQuickFix {
private final String myFieldTypeText;

View File

@@ -271,27 +271,25 @@ class JavaLangReflectHandleInvocationChecker {
}
else if (isCallToMethod(typeDefinitionCall, JAVA_LANG_INVOKE_METHOD_TYPE, GENERIC_METHOD_TYPE)) {
final PsiExpression[] arguments = typeDefinitionCall.getArgumentList().getExpressions();
final Pair.NonNull<Integer, Boolean> signature = JavaLangInvokeHandleSignatureInspection.getGenericSignature(arguments);
final Pair.NonNull<Integer, Boolean> signature = getGenericSignature(arguments);
if (signature != null) {
final int objectArgCount = signature.getFirst();
final boolean finalArray = signature.getSecond();
if (objectArgCount == 0 && !finalArray) {
return Collections.emptyList();
}
final JavaPsiFacade facade = JavaPsiFacade.getInstance(methodTypeExpression.getProject());
final PsiClass objectClass = facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, methodTypeExpression.getResolveScope());
if (objectClass != null) {
final List<ReflectiveType> argumentTypes = new ArrayList<>();
final ReflectiveType objectType = ReflectiveType.create(objectClass);
argumentTypes.add(objectType); // return type
for (int i = 0; i < objectArgCount; i++) {
argumentTypes.add(objectType);
}
if (finalArray) {
argumentTypes.add(ReflectiveType.arrayOf(objectType));
}
return ContainerUtil.map(argumentTypes, type -> (() -> type));
final PsiClassType javaLangObject =
PsiType.getJavaLangObject(methodTypeExpression.getManager(), methodTypeExpression.getResolveScope());
final ReflectiveType objectType = ReflectiveType.create(javaLangObject);
final List<ReflectiveType> argumentTypes = new ArrayList<>();
argumentTypes.add(objectType); // return type
for (int i = 0; i < objectArgCount; i++) {
argumentTypes.add(objectType);
}
if (finalArray) {
argumentTypes.add(ReflectiveType.arrayOf(objectType));
}
return ContainerUtil.map(argumentTypes, type -> (() -> type));
}
}
}
@@ -364,7 +362,7 @@ class JavaLangReflectHandleInvocationChecker {
if (INVOKE_WITH_ARGUMENTS.equals(invokeCall.getMethodExpression().getReferenceName())) {
final PsiExpression[] arguments = invokeCall.getArgumentList().getExpressions();
if (arguments.length == 1) {
return JavaReflectionInvocationInspection.isVarargAsArray(arguments[0]) ||
return isVarargAsArray(arguments[0]) ||
InheritanceUtil.isInheritor(arguments[0].getType(), JAVA_UTIL_LIST);
}
}

View File

@@ -19,10 +19,9 @@ import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -132,34 +131,12 @@ public class JavaReflectionInvocationInspection extends BaseJavaBatchLocalInspec
if (definition instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression definitionCall = (PsiMethodCallExpression)definition;
if (methodPredicate.test(definitionCall)) {
return getRequiredMethodArguments(definitionCall, argumentOffset);
return JavaLangClassMemberReference.getReflectionMethodArguments(definitionCall, argumentOffset);
}
}
return null;
}
private static List<PsiExpression> getRequiredMethodArguments(@NotNull PsiMethodCallExpression definitionCall, int argumentOffset) {
final PsiExpression[] arguments = definitionCall.getArgumentList().getExpressions();
if (arguments.length == argumentOffset + 1) {
final PsiExpression[] arrayElements = getVarargAsArray(arguments[argumentOffset]);
if (arrayElements != null) {
return Arrays.asList(arrayElements);
}
}
if (arguments.length >= argumentOffset) {
return Arrays.asList(arguments).subList(argumentOffset, arguments.length);
}
return null;
}
@Nullable
public static List<ReflectiveType> getReflectionMethodParameterTypes(@NotNull PsiMethodCallExpression definitionCall,
int argumentOffset) {
List<PsiExpression> arguments = getRequiredMethodArguments(definitionCall, argumentOffset);
return arguments != null ? ContainerUtil.map(arguments, type -> getReflectiveType(type)) : null;
}
@Nullable
static Arguments getActualMethodArguments(PsiExpression[] arguments, int argumentOffset, boolean allowVarargAsArray) {
if (allowVarargAsArray && arguments.length == argumentOffset + 1) {
@@ -181,38 +158,6 @@ public class JavaReflectionInvocationInspection extends BaseJavaBatchLocalInspec
return null;
}
@Nullable
private static PsiExpression[] getVarargAsArray(@Nullable PsiExpression maybeArray) {
if (isVarargAsArray(maybeArray)) {
final PsiExpression argumentsDefinition = findDefinition(maybeArray);
if (argumentsDefinition instanceof PsiArrayInitializerExpression) {
return ((PsiArrayInitializerExpression)argumentsDefinition).getInitializers();
}
if (argumentsDefinition instanceof PsiNewExpression) {
final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer();
if (arrayInitializer != null) {
return arrayInitializer.getInitializers();
}
final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions();
if (dimensions.length == 1) { // special case: new Object[0]
final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class);
if (itemCount != null && itemCount == 0) {
return PsiExpression.EMPTY_ARRAY;
}
}
}
}
return null;
}
@Contract("null -> false")
static boolean isVarargAsArray(@Nullable PsiExpression maybeArray) {
final PsiType type = maybeArray != null ? maybeArray.getType() : null;
return type instanceof PsiArrayType &&
type.getArrayDimensions() == 1 &&
type.getDeepComponentType() instanceof PsiClassType;
}
@Nullable
private static PsiExpression unwrapDisambiguatingCastToObject(@Nullable PsiExpression expression) {
if (expression instanceof PsiTypeCastExpression) {

View File

@@ -23,6 +23,7 @@ import com.intellij.codeInspection.ui.ListWrappingTableModel;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference;
import com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.CheckBox;
@@ -279,45 +280,6 @@ public class JavaReflectionMemberAccessInspection extends BaseJavaBatchLocalInsp
final List<ReflectiveType> argumentTypes =
ContainerUtil.map(methodArguments.expressions, JavaReflectionReferenceUtil::getReflectiveType);
return matchMethod(methods, argumentTypes);
}
@Nullable
public static PsiMethod matchMethod(@NotNull PsiMethod[] methods, @NotNull List<ReflectiveType> argumentTypes) {
int mismatchCount = Integer.MAX_VALUE;
PsiMethod bestGuess = null;
for (PsiMethod method : methods) {
final int match = matchMethodArguments(method, argumentTypes);
if (match == 0) {
return method;
}
if (match < 0) {
continue;
}
if (mismatchCount > match) {
mismatchCount = match;
bestGuess = method;
}
}
return bestGuess;
}
private static int matchMethodArguments(PsiMethod method, List<ReflectiveType> argumentTypes) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != argumentTypes.size()) {
return -1;
}
int mismatchCount = 0;
for (int i = 0; i < parameters.length; i++) {
final ReflectiveType argumentType = argumentTypes.get(i);
if (argumentType == null) {
mismatchCount++;
continue;
}
if (!argumentType.isEqualTo(parameters[i].getType())) {
return -1;
}
}
return mismatchCount;
return JavaLangClassMemberReference.matchMethod(methods, argumentTypes);
}
}

View File

@@ -18,8 +18,6 @@ package com.intellij.psi.impl.source.resolve.reference.impl;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInspection.reflectiveAccess.JavaReflectionInvocationInspection;
import com.intellij.codeInspection.reflectiveAccess.JavaReflectionMemberAccessInspection;
import com.intellij.psi.*;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
@@ -170,9 +168,10 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
private PsiElement findOverloadedMethod(PsiMethod[] methods) {
final PsiMethodCallExpression definitionCall = PsiTreeUtil.getParentOfType(myElement, PsiMethodCallExpression.class);
if (definitionCall != null) {
final List<ReflectiveType> parameterTypes = JavaReflectionInvocationInspection.getReflectionMethodParameterTypes(definitionCall, 1);
if (parameterTypes != null) {
return JavaReflectionMemberAccessInspection.matchMethod(methods, parameterTypes);
final List<PsiExpression> arguments = getReflectionMethodArguments(definitionCall, 1);
if (arguments != null) {
final List<ReflectiveType> parameterTypes = ContainerUtil.map(arguments, type -> getReflectiveType(type));
return matchMethod(methods, parameterTypes);
}
}
return null;
@@ -187,4 +186,60 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
replaceText(context, text.isEmpty() ? "" : ", " + text);
}
}
@Nullable
public static PsiMethod matchMethod(@NotNull PsiMethod[] methods, @NotNull List<ReflectiveType> argumentTypes) {
int mismatchCount = Integer.MAX_VALUE;
PsiMethod bestGuess = null;
for (PsiMethod method : methods) {
final int match = matchMethodArguments(method, argumentTypes);
if (match == 0) {
return method;
}
if (match < 0) {
continue;
}
if (mismatchCount > match) {
mismatchCount = match;
bestGuess = method;
}
}
return bestGuess;
}
private static int matchMethodArguments(PsiMethod method, List<ReflectiveType> argumentTypes) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != argumentTypes.size()) {
return -1;
}
int mismatchCount = 0;
for (int i = 0; i < parameters.length; i++) {
final ReflectiveType argumentType = argumentTypes.get(i);
if (argumentType == null) {
mismatchCount++;
continue;
}
if (!argumentType.isEqualTo(parameters[i].getType())) {
return -1;
}
}
return mismatchCount;
}
@Nullable
public static List<PsiExpression> getReflectionMethodArguments(@NotNull PsiMethodCallExpression definitionCall, int argumentOffset) {
final PsiExpression[] arguments = definitionCall.getArgumentList().getExpressions();
if (arguments.length == argumentOffset + 1) {
final PsiExpression[] arrayElements = getVarargAsArray(arguments[argumentOffset]);
if (arrayElements != null) {
return Arrays.asList(arrayElements);
}
}
if (arguments.length >= argumentOffset) {
return Arrays.asList(arguments).subList(argumentOffset, arguments.length);
}
return null;
}
}

View File

@@ -19,7 +19,6 @@ import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
@@ -33,10 +32,7 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil.*;
@@ -110,7 +106,7 @@ public class JavaLangInvokeHandleReference extends PsiReferenceBase<PsiLiteralEx
final PsiExpression[] arguments = definitionCall.getArgumentList().getExpressions();
if (arguments.length > 2) {
final PsiExpression typeExpression = ParenthesesUtils.stripParentheses(arguments[2]);
final ReflectiveSignature expectedSignature = JavaLangInvokeHandleSignatureInspection.composeMethodSignature(typeExpression);
final ReflectiveSignature expectedSignature = composeMethodSignature(typeExpression);
if (expectedSignature != null) {
return ContainerUtil.find(methods, method -> expectedSignature.equals(getMethodSignature(method)));
}

View File

@@ -23,6 +23,7 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
@@ -441,6 +442,118 @@ public class JavaReflectionReferenceUtil {
return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName, (PsiType[])null);
}
@Nullable
public static PsiExpression[] getVarargAsArray(@Nullable PsiExpression maybeArray) {
if (isVarargAsArray(maybeArray)) {
final PsiExpression argumentsDefinition = findDefinition(maybeArray);
if (argumentsDefinition instanceof PsiArrayInitializerExpression) {
return ((PsiArrayInitializerExpression)argumentsDefinition).getInitializers();
}
if (argumentsDefinition instanceof PsiNewExpression) {
final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer();
if (arrayInitializer != null) {
return arrayInitializer.getInitializers();
}
final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions();
if (dimensions.length == 1) { // special case: new Object[0]
final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class);
if (itemCount != null && itemCount == 0) {
return PsiExpression.EMPTY_ARRAY;
}
}
}
}
return null;
}
@Contract("null -> false")
public static boolean isVarargAsArray(@Nullable PsiExpression maybeArray) {
final PsiType type = maybeArray != null ? maybeArray.getType() : null;
return type instanceof PsiArrayType &&
type.getArrayDimensions() == 1 &&
type.getDeepComponentType() instanceof PsiClassType;
}
/**
* Take method's return type and parameter types
* from arguments of MethodType.methodType(Class...) and MethodType.genericMethodType(int, boolean?)
*/
@Nullable
public static ReflectiveSignature composeMethodSignature(@Nullable PsiExpression methodTypeExpression) {
final PsiExpression typeDefinition = findDefinition(methodTypeExpression);
if (typeDefinition instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)typeDefinition;
final String referenceName = methodCallExpression.getMethodExpression().getReferenceName();
Function<PsiExpression[], ReflectiveSignature> composer = null;
if (METHOD_TYPE.equals(referenceName)) {
composer = JavaReflectionReferenceUtil::composeMethodSignatureFromTypes;
}
else if (GENERIC_METHOD_TYPE.equals(referenceName)) {
composer = JavaReflectionReferenceUtil::composeGenericMethodSignature;
}
if (composer != null) {
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null) {
final PsiClass psiClass = method.getContainingClass();
if (psiClass != null && JAVA_LANG_INVOKE_METHOD_TYPE.equals(psiClass.getQualifiedName())) {
final PsiExpression[] arguments = methodCallExpression.getArgumentList().getExpressions();
return composer.apply(arguments);
}
}
}
}
return null;
}
@Nullable
private static ReflectiveSignature composeMethodSignatureFromTypes(@NotNull PsiExpression[] returnAndParameterTypes) {
final List<String> typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText);
return ReflectiveSignature.create(typeTexts);
}
@Nullable
public static Pair.NonNull<Integer, Boolean> getGenericSignature(@NotNull PsiExpression[] genericSignatureShape) {
if (genericSignatureShape.length == 0 || genericSignatureShape.length > 2) {
return null;
}
final Integer objectArgCount = computeConstantExpression(genericSignatureShape[0], Integer.class);
final Boolean finalArray = // there's an additional parameter which is an ellipsis or an array
genericSignatureShape.length > 1 ? computeConstantExpression(genericSignatureShape[1], Boolean.class) : false;
if (objectArgCount == null || objectArgCount < 0 || objectArgCount > 255) {
return null;
}
if (finalArray == null || finalArray && objectArgCount > 254) {
return null;
}
return Pair.createNonNull(objectArgCount, finalArray);
}
/**
* All the types in the method signature are either unbounded type parameters or java.lang.Object (with possible vararg)
*/
@Nullable
private static ReflectiveSignature composeGenericMethodSignature(@NotNull PsiExpression[] genericSignatureShape) {
final Pair.NonNull<Integer, Boolean> signature = getGenericSignature(genericSignatureShape);
if (signature == null) return null;
final int objectArgCount = signature.getFirst();
final boolean finalArray = signature.getSecond();
final List<String> typeNames = new ArrayList<>();
typeNames.add(CommonClassNames.JAVA_LANG_OBJECT); // return type
for (int i = 0; i < objectArgCount; i++) {
typeNames.add(CommonClassNames.JAVA_LANG_OBJECT);
}
if (finalArray) {
typeNames.add(CommonClassNames.JAVA_LANG_OBJECT + "[]");
}
return ReflectiveSignature.create(typeNames);
}
public static class ReflectiveType {
final PsiType myType;

View File

@@ -15,6 +15,7 @@
*/
package com.intellij.java.execution;
import com.intellij.application.options.ModuleDescriptionsComboBox;
import com.intellij.execution.CantRunException;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunConfigurationConfigurableAdapter;
@@ -62,7 +63,6 @@ import com.intellij.util.containers.ContainerUtilRt;
import junit.framework.TestCase;
import org.jdom.Element;
import javax.swing.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
@@ -127,12 +127,12 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
JUnitConfiguration configuration = createConfiguration(findTestA(module2));
editor.getComponent(); // To get all the watchers installed.
Configurable configurable = new RunConfigurationConfigurableAdapter(editor, configuration);
JComboBox comboBox = editor.getModulesComponent();
ModuleDescriptionsComboBox comboBox = editor.getModulesComponent();
configurable.reset();
assertFalse(configurable.isModified());
assertEquals(module2.getName(), ((Module)comboBox.getSelectedItem()).getName());
assertEquals(module2.getName(), comboBox.getSelectedModuleName());
assertEquals(ModuleManager.getInstance(myProject).getModules().length + 1, comboBox.getModel().getSize()); //no module
comboBox.setSelectedItem(module1);
comboBox.setSelectedModule(module1);
assertTrue(configurable.isModified());
configurable.apply();
assertFalse(configurable.isModified());

View File

@@ -62,7 +62,7 @@
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="com.intellij.application.options.ModulesComboBox"/>
<componentClass value="com.intellij.application.options.ModuleDescriptionsComboBox"/>
<enabled value="true"/>
<labelLocation value="West"/>
<text resource-bundle="messages/ExecutionBundle" key="application.configuration.use.classpath.and.jdk.of.module.label"/>

View File

@@ -16,7 +16,7 @@
package com.intellij.execution.junit2.configuration;
import com.intellij.application.options.ModulesComboBox;
import com.intellij.application.options.ModuleDescriptionsComboBox;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.MethodBrowser;
import com.intellij.execution.configuration.BrowseModuleValueActionListener;
@@ -94,7 +94,7 @@ public class JUnitConfigurable<T extends JUnitConfiguration> extends SettingsEdi
private LabeledComponent<EditorTextFieldWithBrowseButton> myCategory;
// Fields
private JPanel myWholePanel;
private LabeledComponent<ModulesComboBox> myModule;
private LabeledComponent<ModuleDescriptionsComboBox> myModule;
private CommonJavaParametersPanel myCommonJavaParameters;
private JRadioButton myWholeProjectScope;
private JRadioButton mySingleModuleScope;
@@ -445,7 +445,7 @@ public class JUnitConfigurable<T extends JUnitConfiguration> extends SettingsEdi
return new DefaultComboBoxModel(RepeatCount.ONCE.equals(myRepeatCb.getSelectedItem()) ? FORK_MODE : FORK_MODE_ALL);
}
public ModulesComboBox getModulesComponent() {
public ModuleDescriptionsComboBox getModulesComponent() {
return myModule.getComponent();
}