Completion refactoring: got rid of JetExtensionReceiverTypeContributor
This commit is contained in:
@@ -228,14 +228,9 @@
|
||||
order="first"
|
||||
implementationClass="org.jetbrains.jet.plugin.completion.JetPackagesContributor"/>
|
||||
|
||||
<completion.contributor language="jet"
|
||||
id="JetExtensionFunctionReceiverContributor"
|
||||
order="after JetPackagesContributor"
|
||||
implementationClass="org.jetbrains.jet.plugin.completion.JetExtensionReceiverTypeContributor"/>
|
||||
|
||||
<completion.contributor language="jet"
|
||||
id="JetCompletionContributor"
|
||||
order="after JetExtensionFunctionReceiverContributor"
|
||||
order="after JetPackagesContributor"
|
||||
implementationClass="org.jetbrains.jet.plugin.completion.JetCompletionContributor"/>
|
||||
|
||||
<completion.contributor language="jet"
|
||||
|
||||
@@ -31,13 +31,20 @@ import org.jetbrains.jet.plugin.references.JetSimpleNameReference
|
||||
|
||||
import com.intellij.patterns.PsiJavaPatterns.elementType
|
||||
import com.intellij.patterns.PsiJavaPatterns.psiElement
|
||||
import com.intellij.patterns.PsiElementPattern
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
public class JetCompletionContributor : CompletionContributor() {
|
||||
|
||||
{
|
||||
private val AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping(psiElement().withText(""), psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL)))
|
||||
|
||||
private val EXTENSION_RECEIVER_TYPE_DUMMY_IDENTIFIER: String = "KotlinExtensionDummy.fake() {}" // A way to add reference into file at completion place
|
||||
private val EXTENSION_RECEIVER_TYPE_ACTIVATION_PATTERN: PsiElementPattern.Capture<PsiElement> = PlatformPatterns.psiElement().afterLeaf(JetTokens.FUN_KEYWORD.toString(), JetTokens.VAL_KEYWORD.toString(), JetTokens.VAR_KEYWORD.toString())
|
||||
|
||||
;{
|
||||
val provider = object : CompletionProvider<CompletionParameters>() {
|
||||
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
|
||||
doSimpleReferenceCompletion(parameters, result)
|
||||
performCompletion(parameters, result)
|
||||
}
|
||||
}
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), provider)
|
||||
@@ -50,26 +57,21 @@ public class JetCompletionContributor : CompletionContributor() {
|
||||
|
||||
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)
|
||||
}
|
||||
val dummyIdentifier = when {
|
||||
context.getCompletionType() == CompletionType.SMART -> CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + "$" // add '$' to ignore context after the caret
|
||||
|
||||
JetPackagesContributor.ACTIVATION_PATTERN.accepts(tokenBefore) -> JetPackagesContributor.DUMMY_IDENTIFIER
|
||||
|
||||
EXTENSION_RECEIVER_TYPE_ACTIVATION_PATTERN.accepts(tokenBefore) -> EXTENSION_RECEIVER_TYPE_DUMMY_IDENTIFIER
|
||||
|
||||
else -> CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED
|
||||
}
|
||||
context.setDummyIdentifier(dummyIdentifier)
|
||||
|
||||
// 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()
|
||||
@@ -100,54 +102,55 @@ public class JetCompletionContributor : CompletionContributor() {
|
||||
}
|
||||
}
|
||||
|
||||
class object {
|
||||
private val AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping(psiElement().withText(""), psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL)))
|
||||
private fun performCompletion(parameters: CompletionParameters, result: CompletionResultSet) {
|
||||
val position = parameters.getPosition()
|
||||
if (position.getContainingFile() !is JetFile) return
|
||||
|
||||
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()
|
||||
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC) {
|
||||
val somethingAdded = BasicCompletionSession(parameters, result, jetReference).complete()
|
||||
if (!somethingAdded && parameters.getInvocationCount() < 2) {
|
||||
// Rerun completion if nothing was found
|
||||
BasicCompletionSession(parameters.withInvocationCount(2), result, jetReference).complete()
|
||||
}
|
||||
}
|
||||
else {
|
||||
SmartCompletionSession(parameters, result, jetReference).complete()
|
||||
}
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
throw rethrowWithCancelIndicator(e)
|
||||
}
|
||||
}
|
||||
if (AFTER_NUMBER_LITERAL.accepts(parameters.getPosition())) {
|
||||
// First Kotlin completion contributors - stop here will stop all completion
|
||||
result.stopHere()
|
||||
return
|
||||
}
|
||||
|
||||
private fun getJetReference(parameters: CompletionParameters): JetSimpleNameReference?
|
||||
= parameters.getPosition().getParent()?.getReferences()?.filterIsInstance(javaClass<JetSimpleNameReference>())?.firstOrNull()
|
||||
if (EXTENSION_RECEIVER_TYPE_ACTIVATION_PATTERN.accepts(position) && parameters.getInvocationCount() == 0) {
|
||||
result.stopHere()
|
||||
return
|
||||
}
|
||||
|
||||
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++
|
||||
val jetReference = getJetReference(parameters)
|
||||
if (jetReference != null) {
|
||||
try {
|
||||
result.restartCompletionWhenNothingMatches()
|
||||
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC) {
|
||||
val somethingAdded = BasicCompletionSession(parameters, result, jetReference).complete()
|
||||
if (!somethingAdded && parameters.getInvocationCount() < 2) {
|
||||
// Rerun completion if nothing was found
|
||||
BasicCompletionSession(parameters.withInvocationCount(2), result, jetReference).complete()
|
||||
}
|
||||
}
|
||||
else {
|
||||
SmartCompletionSession(parameters, result, jetReference).complete()
|
||||
}
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
throw rethrowWithCancelIndicator(e)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun getJetReference(parameters: CompletionParameters): JetSimpleNameReference?
|
||||
= parameters.getPosition().getParent()?.getReferences()?.filterIsInstance(javaClass<JetSimpleNameReference>())?.firstOrNull()
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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<PsiElement> = PlatformPatterns.psiElement().afterLeaf(JetTokens.FUN_KEYWORD.toString(), JetTokens.VAL_KEYWORD.toString(), JetTokens.VAR_KEYWORD.toString())
|
||||
}
|
||||
|
||||
{
|
||||
extend(CompletionType.BASIC, ACTIVATION_PATTERN, object : CompletionProvider<CompletionParameters>() {
|
||||
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
|
||||
if (parameters.getInvocationCount() > 0) {
|
||||
JetCompletionContributor.doSimpleReferenceCompletion(parameters, result)
|
||||
}
|
||||
|
||||
result.stopHere()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,6 @@ public class JetKeywordCompletionContributor : CompletionContributor() {
|
||||
CommentFilter(),
|
||||
ParentFilter(ClassFilter(javaClass<JetLiteralStringTemplateEntry>())),
|
||||
ParentFilter(ClassFilter(javaClass<JetConstantExpression>())),
|
||||
PatternFilter(JetExtensionReceiverTypeContributor.ACTIVATION_PATTERN),
|
||||
LeftNeighbour(TextFilter("."))
|
||||
))
|
||||
|
||||
|
||||
@@ -36,19 +36,18 @@ public class JetPackagesContributor : CompletionContributor() {
|
||||
class object {
|
||||
val DUMMY_IDENTIFIER = "___package___"
|
||||
|
||||
val ACTIVATION_PATTERN: ElementPattern<out PsiElement> = PlatformPatterns.psiElement().inside(javaClass<JetPackageDirective>())
|
||||
val ACTIVATION_PATTERN = PlatformPatterns.psiElement().inside(javaClass<JetPackageDirective>())
|
||||
}
|
||||
|
||||
{
|
||||
extend(CompletionType.BASIC, ACTIVATION_PATTERN, object : CompletionProvider<CompletionParameters>() {
|
||||
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
|
||||
val file = parameters.getPosition().getContainingFile()
|
||||
if (file !is JetFile) return
|
||||
val file = parameters.getPosition().getContainingFile() as JetFile
|
||||
|
||||
val ref = file.findReferenceAt(parameters.getOffset())
|
||||
|
||||
if (ref is JetSimpleNameReference) {
|
||||
val name = ref.expression.getText() ?: return
|
||||
val name = ref.expression.getText()!!
|
||||
|
||||
try {
|
||||
val prefixLength = parameters.getOffset() - ref.expression.getTextOffset()
|
||||
|
||||
Reference in New Issue
Block a user