Converted more completion code to Kotlin

This commit is contained in:
Valentin Kipyatkov
2014-07-30 15:48:10 +04:00
parent 7219a521d7
commit 620c018b54
7 changed files with 140 additions and 197 deletions
@@ -19,6 +19,10 @@
name='com.intellij.codeInsight.completion.CompletionProvider void addCompletions(V, com.intellij.util.ProcessingContext, com.intellij.codeInsight.completion.CompletionResultSet) 1'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.completion.CompletionService com.intellij.codeInsight.completion.CompletionService getCompletionService()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.completion.CompletionSorter com.intellij.codeInsight.completion.CompletionSorter weighAfter(java.lang.String, com.intellij.codeInsight.lookup.LookupElementWeigher...)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
@@ -1,40 +0,0 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.plugin.completion;
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
import com.intellij.codeInsight.completion.CompletionService;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NotNull;
public class CompletionProgressIndicatorUtil {
private CompletionProgressIndicatorUtil() {
}
@NotNull
public static ProcessCanceledException rethrowWithCancelIndicator(ProcessCanceledException exception) {
CompletionProgressIndicator indicator = (CompletionProgressIndicator) CompletionService.getCompletionService().getCurrentCompletion();
assert indicator != null;
// Force cancel to avoid deadlock in CompletionThreading.delegateWeighing()
if (!indicator.isCanceled()) {
indicator.cancel();
}
return exception;
}
}
@@ -19,6 +19,9 @@ package org.jetbrains.jet.plugin.completion
import com.intellij.openapi.util.Key
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.AutoCompletionPolicy
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.codeInsight.completion.CompletionService
import com.intellij.codeInsight.completion.CompletionProgressIndicator
enum class ItemPriority {
DEFAULT
@@ -41,3 +44,13 @@ fun LookupElement.keepOldArgumentListOnTab(): LookupElement {
return this
}
fun rethrowWithCancelIndicator(exception: ProcessCanceledException): ProcessCanceledException {
val indicator = CompletionService.getCompletionService().getCurrentCompletion() as CompletionProgressIndicator
// Force cancel to avoid deadlock in CompletionThreading.delegateWeighing()
if (!indicator.isCanceled()) {
indicator.cancel()
}
return exception
}
@@ -1,144 +0,0 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.plugin.completion;
import com.google.common.collect.Lists;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.plugin.JetDescriptorIconProvider;
import org.jetbrains.jet.plugin.completion.handlers.CaretPosition;
import org.jetbrains.jet.plugin.completion.handlers.GenerateLambdaInfo;
import org.jetbrains.jet.plugin.completion.handlers.JetClassInsertHandler;
import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.List;
public final class DescriptorLookupConverter {
private DescriptorLookupConverter() {}
@NotNull
public static LookupElement createLookupElement(@NotNull KotlinCodeAnalyzer analyzer,
@NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) {
LookupElementBuilder element = LookupElementBuilder.create(
new DeclarationLookupObject(descriptor, analyzer, declaration), descriptor.getName().asString());
String presentableText = descriptor.getName().asString();
String typeText = "";
String tailText = "";
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
JetType returnType = functionDescriptor.getReturnType();
typeText = returnType != null ? DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(returnType) : "";
presentableText += DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(functionDescriptor);
boolean extensionFunction = functionDescriptor.getReceiverParameter() != null;
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration != null && extensionFunction) {
tailText += " for " + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(functionDescriptor.getReceiverParameter().getType());
tailText += " in " + DescriptorUtils.getFqName(containingDeclaration);
}
}
else if (descriptor instanceof VariableDescriptor) {
JetType outType = ((VariableDescriptor) descriptor).getType();
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(outType);
}
else if (descriptor instanceof ClassDescriptor) {
DeclarationDescriptor declaredIn = descriptor.getContainingDeclaration();
assert declaredIn != null;
tailText = " (" + DescriptorUtils.getFqName(declaredIn) + ")";
}
else {
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
}
InsertHandler<LookupElement> insertHandler = getDefaultInsertHandler(descriptor);
element = element.withInsertHandler(insertHandler);
if (insertHandler instanceof JetFunctionInsertHandler && ((JetFunctionInsertHandler)insertHandler).getLambdaInfo() != null) {
element.putUserData(JetCompletionCharFilter.ACCEPT_OPENING_BRACE, true);
}
element = element.withTailText(tailText, true).withTypeText(typeText).withPresentableText(presentableText);
element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY));
element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor));
return element;
}
@Nullable
public static InsertHandler<LookupElement> getDefaultInsertHandler(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
if (parameters.isEmpty()) {
return JetFunctionInsertHandler.NO_PARAMETERS_HANDLER;
}
if (parameters.size() == 1) {
JetType parameterType = parameters.get(0).getType();
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
int parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size();
if (parameterCount <= 1) { // otherwise additional item with lambda template is to be added
return new JetFunctionInsertHandler(CaretPosition.IN_BRACKETS, new GenerateLambdaInfo(parameterType, false));
}
}
}
return JetFunctionInsertHandler.WITH_PARAMETERS_HANDLER;
}
if (descriptor instanceof ClassDescriptor) {
return JetClassInsertHandler.INSTANCE$;
}
return null;
}
@NotNull
public static LookupElement createLookupElement(@NotNull KotlinCodeAnalyzer analyzer, @NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof CallableMemberDescriptor) {
descriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor);
}
return createLookupElement(analyzer, descriptor, DescriptorToSourceUtils.descriptorToDeclaration(descriptor));
}
@NotNull
public static LookupElement[] collectLookupElements(
@NotNull KotlinCodeAnalyzer analyzer,
@NotNull Iterable<DeclarationDescriptor> descriptors
) {
List<LookupElement> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : descriptors) {
result.add(createLookupElement(analyzer, descriptor));
}
return result.toArray(new LookupElement[result.size()]);
}
}
@@ -0,0 +1,114 @@
/*
* Copyright 2010-2014 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 org.jetbrains.jet.plugin.completion
import com.intellij.codeInsight.completion.InsertHandler
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.util.Iconable
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.descriptors.*
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.plugin.JetDescriptorIconProvider
import org.jetbrains.jet.plugin.completion.handlers.CaretPosition
import org.jetbrains.jet.plugin.completion.handlers.GenerateLambdaInfo
import org.jetbrains.jet.plugin.completion.handlers.JetClassInsertHandler
import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler
import org.jetbrains.jet.renderer.DescriptorRenderer
public object DescriptorLookupConverter {
public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, declaration: PsiElement?): LookupElement {
var element = LookupElementBuilder.create(DeclarationLookupObject(descriptor, analyzer, declaration), descriptor.getName().asString())
var presentableText = descriptor.getName().asString()
var typeText = ""
var tailText = ""
if (descriptor is FunctionDescriptor) {
val returnType = descriptor.getReturnType()
typeText = if (returnType != null) DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(returnType) else ""
presentableText += DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(descriptor)
if (descriptor.getReceiverParameter() != null) {
tailText += " for " + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getReceiverParameter()!!.getType())
tailText += " in " + DescriptorUtils.getFqName(descriptor.getContainingDeclaration())
}
}
else if (descriptor is VariableDescriptor) {
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getType())
}
else if (descriptor is ClassDescriptor) {
tailText = " (" + DescriptorUtils.getFqName(descriptor.getContainingDeclaration()) + ")"
}
else {
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor)
}
val insertHandler = getDefaultInsertHandler(descriptor)
element = element.withInsertHandler(insertHandler)
if (insertHandler is JetFunctionInsertHandler && insertHandler.lambdaInfo != null) {
element.putUserData<Boolean>(JetCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
}
element = element.withTailText(tailText, true).withTypeText(typeText).withPresentableText(presentableText)
element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor))
return element
}
public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler<LookupElement>? {
return when (descriptor) {
is FunctionDescriptor -> {
val parameters = descriptor.getValueParameters()
when (parameters.size) {
0 -> JetFunctionInsertHandler.NO_PARAMETERS_HANDLER
1 -> {
val parameterType = parameters.single().getType()
if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) {
val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size()
if (parameterCount <= 1) {
// otherwise additional item with lambda template is to be added
return JetFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false))
}
}
JetFunctionInsertHandler.WITH_PARAMETERS_HANDLER
}
else -> JetFunctionInsertHandler.WITH_PARAMETERS_HANDLER
}
}
is ClassDescriptor -> JetClassInsertHandler
else -> null
}
}
public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement {
val _descriptor = if (descriptor is CallableMemberDescriptor)
DescriptorUtils.unwrapFakeOverride(descriptor)
else
descriptor
return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor))
}
}
@@ -133,7 +133,7 @@ public class JetCompletionContributor : CompletionContributor() {
}
}
catch (e: ProcessCanceledException) {
throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e)
throw rethrowWithCancelIndicator(e)
}
}
}
@@ -17,20 +17,15 @@
package org.jetbrains.jet.plugin.completion
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.patterns.ElementPattern
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.util.ProcessingContext
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.JetPackageDirective
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.caches.resolve.*
import org.jetbrains.jet.plugin.codeInsight.TipsManager
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
import org.jetbrains.jet.plugin.references.JetSimpleNameReference
/**
@@ -47,10 +42,10 @@ public class JetPackagesContributor : CompletionContributor() {
{
extend(CompletionType.BASIC, ACTIVATION_PATTERN, object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
val position = parameters.getPosition()
if (position.getContainingFile() !is JetFile) return
val file = parameters.getPosition().getContainingFile()
if (file !is JetFile) return
val ref = parameters.getPosition().getContainingFile()!!.findReferenceAt(parameters.getOffset())
val ref = file.findReferenceAt(parameters.getOffset())
if (ref is JetSimpleNameReference) {
val name = ref.expression.getText() ?: return
@@ -63,16 +58,17 @@ public class JetPackagesContributor : CompletionContributor() {
val bindingContext = resolveSession.resolveToElement(ref.expression)
val variants = TipsManager.getPackageReferenceVariants(ref.expression, bindingContext)
for (variant in DescriptorLookupConverter.collectLookupElements(resolveSession, variants)) {
if (!variant.getLookupString().contains(DUMMY_IDENTIFIER)) {
result.addElement(variant)
for (variant in variants) {
val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, variant)
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
result.addElement(lookupElement)
}
}
result.stopHere()
}
catch (e: ProcessCanceledException) {
throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e)
throw rethrowWithCancelIndicator(e)
}
}
}