mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
IDEA-171205 Create local variable from usage: honor most suitable overload by parameter count
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -67,6 +67,7 @@ import com.intellij.psi.util.proximity.PsiProximityComparator;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -388,71 +389,68 @@ public class CreateFromUsageUtils {
|
||||
final PsiElementFactory factory = facade.getElementFactory();
|
||||
|
||||
return ApplicationManager.getApplication().runWriteAction(
|
||||
new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
try {
|
||||
PsiClass targetClass;
|
||||
if (directory != null) {
|
||||
try {
|
||||
if (classKind == CreateClassKind.INTERFACE) {
|
||||
targetClass = JavaDirectoryService.getInstance().createInterface(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.CLASS) {
|
||||
targetClass = JavaDirectoryService.getInstance().createClass(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ENUM) {
|
||||
targetClass = JavaDirectoryService.getInstance().createEnum(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ANNOTATION) {
|
||||
targetClass = JavaDirectoryService.getInstance().createAnnotationType(directory, name);
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown kind of a class to create");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (final IncorrectOperationException e) {
|
||||
scheduleFileOrPackageCreationFailedMessageBox(e, name, directory, false);
|
||||
return null;
|
||||
}
|
||||
if (!facade.getResolveHelper().isAccessible(targetClass, contextElement, null)) {
|
||||
PsiUtil.setModifierProperty(targetClass, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
}
|
||||
else { //tests
|
||||
PsiClass aClass;
|
||||
(Computable<PsiClass>)() -> {
|
||||
try {
|
||||
PsiClass targetClass;
|
||||
if (directory != null) {
|
||||
try {
|
||||
if (classKind == CreateClassKind.INTERFACE) {
|
||||
aClass = factory.createInterface(name);
|
||||
targetClass = JavaDirectoryService.getInstance().createInterface(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.CLASS) {
|
||||
aClass = factory.createClass(name);
|
||||
targetClass = JavaDirectoryService.getInstance().createClass(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ENUM) {
|
||||
aClass = factory.createEnum(name);
|
||||
targetClass = JavaDirectoryService.getInstance().createEnum(directory, name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ANNOTATION) {
|
||||
aClass = factory.createAnnotationType(name);
|
||||
targetClass = JavaDirectoryService.getInstance().createAnnotationType(directory, name);
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown kind of a class to create");
|
||||
return null;
|
||||
}
|
||||
targetClass = (PsiClass) sourceFile.add(aClass);
|
||||
}
|
||||
catch (final IncorrectOperationException e) {
|
||||
scheduleFileOrPackageCreationFailedMessageBox(e, name, directory, false);
|
||||
return null;
|
||||
}
|
||||
if (!facade.getResolveHelper().isAccessible(targetClass, contextElement, null)) {
|
||||
PsiUtil.setModifierProperty(targetClass, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
}
|
||||
else { //tests
|
||||
PsiClass aClass;
|
||||
if (classKind == CreateClassKind.INTERFACE) {
|
||||
aClass = factory.createInterface(name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.CLASS) {
|
||||
aClass = factory.createClass(name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ENUM) {
|
||||
aClass = factory.createEnum(name);
|
||||
}
|
||||
else if (classKind == CreateClassKind.ANNOTATION) {
|
||||
aClass = factory.createAnnotationType(name);
|
||||
}
|
||||
else {
|
||||
LOG.error("Unknown kind of a class to create");
|
||||
return null;
|
||||
}
|
||||
targetClass = (PsiClass)sourceFile.add(aClass);
|
||||
}
|
||||
|
||||
if (superClassName != null && (classKind != CreateClassKind.ENUM || !superClassName.equals(CommonClassNames.JAVA_LANG_ENUM))) {
|
||||
setupSuperClassReference(targetClass, superClassName);
|
||||
}
|
||||
if (contextElement instanceof PsiJavaCodeReferenceElement) {
|
||||
CreateFromUsageBaseFix.setupGenericParameters(targetClass, (PsiJavaCodeReferenceElement)contextElement);
|
||||
}
|
||||
return targetClass;
|
||||
if (superClassName != null && (classKind != CreateClassKind.ENUM || !superClassName.equals(CommonClassNames.JAVA_LANG_ENUM))) {
|
||||
setupSuperClassReference(targetClass, superClassName);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
if (contextElement instanceof PsiJavaCodeReferenceElement) {
|
||||
CreateFromUsageBaseFix.setupGenericParameters(targetClass, (PsiJavaCodeReferenceElement)contextElement);
|
||||
}
|
||||
return targetClass;
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -571,16 +569,27 @@ public class CreateFromUsageUtils {
|
||||
List<ExpectedTypeInfo[]> types,
|
||||
List<String> expectedMethodNames,
|
||||
List<String> expectedFieldNames) {
|
||||
Comparator<ExpectedTypeInfo> expectedTypesComparator = (o1, o2) -> compareExpectedTypes(o1, o2, expression);
|
||||
for (PsiExpression expr : collectExpressions(expression, PsiMember.class, PsiFile.class)) {
|
||||
PsiElement parent = expr.getParent();
|
||||
|
||||
if (!(parent instanceof PsiReferenceExpression)) {
|
||||
boolean isAssignmentToFunctionalExpression = PsiUtil.isOnAssignmentLeftHand(expr) &&
|
||||
((PsiAssignmentExpression)PsiUtil.skipParenthesizedExprUp(parent)).getRExpression() instanceof PsiFunctionalExpression;
|
||||
boolean forCompletion = PsiUtil.skipParenthesizedExprUp(isAssignmentToFunctionalExpression ? parent.getParent() : parent) instanceof PsiExpressionList;
|
||||
PsiExpressionList expressionList = ObjectUtils
|
||||
.tryCast(PsiUtil.skipParenthesizedExprUp(isAssignmentToFunctionalExpression ? parent.getParent() : parent),
|
||||
PsiExpressionList.class);
|
||||
boolean forCompletion = expressionList != null;
|
||||
ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, forCompletion);
|
||||
if (someExpectedTypes.length > 0) {
|
||||
Arrays.sort(someExpectedTypes, (o1, o2) -> compareExpectedTypes(o1, o2, expression));
|
||||
Comparator<ExpectedTypeInfo> comparator = expectedTypesComparator;
|
||||
if (expressionList != null) {
|
||||
int argCount = expressionList.getExpressions().length;
|
||||
Comparator<ExpectedTypeInfo> mostSuitableMethodComparator = Comparator
|
||||
.comparingInt((ExpectedTypeInfo eti) -> eti.getCalledMethod().getParameterList().getParametersCount() == argCount ? 0 : 1);
|
||||
comparator = mostSuitableMethodComparator.thenComparing(comparator);
|
||||
}
|
||||
Arrays.sort(someExpectedTypes, comparator);
|
||||
types.add(someExpectedTypes);
|
||||
}
|
||||
continue;
|
||||
@@ -597,7 +606,7 @@ public class CreateFromUsageUtils {
|
||||
if (refName.equals("equals")) {
|
||||
ExpectedTypeInfo[] someExpectedTypes = equalsExpectedTypes((PsiMethodCallExpression)pparent);
|
||||
if (someExpectedTypes.length > 0) {
|
||||
Arrays.sort(someExpectedTypes, (o1, o2) -> compareExpectedTypes(o1, o2, expression));
|
||||
Arrays.sort(someExpectedTypes, expectedTypesComparator);
|
||||
types.add(someExpectedTypes);
|
||||
}
|
||||
}
|
||||
@@ -689,7 +698,7 @@ public class CreateFromUsageUtils {
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
static PsiType[] guessType(PsiExpression expression, final boolean allowVoidType) {
|
||||
final PsiManager manager = expression.getManager();
|
||||
final GlobalSearchScope resolveScope = expression.getResolveScope();
|
||||
@@ -876,12 +885,8 @@ public class CreateFromUsageUtils {
|
||||
final Module moduleForFile = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (moduleForFile == null) return;
|
||||
|
||||
final GlobalSearchScope searchScope = ApplicationManager.getApplication().runReadAction(new Computable<GlobalSearchScope>() {
|
||||
@Override
|
||||
public GlobalSearchScope compute() {
|
||||
return file.getResolveScope();
|
||||
}
|
||||
});
|
||||
final GlobalSearchScope searchScope =
|
||||
ApplicationManager.getApplication().runReadAction((Computable<GlobalSearchScope>)file::getResolveScope);
|
||||
GlobalSearchScope descendantsSearchScope = GlobalSearchScope.moduleWithDependenciesScope(moduleForFile);
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
|
||||
@@ -890,12 +895,10 @@ public class CreateFromUsageUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiMember[] members = ApplicationManager.getApplication().runReadAction(new Computable<PsiMember[]>() {
|
||||
@Override
|
||||
public PsiMember[] compute() {
|
||||
return method ? cache.getMethodsByName(memberName, searchScope) : cache.getFieldsByName(memberName, searchScope);
|
||||
}
|
||||
});
|
||||
final PsiMember[] members = ApplicationManager.getApplication().runReadAction(
|
||||
(Computable<PsiMember[]>)() -> method
|
||||
? cache.getMethodsByName(memberName, searchScope)
|
||||
: cache.getFieldsByName(memberName, searchScope));
|
||||
|
||||
for (int i = 0; i < members.length; ++i) {
|
||||
final PsiMember member = members[i];
|
||||
@@ -942,19 +945,10 @@ public class CreateFromUsageUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String[] strings = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
|
||||
@Override
|
||||
public String[] compute() {
|
||||
return cache.getAllClassNames();
|
||||
}
|
||||
});
|
||||
final String[] strings = ApplicationManager.getApplication().runReadAction((Computable<String[]>)cache::getAllClassNames);
|
||||
for (final String className : strings) {
|
||||
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
|
||||
@Override
|
||||
public PsiClass[] compute() {
|
||||
return cache.getClassesByName(className, searchScope);
|
||||
}
|
||||
});
|
||||
final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(
|
||||
(Computable<PsiClass[]>)() -> cache.getClassesByName(className, searchScope));
|
||||
for (final PsiClass aClass : classes) {
|
||||
final String qname = getQualifiedName(aClass);
|
||||
ContainerUtil.addIfNotNull(possibleClassNames, qname);
|
||||
@@ -967,13 +961,7 @@ public class CreateFromUsageUtils {
|
||||
|
||||
@Nullable
|
||||
private static String getQualifiedName(final PsiClass aClass) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String compute() {
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
});
|
||||
return ApplicationManager.getApplication().runReadAction((Computable<String>)aClass::getQualifiedName);
|
||||
}
|
||||
|
||||
private static boolean hasCorrectModifiers(@Nullable final PsiMember member, final boolean staticAccess) {
|
||||
@@ -981,12 +969,9 @@ public class CreateFromUsageUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return !member.hasModifierProperty(PsiModifier.PRIVATE) && member.hasModifierProperty(PsiModifier.STATIC) == staticAccess;
|
||||
}
|
||||
}).booleanValue();
|
||||
return ApplicationManager.getApplication().runReadAction(
|
||||
(Computable<Boolean>)() -> !member.hasModifierProperty(PsiModifier.PRIVATE) &&
|
||||
member.hasModifierProperty(PsiModifier.STATIC) == staticAccess).booleanValue();
|
||||
}
|
||||
|
||||
private static class ParameterNameExpression extends Expression {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create local variable 'xyz'" "true"
|
||||
interface Other<T> {
|
||||
void add(int x, T y);
|
||||
void add(T y);
|
||||
}
|
||||
class A {
|
||||
public void foo(Other<String> other) {
|
||||
String xyz;
|
||||
other.add(xyz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Create local variable 'xyz'" "true"
|
||||
interface Other<T> {
|
||||
void add(int x, T y);
|
||||
void add(T y);
|
||||
}
|
||||
class A {
|
||||
public void foo(Other<String> other) {
|
||||
other.add(x<caret>yz);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user