mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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&odule's classpath:" noi18n="true"/>
|
||||
<visible value="true"/>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user