mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
method chain completion: remove sub lookup element (automatic argument insertion)
This commit is contained in:
+19
-21
@@ -18,14 +18,13 @@ package com.intellij.compiler.chainsSearch;
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.JavaMethodCallElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.ChainCompletionNewVariableLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.sub.GetterLookupSubLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.sub.VariableSubLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.psi.*;
|
||||
@@ -33,14 +32,12 @@ import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.intellij.compiler.chainsSearch.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
|
||||
public class MethodsChainLookupRangingHelper {
|
||||
@@ -152,25 +149,19 @@ public class MethodsChainLookupRangingHelper {
|
||||
boolean hasCallingVariableInContext = false;
|
||||
boolean introduceNewVariable = false;
|
||||
PsiParameterList parameterList = method.getParameterList();
|
||||
TIntObjectHashMap<SubLookupElement> parametersMap = new TIntObjectHashMap<>(parameterList.getParametersCount());
|
||||
PsiParameter[] parameters = parameterList.getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
for (PsiParameter parameter : parameters) {
|
||||
PsiType type = parameter.getType();
|
||||
if (type.equalsToText(JAVA_LANG_STRING)) {
|
||||
PsiElement relevantStringElement = context.findRelevantStringInContext(parameter.getName());
|
||||
if (relevantStringElement == null) {
|
||||
notMatchedStringVars++;
|
||||
}
|
||||
else {
|
||||
parametersMap.put(i, createSubLookup(relevantStringElement));
|
||||
}
|
||||
}
|
||||
else if (!ChainCompletionContext.isWidelyUsed(type)) {
|
||||
Collection<PsiElement> contextVariables = context.getQualifiers(type).collect(Collectors.toList());
|
||||
PsiElement contextVariable = ContainerUtil.getFirstItem(contextVariables, null);
|
||||
if (contextVariable != null) {
|
||||
if (contextVariables.size() == 1) parametersMap.put(i, createSubLookup(contextVariable));
|
||||
matchedParametersInContext++;
|
||||
continue;
|
||||
}
|
||||
@@ -183,7 +174,7 @@ public class MethodsChainLookupRangingHelper {
|
||||
if (isHeadMethod) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
hasCallingVariableInContext = true;
|
||||
lookupElement = createLookupElement(method, parametersMap);
|
||||
lookupElement = createMethodLookupElement(method);
|
||||
}
|
||||
else if (method.isConstructor()) {
|
||||
return null;
|
||||
@@ -196,7 +187,7 @@ public class MethodsChainLookupRangingHelper {
|
||||
firstChainElement = new VariableLookupItem((PsiVariable)e);
|
||||
}
|
||||
else if (e instanceof PsiMethod) {
|
||||
firstChainElement = createLookupElement((PsiMethod)e, null);
|
||||
firstChainElement = createMethodLookupElement((PsiMethod)e);
|
||||
}
|
||||
else if (e instanceof LookupElement) {
|
||||
firstChainElement = (LookupElement)e;
|
||||
@@ -205,10 +196,10 @@ public class MethodsChainLookupRangingHelper {
|
||||
throw new AssertionError();
|
||||
}
|
||||
hasCallingVariableInContext = true;
|
||||
lookupElement = new JavaChainLookupElement(firstChainElement, createLookupElement(method, parametersMap));
|
||||
lookupElement = new JavaChainLookupElement(firstChainElement, createMethodLookupElement(method));
|
||||
}
|
||||
else {
|
||||
lookupElement = createLookupElement(method, parametersMap);
|
||||
lookupElement = createMethodLookupElement(method);
|
||||
if (!context.hasQualifier(qualifierClass)) {
|
||||
introduceNewVariable = true;
|
||||
}
|
||||
@@ -216,7 +207,7 @@ public class MethodsChainLookupRangingHelper {
|
||||
}
|
||||
}
|
||||
else {
|
||||
lookupElement = createLookupElement(method, parametersMap);
|
||||
lookupElement = createMethodLookupElement(method);
|
||||
}
|
||||
return new MethodProcResult(lookupElement,
|
||||
unreachableParametersCount,
|
||||
@@ -227,10 +218,17 @@ public class MethodsChainLookupRangingHelper {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static SubLookupElement createSubLookup(PsiElement relevantStringElement) {
|
||||
return relevantStringElement instanceof PsiMethod
|
||||
? new GetterLookupSubLookupElement((PsiMethod)relevantStringElement)
|
||||
: new VariableSubLookupElement((PsiVariable)relevantStringElement);
|
||||
private static LookupElement createMethodLookupElement(@NotNull PsiMethod method) {
|
||||
LookupElement result;
|
||||
if (method.isConstructor()) {
|
||||
//noinspection ConstantConditions
|
||||
result = LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
|
||||
} else if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
result = new JavaMethodCallElement(method, false, true);
|
||||
} else {
|
||||
result = new JavaMethodCallElement(method);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class MethodProcResult {
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.psi.PsiKeyword;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class ChainCompletionLookupElementUtil {
|
||||
private ChainCompletionLookupElementUtil() {
|
||||
}
|
||||
|
||||
public static LookupElement createLookupElement(final PsiMethod method,
|
||||
final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
|
||||
if (method.isConstructor()) {
|
||||
//noinspection ConstantConditions
|
||||
return LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
|
||||
} else if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return new ChainCompletionMethodCallLookupElement(method, replaceElements, false, true);
|
||||
} else {
|
||||
return new ChainCompletionMethodCallLookupElement(method, replaceElements);
|
||||
}
|
||||
}
|
||||
|
||||
public static String fillMethodParameters(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
|
||||
final TIntObjectHashMap<SubLookupElement> notNullReplaceElements = replaceElements == null ?
|
||||
new TIntObjectHashMap<>(0) :
|
||||
replaceElements;
|
||||
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
final PsiParameter parameter = parameters[i];
|
||||
final SubLookupElement replaceElement = notNullReplaceElements.get(i);
|
||||
if (replaceElement != null) {
|
||||
sb.append(replaceElement.getInsertString());
|
||||
} else {
|
||||
sb.append(parameter.getName());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaMethodCallElement;
|
||||
import com.intellij.codeInsight.completion.StaticallyImportable;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ChainCompletionMethodCallLookupElement extends JavaMethodCallElement implements StaticallyImportable {
|
||||
public static final String PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION = "methods.chain.completion.autoCompletion";
|
||||
|
||||
private final PsiMethod myMethod;
|
||||
@Nullable
|
||||
private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
|
||||
private final boolean myMergedOverloads;
|
||||
|
||||
public ChainCompletionMethodCallLookupElement(final PsiMethod method,
|
||||
final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements,
|
||||
final boolean shouldImportStatic,
|
||||
final boolean mergedOverloads) {
|
||||
super(method, shouldImportStatic, mergedOverloads);
|
||||
myMethod = method;
|
||||
myReplaceElements = replaceElements;
|
||||
myMergedOverloads = mergedOverloads;
|
||||
configureAutoCompletionPolicy();
|
||||
}
|
||||
|
||||
public ChainCompletionMethodCallLookupElement(final PsiMethod method,
|
||||
final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
|
||||
super(method);
|
||||
myMethod = method;
|
||||
myReplaceElements = replaceElements;
|
||||
myMergedOverloads = true;
|
||||
configureAutoCompletionPolicy();
|
||||
}
|
||||
|
||||
private void configureAutoCompletionPolicy() {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (PropertiesComponent.getInstance(myMethod.getProject()).getBoolean(PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION)) {
|
||||
setAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInsert(final InsertionContext context) {
|
||||
super.handleInsert(context);
|
||||
if (!myMergedOverloads || isUniqueMethod(myMethod)) {
|
||||
context.commitDocument();
|
||||
context.getDocument()
|
||||
.insertString(context.getTailOffset() - 1, ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
|
||||
final PsiFile file = context.getFile();
|
||||
assert file instanceof PsiJavaFile;
|
||||
final PsiJavaFile javaFile = (PsiJavaFile)file;
|
||||
if (myReplaceElements != null) {
|
||||
myReplaceElements.forEachValue(subLookupElement -> {
|
||||
subLookupElement.doImport(javaFile);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
context.commitDocument();
|
||||
context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
|
||||
context.commitDocument();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean isUniqueMethod(@NotNull final PsiMethod method) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
return containingClass == null || containingClass.findMethodsByName(method.getName(), true).length == 1;
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class GetterLookupSubLookupElement implements SubLookupElement {
|
||||
private final String myVariableName;
|
||||
private final String myMethodName;
|
||||
|
||||
public GetterLookupSubLookupElement(final PsiMethod method) {
|
||||
this(null, method.getName());
|
||||
}
|
||||
|
||||
public GetterLookupSubLookupElement(@Nullable final String variableName, final String methodName) {
|
||||
myVariableName = variableName;
|
||||
myMethodName = methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(final PsiJavaFile javaFile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInsertString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (myVariableName != null) {
|
||||
sb.append(myVariableName).append(".");
|
||||
}
|
||||
sb.append(myMethodName).append("()");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public interface SubLookupElement {
|
||||
|
||||
void doImport(final PsiJavaFile javaFile);
|
||||
|
||||
String getInsertString();
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class VariableSubLookupElement implements SubLookupElement {
|
||||
|
||||
private final String myVarName;
|
||||
|
||||
public VariableSubLookupElement(final PsiVariable variable) {
|
||||
myVarName = variable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(final PsiJavaFile javaFile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInsertString() {
|
||||
return myVarName;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,6 +11,6 @@ public class TestCompletion {
|
||||
void m() {
|
||||
String asd = "123";
|
||||
PsiManager psiManager = null;
|
||||
Project p = psiManager.getProject(asd, zxc)
|
||||
Project p = psiManager.getProject()
|
||||
}
|
||||
}
|
||||
|
||||
-7
@@ -20,9 +20,7 @@ import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.compiler.chainsSearch.ChainRelevance;
|
||||
import com.intellij.compiler.chainsSearch.completion.MethodChainCompletionContributor;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.ChainCompletionMethodCallLookupElement;
|
||||
import com.intellij.compiler.chainsSearch.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.testFramework.SkipSlowTestLocally;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -248,8 +246,6 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
}
|
||||
|
||||
private void doTestRendering() {
|
||||
PropertiesComponent.getInstance(getProject())
|
||||
.setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(true));
|
||||
compileAndIndexData(TEST_INDEX_FILE_NAME);
|
||||
myFixture.configureByFiles(getBeforeCompletionFilePath());
|
||||
for (LookupElement element : myFixture.complete(CompletionType.BASIC)) {
|
||||
@@ -259,9 +255,6 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PropertiesComponent.getInstance(getProject())
|
||||
.setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(false));
|
||||
myFixture.checkResultByFile(getAfterCompletionFilePath());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user