Use lookup elements from completion for variables in live templates
This commit is contained in:
@@ -18,5 +18,6 @@
|
|||||||
<orderEntry type="module" module-name="idea" scope="RUNTIME" />
|
<orderEntry type="module" module-name="idea" scope="RUNTIME" />
|
||||||
<orderEntry type="library" scope="RUNTIME" name="junit-plugin" level="project" />
|
<orderEntry type="library" scope="RUNTIME" name="junit-plugin" level="project" />
|
||||||
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
|
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
|
||||||
|
<orderEntry type="module" module-name="idea-completion" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
+12
-20
@@ -17,34 +17,31 @@
|
|||||||
package org.jetbrains.kotlin.idea.liveTemplates.macro
|
package org.jetbrains.kotlin.idea.liveTemplates.macro
|
||||||
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.template.*
|
||||||
import com.intellij.codeInsight.template.Expression
|
|
||||||
import com.intellij.codeInsight.template.ExpressionContext
|
|
||||||
import com.intellij.codeInsight.template.Macro
|
|
||||||
import com.intellij.codeInsight.template.Result
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.UserDataHolder
|
import com.intellij.openapi.util.UserDataHolder
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiNamedElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||||
|
import org.jetbrains.kotlin.idea.completion.BasicLookupElementFactory
|
||||||
|
import org.jetbrains.kotlin.idea.completion.InsertHandlerProvider
|
||||||
import org.jetbrains.kotlin.idea.core.isVisible
|
import org.jetbrains.kotlin.idea.core.isVisible
|
||||||
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.util.slicedMap.UserDataHolderImpl
|
import org.jetbrains.kotlin.util.slicedMap.UserDataHolderImpl
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
abstract class BaseKotlinVariableMacro : Macro() {
|
abstract class BaseKotlinVariableMacro : Macro() {
|
||||||
private fun getVariables(params: Array<Expression>, context: ExpressionContext): Collection<PsiNamedElement> {
|
private fun getVariables(params: Array<Expression>, context: ExpressionContext): Collection<VariableDescriptor> {
|
||||||
if (params.size != 0) return emptyList()
|
if (params.size != 0) return emptyList()
|
||||||
|
|
||||||
val project = context.project
|
val project = context.project
|
||||||
@@ -67,16 +64,10 @@ abstract class BaseKotlinVariableMacro : Macro() {
|
|||||||
initUserData(userData, contextElement, bindingContext)
|
initUserData(userData, contextElement, bindingContext)
|
||||||
|
|
||||||
val helper = ReferenceVariantsHelper(bindingContext, resolutionFacade, resolutionFacade.moduleDescriptor, ::isVisible)
|
val helper = ReferenceVariantsHelper(bindingContext, resolutionFacade, resolutionFacade.moduleDescriptor, ::isVisible)
|
||||||
val variants = helper
|
return helper
|
||||||
.getReferenceVariants(contextElement, CallTypeAndReceiver.DEFAULT, DescriptorKindFilter.VARIABLES, { true })
|
.getReferenceVariants(contextElement, CallTypeAndReceiver.DEFAULT, DescriptorKindFilter.VARIABLES, { true })
|
||||||
.filter { isSuitable(it as VariableDescriptor, project, userData) }
|
.map { it as VariableDescriptor }
|
||||||
|
.filter { isSuitable(it, project, userData) }
|
||||||
val declarations = ArrayList<PsiNamedElement>()
|
|
||||||
for (descriptor in variants) {
|
|
||||||
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? PsiNamedElement ?: continue
|
|
||||||
declarations.add(declaration)
|
|
||||||
}
|
|
||||||
return declarations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) {
|
protected open fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) {
|
||||||
@@ -90,12 +81,13 @@ abstract class BaseKotlinVariableMacro : Macro() {
|
|||||||
override fun calculateResult(params: Array<Expression>, context: ExpressionContext): Result? {
|
override fun calculateResult(params: Array<Expression>, context: ExpressionContext): Result? {
|
||||||
val vars = getVariables(params, context)
|
val vars = getVariables(params, context)
|
||||||
if (vars.isEmpty()) return null
|
if (vars.isEmpty()) return null
|
||||||
return KotlinPsiElementResult(vars.first())
|
return vars.firstOrNull()?.let { TextResult(it.name.render()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun calculateLookupItems(params: Array<Expression>, context: ExpressionContext): Array<LookupElement>? {
|
override fun calculateLookupItems(params: Array<Expression>, context: ExpressionContext): Array<LookupElement>? {
|
||||||
val vars = getVariables(params, context)
|
val vars = getVariables(params, context)
|
||||||
if (vars.size < 2) return null
|
if (vars.size < 2) return null
|
||||||
return vars.map { LookupElementBuilder.create(it) }.toTypedArray()
|
val lookupElementFactory = BasicLookupElementFactory(context.project, InsertHandlerProvider(CallType.DEFAULT, { emptyList() }))
|
||||||
|
return vars.map { lookupElementFactory.createLookupElement(it) }.toTypedArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ class LiveTemplatesTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
fun testSoutv() {
|
fun testSoutv() {
|
||||||
start()
|
start()
|
||||||
|
|
||||||
assertStringItems("args", "x", "y")
|
assertStringItems("ASSERTIONS_ENABLED", "args", "defaultBlockSize", "defaultBufferSize", "minimumBlockSize", "x", "y")
|
||||||
typeAndNextTab("y")
|
typeAndNextTab("y")
|
||||||
|
|
||||||
checkAfter()
|
checkAfter()
|
||||||
|
|||||||
Reference in New Issue
Block a user