From 3f62a960287ea4f08126e30e410ea66ee98d817a Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 30 Jul 2014 14:46:51 +0400 Subject: [PATCH] Converting completion code to Kotlin --- .../codeInsight/completion/annotations.xml | 20 ++ .../openapi/diagnostic/annotations.xml | 3 + .../com/intellij/patterns/annotations.xml | 96 +++++++++ .../com/intellij/psi/filters/annotations.xml | 5 + .../CompletionProgressIndicatorUtil.java | 2 + .../plugin/completion/CompletionSession.java | 2 + .../plugin/completion/CompletionSorting.kt | 8 +- .../completion/DeclarationLookupObject.java | 86 -------- .../completion/DeclarationLookupObject.kt | 54 +++++ .../completion/DescriptorLookupConverter.java | 1 + .../completion/JetCompletionContributor.java | 185 ------------------ .../completion/JetCompletionContributor.kt | 171 ++++++++++++++++ .../JetExtensionReceiverTypeContributor.java | 54 ----- .../JetExtensionReceiverTypeContributor.kt | 48 +++++ .../JetKeywordCompletionContributor.kt | 17 +- .../completion/JetPackagesContributor.java | 98 ---------- .../completion/JetPackagesContributor.kt | 81 ++++++++ .../KotlinNamedParametersContributor.kt | 2 +- .../plugin/completion/LeafElementFilter.java | 43 ---- .../plugin/completion/LeafElementFilter.kt | 36 ++++ .../handlers/JetClassInsertHandler.kt | 2 +- .../handlers/JetFunctionInsertHandler.kt | 16 +- 22 files changed, 541 insertions(+), 489 deletions(-) create mode 100644 annotations/com/intellij/psi/filters/annotations.xml delete mode 100644 idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.kt delete mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.kt delete mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.kt delete mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.kt delete mode 100644 idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.kt diff --git a/annotations/com/intellij/codeInsight/completion/annotations.xml b/annotations/com/intellij/codeInsight/completion/annotations.xml index 1e74e946e0c..935b49e4d51 100644 --- a/annotations/com/intellij/codeInsight/completion/annotations.xml +++ b/annotations/com/intellij/codeInsight/completion/annotations.xml @@ -1,4 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/annotations/com/intellij/openapi/diagnostic/annotations.xml b/annotations/com/intellij/openapi/diagnostic/annotations.xml index d9806ca45bc..8a460a47645 100644 --- a/annotations/com/intellij/openapi/diagnostic/annotations.xml +++ b/annotations/com/intellij/openapi/diagnostic/annotations.xml @@ -2,4 +2,7 @@ + + + \ No newline at end of file diff --git a/annotations/com/intellij/patterns/annotations.xml b/annotations/com/intellij/patterns/annotations.xml index 92b6a535cd5..649091075dd 100644 --- a/annotations/com/intellij/patterns/annotations.xml +++ b/annotations/com/intellij/patterns/annotations.xml @@ -2,6 +2,9 @@ + + + @@ -14,7 +17,100 @@ name='com.intellij.patterns.PlatformPatterns com.intellij.patterns.PsiElementPattern.Capture<com.intellij.psi.PsiElement> psiElement(com.intellij.psi.tree.IElementType)'> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/annotations/com/intellij/psi/filters/annotations.xml b/annotations/com/intellij/psi/filters/annotations.xml new file mode 100644 index 00000000000..f7b53387912 --- /dev/null +++ b/annotations/com/intellij/psi/filters/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionProgressIndicatorUtil.java b/idea/src/org/jetbrains/jet/plugin/completion/CompletionProgressIndicatorUtil.java index d5a297bfaf8..de312447bc2 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionProgressIndicatorUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionProgressIndicatorUtil.java @@ -19,11 +19,13 @@ 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; diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java index f86a81a0928..a824c36a4a4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java @@ -291,10 +291,12 @@ class CompletionSession { return parameters.getPosition(); } + @NotNull public JetCompletionResultSet getJetResult() { return jetResult; } + @NotNull public CompletionParameters getParameters() { return parameters; } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt index 7208af048c9..c93fe5e8edc 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSorting.kt @@ -68,7 +68,7 @@ private object KindWeigher : LookupElementWeigher("kotlin.kind") { override fun weigh(element: LookupElement): Weight { val o = element.getObject() return when (o) { - is DeclarationLookupObject -> when (o.getDescriptor()) { + is DeclarationLookupObject -> when (o.descriptor) { is LocalVariableDescriptor, is ValueParameterDescriptor -> Weight.localOrParameter is PropertyDescriptor -> Weight.property is PackageViewDescriptor -> Weight.packages @@ -86,7 +86,7 @@ private object DeprecatedWeigher : LookupElementWeigher("kotlin.deprecated") { override fun weigh(element: LookupElement): Int { val o = element.getObject() if (o is DeclarationLookupObject) { - val descriptor = o.getDescriptor() + val descriptor = o.descriptor if (descriptor != null && KotlinBuiltIns.getInstance().isDeprecated(descriptor)) return 1 } @@ -115,12 +115,12 @@ private class JetDeclarationRemotenessWeigher(private val file: JetFile) : Looku override fun weigh(element: LookupElement): Weight { val o = element.getObject() if (o is DeclarationLookupObject) { - val elementFile = o.getPsiElement()?.getContainingFile() + val elementFile = o.psiElement?.getContainingFile() if (elementFile is JetFile && elementFile.getOriginalFile() == file) { return Weight.thisFile } - val descriptor = o.getDescriptor() + val descriptor = o.descriptor if (descriptor != null) { val fqName = DescriptorUtils.getFqName(descriptor).toString() // Invalid name can be met for class object descriptor: Test.MyTest.A..testOther diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.java b/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.java deleted file mode 100644 index 69b9c5e7e89..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.java +++ /dev/null @@ -1,86 +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.openapi.diagnostic.Logger; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer; - -/** - * Stores information about resolved descriptor and position of that descriptor. - * Position will be used for sorting - */ -public final class DeclarationLookupObject { - private static final Logger LOG = Logger.getInstance("#" + DeclarationLookupObject.class.getName()); - - @Nullable - private final DeclarationDescriptor descriptor; - - @NotNull - private final KotlinCodeAnalyzer analyzer; - - @Nullable - private final PsiElement psiElement; - - public DeclarationLookupObject( - @Nullable DeclarationDescriptor descriptor, - @NotNull KotlinCodeAnalyzer analyzer, - @Nullable PsiElement psiElement - ) { - this.descriptor = descriptor; - this.analyzer = analyzer; - this.psiElement = psiElement; - } - - @Nullable - public DeclarationDescriptor getDescriptor() { - return descriptor; - } - - @Nullable - public PsiElement getPsiElement() { - return psiElement; - } - - @Override - public String toString() { - return super.toString() + " " + descriptor; - } - - @Override - public int hashCode() { - return descriptor != null ? descriptor.hashCode() : 0; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - - DeclarationLookupObject lookupObject = (DeclarationLookupObject) obj; - - if (!analyzer.equals(lookupObject.analyzer)) { - LOG.warn("Descriptors from different resolve sessions"); - return false; - } - - return descriptor != null ? descriptor.equals(lookupObject.descriptor) : lookupObject.descriptor == null; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.kt b/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.kt new file mode 100644 index 00000000000..7c959c9dc56 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/DeclarationLookupObject.kt @@ -0,0 +1,54 @@ +/* + * 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.openapi.diagnostic.Logger +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor +import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer + +/** + * Stores information about resolved descriptor and position of that descriptor. + * Position will be used for sorting + */ +public class DeclarationLookupObject(public val descriptor: DeclarationDescriptor?, private val analyzer: KotlinCodeAnalyzer, public val psiElement: PsiElement?) { + override fun toString(): String { + return super.toString() + " " + descriptor + } + + override fun hashCode(): Int { + return if (descriptor != null) descriptor!!.hashCode() else 0 + } + + override fun equals(other: Any?): Boolean { + if (this identityEquals other) return true + if (other == null || javaClass != other.javaClass) return false + + val lookupObject = other as DeclarationLookupObject + + if (analyzer != lookupObject.analyzer) { + LOG.warn("Descriptors from different resolve sessions") + return false + } + + return lookupObject.descriptor == descriptor + } + + class object { + private val LOG = Logger.getInstance("#" + javaClass().getName()) + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java index 55bfde6ded9..d2dd702dca3 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java @@ -128,6 +128,7 @@ public final class DescriptorLookupConverter { return createLookupElement(analyzer, descriptor, DescriptorToSourceUtils.descriptorToDeclaration(descriptor)); } + @NotNull public static LookupElement[] collectLookupElements( @NotNull KotlinCodeAnalyzer analyzer, @NotNull Iterable descriptors diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java deleted file mode 100644 index 131ae22a455..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ /dev/null @@ -1,185 +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.*; -import com.intellij.openapi.editor.Document; -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.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetBlockExpression; -import org.jetbrains.jet.lang.psi.JetCallExpression; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.plugin.completion.smart.SmartCompletion; -import org.jetbrains.jet.plugin.references.JetSimpleNameReference; - -import static com.intellij.patterns.PsiJavaPatterns.elementType; -import static com.intellij.patterns.PsiJavaPatterns.psiElement; - -public class JetCompletionContributor extends CompletionContributor { - private static final ElementPattern AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping( - psiElement().withText(""), - psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL))); - - public JetCompletionContributor() { - CompletionProvider provider = new CompletionProvider() { - @Override - protected void addCompletions( - @NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result - ) { - doSimpleReferenceCompletion(parameters, result); - } - }; - extend(CompletionType.BASIC, PlatformPatterns.psiElement(), provider); - extend(CompletionType.SMART, PlatformPatterns.psiElement(), provider); - } - - public static void doSimpleReferenceCompletion(CompletionParameters parameters, CompletionResultSet result) { - PsiElement position = parameters.getPosition(); - - if (!(position.getContainingFile() instanceof JetFile)) return; - - if (AFTER_NUMBER_LITERAL.accepts(parameters.getPosition())) { - // First Kotlin completion contributors - stop here will stop all completion - result.stopHere(); - return; - } - - JetSimpleNameReference jetReference = getJetReference(parameters); - if (jetReference != null) { - try { - result.restartCompletionWhenNothingMatches(); - - CompletionSession session = new CompletionSession(parameters, result, jetReference, position); - if (parameters.getCompletionType() == CompletionType.BASIC) { - session.completeForReference(); - - if (!session.getJetResult().isSomethingAdded() - && session.getParameters().getInvocationCount() < 2) { - // Rerun completion if nothing was found - session = new CompletionSession(parameters.withInvocationCount(2), result, jetReference, position); - session.completeForReference(); - } - } - else { - session.completeSmart(); - } - } - catch (ProcessCanceledException e) { - throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e); - } - } - } - - @Nullable - private static JetSimpleNameReference getJetReference(@NotNull CompletionParameters parameters) { - PsiElement element = parameters.getPosition(); - if (element.getParent() != null) { - PsiElement parent = element.getParent(); - PsiReference[] references = parent.getReferences(); - - if (references.length != 0) { - for (PsiReference reference : references) { - if (reference instanceof JetSimpleNameReference) { - return (JetSimpleNameReference)reference; - } - } - } - } - - return null; - } - - @Override - public void beforeCompletion(@NotNull CompletionInitializationContext context) { - if (context.getFile() instanceof JetFile) { - int offset = context.getStartOffset(); - PsiElement tokenBefore = context.getFile().findElementAt(Math.max(0, offset - 1)); - if (context.getCompletionType() == CompletionType.SMART) { - context.setDummyIdentifier(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + "$"); // add '$' to ignore context after the caret - } - else { - if (JetPackagesContributor.ACTIVATION_PATTERN.accepts(tokenBefore)) { - context.setDummyIdentifier(JetPackagesContributor.DUMMY_IDENTIFIER); - } - else if (JetExtensionReceiverTypeContributor.ACTIVATION_PATTERN.accepts(tokenBefore)) { - context.setDummyIdentifier(JetExtensionReceiverTypeContributor.DUMMY_IDENTIFIER); - } - else{ - context.setDummyIdentifier(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED); - } - } - - // this code will make replacement offset "modified" and prevents altering it by the code in CompletionProgressIndicator - context.setReplacementOffset(context.getReplacementOffset()); - - if (context.getCompletionType() == CompletionType.SMART - && !isAtEndOfLine(offset, context.getEditor().getDocument()) /* do not use parent expression if we are at the end of line - it's probably parsed incorrectly */) { - - PsiElement tokenAt = context.getFile().findElementAt(Math.max(0, offset)); - if (tokenAt != null) { - PsiElement parent = tokenAt.getParent(); - if (parent instanceof JetExpression && !(parent instanceof JetBlockExpression)) { - // search expression to be replaced - go up while we are the first child of parent expression - JetExpression expression = (JetExpression) parent; - parent = expression.getParent(); - while (parent instanceof JetExpression && parent.getFirstChild() == expression) { - expression = (JetExpression) parent; - parent = expression.getParent(); - } - - int expressionEnd = expression.getTextRange().getEndOffset(); - int suggestedReplacementOffset; - if (expression instanceof JetCallExpression) { - JetExpression calleeExpression = ((JetCallExpression) expression).getCalleeExpression(); - suggestedReplacementOffset = calleeExpression != null ? calleeExpression.getTextRange().getEndOffset() : expressionEnd; - } - else { - suggestedReplacementOffset = expressionEnd; - } - if (suggestedReplacementOffset > context.getReplacementOffset()) { - context.setReplacementOffset(suggestedReplacementOffset); - } - - context.getOffsetMap().addOffset(SmartCompletion.OLD_ARGUMENTS_REPLACEMENT_OFFSET, expressionEnd); - } - } - } - } - } - - private static boolean isAtEndOfLine(int offset, Document document) { - int i = offset; - CharSequence chars = document.getCharsSequence(); - while (i < chars.length()) { - char c = chars.charAt(i); - if (c == '\n' || c == 'r') return true; - if (!Character.isWhitespace(c)) return false; - i++; - } - return true; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.kt new file mode 100644 index 00000000000..b2dd2bbe2fd --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.kt @@ -0,0 +1,171 @@ +/* + * 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.* +import com.intellij.openapi.editor.Document +import com.intellij.openapi.progress.ProcessCanceledException +import com.intellij.patterns.PlatformPatterns +import com.intellij.util.ProcessingContext +import org.jetbrains.jet.lang.psi.JetBlockExpression +import org.jetbrains.jet.lang.psi.JetCallExpression +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.psi.JetFile +import org.jetbrains.jet.lexer.JetTokens +import org.jetbrains.jet.plugin.completion.smart.SmartCompletion +import org.jetbrains.jet.plugin.references.JetSimpleNameReference + +import com.intellij.patterns.PsiJavaPatterns.elementType +import com.intellij.patterns.PsiJavaPatterns.psiElement + +public class JetCompletionContributor : CompletionContributor() { + + { + val provider = object : CompletionProvider() { + override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { + doSimpleReferenceCompletion(parameters, result) + } + } + extend(CompletionType.BASIC, PlatformPatterns.psiElement(), provider) + extend(CompletionType.SMART, PlatformPatterns.psiElement(), provider) + } + + override fun beforeCompletion(context: CompletionInitializationContext) { + val psiFile = context.getFile() + if (psiFile !is JetFile) return + + val offset = context.getStartOffset() + val tokenBefore = psiFile.findElementAt(Math.max(0, offset - 1)) + if (context.getCompletionType() == CompletionType.SMART) { + context.setDummyIdentifier(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + "$") // add '$' to ignore context after the caret + } + else { + if (JetPackagesContributor.ACTIVATION_PATTERN.accepts(tokenBefore)) { + context.setDummyIdentifier(JetPackagesContributor.DUMMY_IDENTIFIER) + } + else if (JetExtensionReceiverTypeContributor.ACTIVATION_PATTERN.accepts(tokenBefore)) { + context.setDummyIdentifier(JetExtensionReceiverTypeContributor.DUMMY_IDENTIFIER) + } + else { + context.setDummyIdentifier(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED) + } + } + + // this code will make replacement offset "modified" and prevents altering it by the code in CompletionProgressIndicator + context.setReplacementOffset(context.getReplacementOffset()) + + if (context.getCompletionType() == CompletionType.SMART && !isAtEndOfLine(offset, context.getEditor().getDocument()) /* do not use parent expression if we are at the end of line - it's probably parsed incorrectly */) { + + val tokenAt = psiFile.findElementAt(Math.max(0, offset)) + if (tokenAt != null) { + var parent = tokenAt.getParent() + if (parent is JetExpression && parent !is JetBlockExpression) { + // search expression to be replaced - go up while we are the first child of parent expression + var expression = parent as JetExpression + parent = expression.getParent() + while (parent is JetExpression && parent!!.getFirstChild() == expression) { + expression = parent as JetExpression + parent = expression.getParent() + } + + val expressionEnd = expression.getTextRange()!!.getEndOffset() + val suggestedReplacementOffset: Int + if (expression is JetCallExpression) { + val calleeExpression = (expression as JetCallExpression).getCalleeExpression() + suggestedReplacementOffset = if (calleeExpression != null) calleeExpression.getTextRange()!!.getEndOffset() else expressionEnd + } + else { + suggestedReplacementOffset = expressionEnd + } + if (suggestedReplacementOffset > context.getReplacementOffset()) { + context.setReplacementOffset(suggestedReplacementOffset) + } + + context.getOffsetMap().addOffset(SmartCompletion.OLD_ARGUMENTS_REPLACEMENT_OFFSET, expressionEnd) + } + } + } + } + + class object { + private val AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping(psiElement().withText(""), psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL))) + + public fun doSimpleReferenceCompletion(parameters: CompletionParameters, result: CompletionResultSet) { + val position = parameters.getPosition() + if (position.getContainingFile() !is JetFile) return + + if (AFTER_NUMBER_LITERAL.accepts(parameters.getPosition())) { + // First Kotlin completion contributors - stop here will stop all completion + result.stopHere() + return + } + + val jetReference = getJetReference(parameters) + if (jetReference != null) { + try { + result.restartCompletionWhenNothingMatches() + + var session = CompletionSession(parameters, result, jetReference, position) + if (parameters.getCompletionType() == CompletionType.BASIC) { + session.completeForReference() + + if (!session.getJetResult().isSomethingAdded() && session.getParameters().getInvocationCount() < 2) { + // Rerun completion if nothing was found + session = CompletionSession(parameters.withInvocationCount(2), result, jetReference, position) + session.completeForReference() + } + } + else { + session.completeSmart() + } + } + catch (e: ProcessCanceledException) { + throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e) + } + } + } + + private fun getJetReference(parameters: CompletionParameters): JetSimpleNameReference? { + val element = parameters.getPosition() + val parent = element.getParent() + if (parent != null) { + val references = parent.getReferences() + if (references.size != 0) { + for (reference in references) { + if (reference is JetSimpleNameReference) { + return reference as JetSimpleNameReference + } + } + } + } + + return null + } + + private fun isAtEndOfLine(offset: Int, document: Document): Boolean { + var i = offset + val chars = document.getCharsSequence() + while (i < chars.length()) { + val c = chars.charAt(i) + if (c == '\n' || c == 'r') return true + if (!Character.isWhitespace(c)) return false + i++ + } + return true + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java deleted file mode 100644 index 2676a853545..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java +++ /dev/null @@ -1,54 +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.*; -import com.intellij.patterns.ElementPattern; -import com.intellij.patterns.PlatformPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.util.ProcessingContext; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lexer.JetTokens; - -/** - * Special contributor for getting completion of type for extensions receiver. - */ -public class JetExtensionReceiverTypeContributor extends CompletionContributor { - // A way to add reference into file at completion place - public static final String DUMMY_IDENTIFIER = "KotlinExtensionDummy.fake() {}"; - - public static final ElementPattern ACTIVATION_PATTERN = - PlatformPatterns.psiElement().afterLeaf( - JetTokens.FUN_KEYWORD.toString(), - JetTokens.VAL_KEYWORD.toString(), - JetTokens.VAR_KEYWORD.toString()); - - public JetExtensionReceiverTypeContributor() { - extend(CompletionType.BASIC, ACTIVATION_PATTERN, new CompletionProvider() { - @Override - protected void addCompletions( - @NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result - ) { - if (parameters.getInvocationCount() > 0) { - JetCompletionContributor.doSimpleReferenceCompletion(parameters, result); - } - - result.stopHere(); - } - }); - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.kt new file mode 100644 index 00000000000..12544d6ec23 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.kt @@ -0,0 +1,48 @@ +/* + * 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.* +import com.intellij.patterns.PlatformPatterns +import com.intellij.util.ProcessingContext +import org.jetbrains.jet.lexer.JetTokens +import com.intellij.psi.PsiElement +import com.intellij.patterns.PsiElementPattern + +/** + * Special contributor for getting completion of type for extensions receiver. + */ +public class JetExtensionReceiverTypeContributor : CompletionContributor() { + class object { + // A way to add reference into file at completion place + public val DUMMY_IDENTIFIER: String = "KotlinExtensionDummy.fake() {}" + + public val ACTIVATION_PATTERN: PsiElementPattern.Capture = PlatformPatterns.psiElement().afterLeaf(JetTokens.FUN_KEYWORD.toString(), JetTokens.VAL_KEYWORD.toString(), JetTokens.VAR_KEYWORD.toString()) + } + + { + extend(CompletionType.BASIC, ACTIVATION_PATTERN, object : CompletionProvider() { + override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { + if (parameters.getInvocationCount() > 0) { + JetCompletionContributor.doSimpleReferenceCompletion(parameters, result) + } + + result.stopHere() + } + }) + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.kt index af0366aa085..8a59a6b22df 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.kt @@ -42,7 +42,7 @@ import com.intellij.psi.filters.position.PatternFilter class KeywordLookupObject(val keyword: String) -public open class JetKeywordCompletionContributor() : CompletionContributor() { +public class JetKeywordCompletionContributor : CompletionContributor() { { val inTopLevel = notIdentifier(InTopFilter()) val inTypeParameterFirstChildFilter = InTypeParameterFirstChildFilter() @@ -160,11 +160,11 @@ public open class JetKeywordCompletionContributor() : CompletionContributor() { PlatformPatterns.psiElement().and(FilterPattern(AndFilter(GENERAL_FILTER, placeFilter))) private open class CommentFilter() : ElementFilter { - override fun isAcceptable(element : Any?, context : PsiElement?) : Boolean { - return (element is PsiElement) && JetPsiUtil.isInComment(element as PsiElement) - } + override fun isAcceptable(element : Any?, context : PsiElement?) + = (element is PsiElement) && JetPsiUtil.isInComment(element as PsiElement) - override fun isClassAcceptable(hintClass: Class?): Boolean = true + override fun isClassAcceptable(hintClass: Class) + = true } private open class ParentFilter(filter : ElementFilter) : PositionElementFilter() { @@ -192,9 +192,8 @@ public open class JetKeywordCompletionContributor() : CompletionContributor() { } private open class InNonClassBlockFilter() : PositionElementFilter() { - override fun isAcceptable(element : Any?, context : PsiElement?) : Boolean { - return PsiTreeUtil.getParentOfType(context, javaClass(), true, javaClass()) != null - } + override fun isAcceptable(element : Any?, context : PsiElement?) + = PsiTreeUtil.getParentOfType(context, javaClass(), true, javaClass()) != null } private open class InTypeParameterFirstChildFilter() : PositionElementFilter() { @@ -280,7 +279,7 @@ public open class JetKeywordCompletionContributor() : CompletionContributor() { } } - override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext?, result: CompletionResultSet) { + override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { result.addKotlinSorting(parameters).withPrefixMatcher(SimplePrefixMatcher(result.getPrefixMatcher().getPrefix())).addAllElements(elements) } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java deleted file mode 100644 index 80e4f4114a3..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.java +++ /dev/null @@ -1,98 +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.*; -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.annotations.NotNull; -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.ResolvePackage; -import org.jetbrains.jet.plugin.codeInsight.TipsManager; -import org.jetbrains.jet.plugin.project.ResolveSessionForBodies; -import org.jetbrains.jet.plugin.references.JetSimpleNameReference; - -import java.util.Collection; - -/** - * Performs completion in package directive. Should suggest only packages and avoid showing fake package produced by - * DUMMY_IDENTIFIER. - */ -public class JetPackagesContributor extends CompletionContributor { - - static final String DUMMY_IDENTIFIER = "___package___"; - - static final ElementPattern ACTIVATION_PATTERN = - PlatformPatterns.psiElement().inside(JetPackageDirective.class); - - - public JetPackagesContributor() { - extend(CompletionType.BASIC, ACTIVATION_PATTERN, - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, - @NotNull CompletionResultSet result) { - - PsiElement position = parameters.getPosition(); - if (!(position.getContainingFile() instanceof JetFile)) { - return; - } - - PsiReference ref = parameters.getPosition().getContainingFile().findReferenceAt(parameters.getOffset()); - - if (ref instanceof JetSimpleNameReference) { - JetSimpleNameReference simpleNameReference = (JetSimpleNameReference)ref; - - String name = simpleNameReference.getExpression().getText(); - if (name == null) { - return; - } - - try { - int prefixLength = parameters.getOffset() - simpleNameReference.getExpression().getTextOffset(); - result = result.withPrefixMatcher(new PlainPrefixMatcher(name.substring(0, prefixLength))); - - ResolveSessionForBodies resolveSession = - ResolvePackage.getLazyResolveSession(simpleNameReference.getExpression()); - BindingContext bindingContext = resolveSession.resolveToElement(simpleNameReference.getExpression()); - - Collection variants = - TipsManager.getPackageReferenceVariants(simpleNameReference.getExpression(), bindingContext); - for (LookupElement variant : DescriptorLookupConverter.collectLookupElements(resolveSession, variants)) { - if (!variant.getLookupString().contains(DUMMY_IDENTIFIER)) { - result.addElement(variant); - } - } - - result.stopHere(); - } - catch (ProcessCanceledException e) { - throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e); - } - } - } - }); - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.kt new file mode 100644 index 00000000000..b2d09909ff3 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetPackagesContributor.kt @@ -0,0 +1,81 @@ +/* + * 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.* +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 + +/** + * Performs completion in package directive. Should suggest only packages and avoid showing fake package produced by + * DUMMY_IDENTIFIER. + */ +public class JetPackagesContributor : CompletionContributor() { + class object { + val DUMMY_IDENTIFIER = "___package___" + + val ACTIVATION_PATTERN: ElementPattern = PlatformPatterns.psiElement().inside(javaClass()) + } + + { + extend(CompletionType.BASIC, ACTIVATION_PATTERN, object : CompletionProvider() { + override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { + val position = parameters.getPosition() + if (position.getContainingFile() !is JetFile) return + + val ref = parameters.getPosition().getContainingFile()!!.findReferenceAt(parameters.getOffset()) + + if (ref is JetSimpleNameReference) { + val name = ref.expression.getText() ?: return + + try { + val prefixLength = parameters.getOffset() - ref.expression.getTextOffset() + var result = result.withPrefixMatcher(PlainPrefixMatcher(name.substring(0, prefixLength))) + + val resolveSession = ref.expression.getLazyResolveSession() + 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) + } + } + + result.stopHere() + } + catch (e: ProcessCanceledException) { + throw CompletionProgressIndicatorUtil.rethrowWithCancelIndicator(e) + } + } + } + }) + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt index f7a199c1e21..175d244e107 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt @@ -62,7 +62,7 @@ public class KotlinNamedParametersContributor : CompletionContributor() { extend(CompletionType.BASIC, PlatformPatterns.psiElement().and(FilterPattern(InNamedParameterFilter)), object : CompletionProvider() { - override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext?, result: CompletionResultSet) { + override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { doParamsCompletion(parameters, result) } }) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.java b/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.java deleted file mode 100644 index d79123b44a1..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.java +++ /dev/null @@ -1,43 +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.psi.PsiElement; -import com.intellij.psi.filters.ClassFilter; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.impl.source.tree.LeafPsiElement; -import com.intellij.psi.tree.IElementType; - -public class LeafElementFilter implements ElementFilter { - private static final ClassFilter LEAF_CLASS_FILTER = new ClassFilter(LeafPsiElement.class); - - private final IElementType myElementType; - - LeafElementFilter(IElementType elementType) { - myElementType = elementType; - } - - @Override - public boolean isAcceptable(Object element, PsiElement context) { - return element instanceof LeafPsiElement && ((LeafPsiElement) element).getElementType() == myElementType; - } - - @Override - public boolean isClassAcceptable(Class hintClass) { - return LEAF_CLASS_FILTER.isClassAcceptable(hintClass); - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.kt b/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.kt new file mode 100644 index 00000000000..ce34e80e9da --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/LeafElementFilter.kt @@ -0,0 +1,36 @@ +/* + * 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.psi.PsiElement +import com.intellij.psi.filters.ClassFilter +import com.intellij.psi.filters.ElementFilter +import com.intellij.psi.impl.source.tree.LeafPsiElement +import com.intellij.psi.tree.IElementType + +public class LeafElementFilter(private val elementType: IElementType) : ElementFilter { + + override fun isAcceptable(element: Any?, context: PsiElement?) + = element is LeafPsiElement && element.getElementType() == elementType + + override fun isClassAcceptable(hintClass: Class<*>) + = LEAF_CLASS_FILTER.isClassAcceptable(hintClass) + + class object { + private val LEAF_CLASS_FILTER = ClassFilter(javaClass()) + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt index 10f7a36ff06..8264ac48e25 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.kt @@ -33,7 +33,7 @@ public object JetClassInsertHandler : InsertHandler { override fun handleInsert(context: InsertionContext, item: LookupElement) { val file = context.getFile() if (file is JetFile) { - val descriptor = (item.getObject() as? org.jetbrains.jet.plugin.completion.DeclarationLookupObject)?.getDescriptor() as? ClassDescriptor + val descriptor = (item.getObject() as? DeclarationLookupObject)?.descriptor as? ClassDescriptor if (descriptor != null) { val startOffset = context.getStartOffset() val document = context.getDocument() diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt index 7384ec51aca..0379167d116 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt @@ -36,6 +36,7 @@ import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper import com.intellij.openapi.editor.Document import org.jetbrains.jet.lang.types.JetType import com.intellij.openapi.util.TextRange +import org.jetbrains.jet.plugin.completion.DeclarationLookupObject public enum class CaretPosition { IN_BRACKETS @@ -155,20 +156,19 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam if (element == null) return@runReadAction val file = context.getFile() - if (file is JetFile && item.getObject() is org.jetbrains.jet.plugin.completion.DeclarationLookupObject) { - val descriptor = (item.getObject() as org.jetbrains.jet.plugin.completion.DeclarationLookupObject).getDescriptor() - - if (descriptor is SimpleFunctionDescriptor) { - val functionDescriptor = descriptor as SimpleFunctionDescriptor + val o = item.getObject() + if (file is JetFile && o is DeclarationLookupObject) { + val descriptor = o.descriptor as? SimpleFunctionDescriptor + if (descriptor != null) { if (PsiTreeUtil.getParentOfType(element, javaClass()) != null && - functionDescriptor.getReceiverParameter() == null) { + descriptor.getReceiverParameter() == null) { return@runReadAction } - if (DescriptorUtils.isTopLevelDeclaration(functionDescriptor)) { + if (DescriptorUtils.isTopLevelDeclaration(descriptor)) { ApplicationManager.getApplication()?.runWriteAction { - val fqn = DescriptorUtils.getFqNameSafe(functionDescriptor) + val fqn = DescriptorUtils.getFqNameSafe(descriptor) ImportInsertHelper.addImportDirectiveIfNeeded(fqn, file) } }