KT-3157 Java void method are inserted with ; after completion

#KT-3157 Fixed
This commit is contained in:
Nikolay Krasko
2012-12-13 20:53:44 +04:00
parent 1f12658ce7
commit 689cff6196
5 changed files with 101 additions and 24 deletions
@@ -17,10 +17,13 @@
package org.jetbrains.jet.plugin.completion; package org.jetbrains.jet.plugin.completion;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaMethodCallElement; import com.intellij.codeInsight.completion.JavaMethodCallElement;
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement; import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.MutableLookupElement;
import com.intellij.codeInsight.lookup.VariableLookupItem; import com.intellij.codeInsight.lookup.VariableLookupItem;
import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Iconable;
import com.intellij.psi.*; import com.intellij.psi.*;
@@ -62,9 +65,15 @@ public final class DescriptorLookupConverter {
public static LookupElement createLookupElement(@NotNull ResolveSession resolveSession, public static LookupElement createLookupElement(@NotNull ResolveSession resolveSession,
@NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) {
if (declaration != null) { if (declaration != null) {
LookupElement javaLookupElement = createJavaLookupElementIfPossible(declaration); MutableLookupElement javaLookupElement = createJavaLookupElementIfPossible(declaration);
if (javaLookupElement != null) { if (javaLookupElement != null) {
return javaLookupElement; InsertHandler<LookupElement> customHandler = getInsertHandler(descriptor);
if (customHandler != null) {
return javaLookupElement.setInsertHandler(getInsertHandler(descriptor));
}
else {
return javaLookupElement;
}
} }
} }
@@ -88,20 +97,6 @@ public final class DescriptorLookupConverter {
tailText += " for " + DescriptorRenderer.TEXT.renderType(functionDescriptor.getReceiverParameter().getType()); tailText += " for " + DescriptorRenderer.TEXT.renderType(functionDescriptor.getReceiverParameter().getType());
tailText += " in " + DescriptorUtils.getFQName(containingDeclaration); tailText += " in " + DescriptorUtils.getFQName(containingDeclaration);
} }
// TODO: A special case when it's impossible to resolve type parameters from arguments. Need '<' caret '>'
// TODO: Support omitting brackets for one argument functions
if (functionDescriptor.getValueParameters().isEmpty()) {
element = element.withInsertHandler(EMPTY_FUNCTION_HANDLER);
}
else {
if (functionDescriptor.getValueParameters().size() == 1
&& KotlinBuiltIns.getInstance().isFunctionType(functionDescriptor.getValueParameters().get(0).getType())) {
element = element.withInsertHandler(PARAMS_BRACES_FUNCTION_HANDLER);
} else {
element = element.withInsertHandler(PARAMS_PARENTHESIS_FUNCTION_HANDLER);
}
}
} }
else if (descriptor instanceof VariableDescriptor) { else if (descriptor instanceof VariableDescriptor) {
JetType outType = ((VariableDescriptor) descriptor).getType(); JetType outType = ((VariableDescriptor) descriptor).getType();
@@ -112,12 +107,12 @@ public final class DescriptorLookupConverter {
assert declaredIn != null; assert declaredIn != null;
tailText = " (" + DescriptorUtils.getFQName(declaredIn) + ")"; tailText = " (" + DescriptorUtils.getFQName(declaredIn) + ")";
tailTextGrayed = true; tailTextGrayed = true;
element = element.withInsertHandler(JetClassInsertHandler.INSTANCE);
} }
else { else {
typeText = DescriptorRenderer.TEXT.render(descriptor); typeText = DescriptorRenderer.TEXT.render(descriptor);
} }
element = element.withInsertHandler(getInsertHandler(descriptor));
element = element.withTailText(tailText, tailTextGrayed).withTypeText(typeText).withPresentableText(presentableText); element = element.withTailText(tailText, tailTextGrayed).withTypeText(typeText).withPresentableText(presentableText);
element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, Iconable.ICON_FLAG_VISIBILITY)); element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, Iconable.ICON_FLAG_VISIBILITY));
element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor)); element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor));
@@ -125,11 +120,35 @@ public final class DescriptorLookupConverter {
} }
@Nullable @Nullable
private static LookupElement createJavaLookupElementIfPossible(@NotNull PsiElement declaration) { private static InsertHandler<LookupElement> getInsertHandler(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (functionDescriptor.getValueParameters().isEmpty()) {
return EMPTY_FUNCTION_HANDLER;
}
if (functionDescriptor.getValueParameters().size() == 1
&& KotlinBuiltIns.getInstance().isFunctionType(functionDescriptor.getValueParameters().get(0).getType())) {
return PARAMS_BRACES_FUNCTION_HANDLER;
}
return PARAMS_PARENTHESIS_FUNCTION_HANDLER;
}
if (descriptor instanceof ClassDescriptor) {
return JetClassInsertHandler.INSTANCE;
}
return null;
}
@Nullable
private static MutableLookupElement createJavaLookupElementIfPossible(@NotNull PsiElement declaration) {
if (declaration instanceof PsiClass) { if (declaration instanceof PsiClass) {
PsiClass psiClass = (PsiClass) declaration; PsiClass psiClass = (PsiClass) declaration;
if (!DecompiledDataFactory.isCompiledFromKotlin(psiClass)) { if (!DecompiledDataFactory.isCompiledFromKotlin(psiClass)) {
return new JavaPsiClassReferenceElement(psiClass).setInsertHandler(JetJavaClassInsertHandler.INSTANCE); return new JavaPsiClassReferenceElement(psiClass);
} }
} }
@@ -137,11 +156,11 @@ public final class DescriptorLookupConverter {
PsiClass containingClass = ((PsiMember) declaration).getContainingClass(); PsiClass containingClass = ((PsiMember) declaration).getContainingClass();
if (containingClass != null && !DecompiledDataFactory.isCompiledFromKotlin(containingClass)) { if (containingClass != null && !DecompiledDataFactory.isCompiledFromKotlin(containingClass)) {
if (declaration instanceof PsiMethod) { if (declaration instanceof PsiMethod) {
return new JavaMethodCallElement((PsiMethod) declaration); return new JavaMethodCallElementWithCustomHandler(declaration);
} }
if (declaration instanceof PsiField) { if (declaration instanceof PsiField) {
return new VariableLookupItem((PsiField) declaration); return new JavaVariableLookupItemWithCustomHandler(declaration);
} }
} }
} }
@@ -149,6 +168,10 @@ public final class DescriptorLookupConverter {
return null; return null;
} }
public static LookupElement setCustomInsertHandler(JavaPsiClassReferenceElement javaPsiReferenceElement) {
return javaPsiReferenceElement.setInsertHandler(JetJavaClassInsertHandler.INSTANCE);
}
@NotNull @NotNull
public static LookupElement createLookupElement( public static LookupElement createLookupElement(
@NotNull ResolveSession resolveSession, @NotNull ResolveSession resolveSession,
@@ -177,4 +200,40 @@ public final class DescriptorLookupConverter {
return result.toArray(new LookupElement[result.size()]); return result.toArray(new LookupElement[result.size()]);
} }
private static class JavaMethodCallElementWithCustomHandler extends JavaMethodCallElement {
public JavaMethodCallElementWithCustomHandler(PsiElement declaration) {
super((PsiMethod) declaration);
}
@Override
public void handleInsert(InsertionContext context) {
final InsertHandler<? extends LookupElement> handler = getInsertHandler();
if (handler != null) {
//noinspection unchecked
((InsertHandler)handler).handleInsert(context, this);
return;
}
super.handleInsert(context);
}
}
private static class JavaVariableLookupItemWithCustomHandler extends VariableLookupItem {
public JavaVariableLookupItemWithCustomHandler(PsiElement declaration) {
super((PsiField) declaration);
}
@Override
public void handleInsert(InsertionContext context) {
final InsertHandler<? extends LookupElement> handler = getInsertHandler();
if (handler != null) {
//noinspection unchecked
((InsertHandler)handler).handleInsert(context, this);
return;
}
super.handleInsert(context);
}
}
} }
@@ -29,7 +29,6 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.plugin.caches.JetCacheManager; import org.jetbrains.jet.plugin.caches.JetCacheManager;
import org.jetbrains.jet.plugin.caches.JetShortNamesCache; import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler;
import org.jetbrains.jet.plugin.libraries.DecompiledDataFactory; import org.jetbrains.jet.plugin.libraries.DecompiledDataFactory;
import org.jetbrains.jet.plugin.project.JsModuleDetector; import org.jetbrains.jet.plugin.project.JsModuleDetector;
@@ -76,8 +75,7 @@ public class JetTypesCompletionHelper {
return; return;
} }
// Redefine standard java insert handler which is going to insert fqn jetCompletionResult.addElement(DescriptorLookupConverter.setCustomInsertHandler(javaPsiReferenceElement));
jetCompletionResult.addElement(javaPsiReferenceElement.setInsertHandler(JetJavaClassInsertHandler.INSTANCE));
} }
} }
}); });
@@ -0,0 +1,7 @@
import java.io.File
fun test() {
val f = File("testFile")
// Should be no ;
f.deleteOnExit<caret>
}
@@ -0,0 +1,7 @@
import java.io.File
fun test() {
val f = File("testFile")
// Should be no ;
f.deleteOnExit()
}
@@ -26,6 +26,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import junit.framework.Assert; import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.PluginTestCaseBase; import org.jetbrains.jet.plugin.PluginTestCaseBase;
import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings; import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings;
@@ -65,6 +66,10 @@ public class CompletionHandlerTest extends LightCompletionTestCase {
doTest(); doTest();
} }
public void testInsertVoidJavaMethod() {
doTest();
}
public void testPropertiesSetter() { public void testPropertiesSetter() {
doTest(); doTest();
} }
@@ -193,6 +198,7 @@ public class CompletionHandlerTest extends LightCompletionTestCase {
return getTestName(false) + ".kt.after"; return getTestName(false) + ".kt.after";
} }
@NotNull
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + File.separator; return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + File.separator;