"kotlinVariable()" macro to filter by expected type, dropped IterableVariableMacro
This commit is contained in:
@@ -139,10 +139,10 @@ class WhenEntryAdditionalData(val whenWithSubject: Boolean) : ExpectedInfo.Addit
|
|||||||
object IfConditionAdditionalData : ExpectedInfo.AdditionalData
|
object IfConditionAdditionalData : ExpectedInfo.AdditionalData
|
||||||
|
|
||||||
class ExpectedInfos(
|
class ExpectedInfos(
|
||||||
val bindingContext: BindingContext,
|
private val bindingContext: BindingContext,
|
||||||
val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
val useHeuristicSignatures: Boolean = true,
|
private val useHeuristicSignatures: Boolean = true,
|
||||||
val useOuterCallsExpectedTypeCount: Int = 0
|
private val useOuterCallsExpectedTypeCount: Int = 0
|
||||||
) {
|
) {
|
||||||
public fun calculate(expressionWithType: KtExpression): Collection<ExpectedInfo> {
|
public fun calculate(expressionWithType: KtExpression): Collection<ExpectedInfo> {
|
||||||
val expectedInfos = calculateForArgument(expressionWithType)
|
val expectedInfos = calculateForArgument(expressionWithType)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<template resource-bundle="org.jetbrains.kotlin.idea.KotlinBundle" key="livetemplate.description.iter"
|
<template resource-bundle="org.jetbrains.kotlin.idea.KotlinBundle" key="livetemplate.description.iter"
|
||||||
name="iter" toReformat="true" toShortenFQNames="true"
|
name="iter" toReformat="true" toShortenFQNames="true"
|
||||||
value="for ($VAR$ in $ITERABLE$) { $END$ }">
|
value="for ($VAR$ in $ITERABLE$) { $END$ }">
|
||||||
<variable alwaysStopAt="true" defaultValue=""iterable"" expression="kotlinIterableVariable()" name="ITERABLE" />
|
<variable alwaysStopAt="true" defaultValue=""iterable"" expression="kotlinVariable()" name="ITERABLE" />
|
||||||
<variable alwaysStopAt="true" defaultValue=""i"" expression="kotlinSuggestVariableName()" name="VAR" />
|
<variable alwaysStopAt="true" defaultValue=""i"" expression="kotlinSuggestVariableName()" name="VAR" />
|
||||||
<context>
|
<context>
|
||||||
<option name="KOTLIN_STATEMENT" value="true" />
|
<option name="KOTLIN_STATEMENT" value="true" />
|
||||||
|
|||||||
@@ -426,9 +426,9 @@
|
|||||||
<liveTemplateContext implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinTemplateContextType$Comment"/>
|
<liveTemplateContext implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinTemplateContextType$Comment"/>
|
||||||
<defaultLiveTemplatesProvider implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinLiveTemplatesProvider"/>
|
<defaultLiveTemplatesProvider implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinLiveTemplatesProvider"/>
|
||||||
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.AnyVariableMacro"/>
|
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.AnyVariableMacro"/>
|
||||||
|
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.SuitableVariableMacro"/>
|
||||||
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.FunctionParametersMacro"/>
|
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.FunctionParametersMacro"/>
|
||||||
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.AnonymousSuperMacro"/>
|
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.AnonymousSuperMacro"/>
|
||||||
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.IterableVariableMacro"/>
|
|
||||||
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.SuggestVariableNameMacro"/>
|
<liveTemplateMacro implementation="org.jetbrains.kotlin.idea.liveTemplates.macro.SuggestVariableNameMacro"/>
|
||||||
<liveTemplateOptionalProcessor implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinShortenFQNamesProcessor"/>
|
<liveTemplateOptionalProcessor implementation="org.jetbrains.kotlin.idea.liveTemplates.KotlinShortenFQNamesProcessor"/>
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import com.intellij.openapi.util.UserDataHolder
|
|||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
|
|
||||||
class AnyVariableMacro : BaseKotlinVariableMacro() {
|
class AnyVariableMacro : BaseKotlinVariableMacro() {
|
||||||
override fun getName() = "kotlinVariable"
|
override fun getName() = "kotlinAnyVariable"
|
||||||
override fun getPresentableName() = "kotlinVariable()"
|
override fun getPresentableName() = "kotlinAnyVariable()"
|
||||||
|
|
||||||
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder) = true
|
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder) = true
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-13
@@ -21,35 +21,46 @@ import com.intellij.openapi.util.Key
|
|||||||
import com.intellij.openapi.util.UserDataHolder
|
import com.intellij.openapi.util.UserDataHolder
|
||||||
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.core.IterableTypesDetection
|
import org.jetbrains.kotlin.idea.core.ExpectedInfo
|
||||||
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
|
import org.jetbrains.kotlin.idea.core.ExpectedInfos
|
||||||
import org.jetbrains.kotlin.idea.core.SmartCastCalculator
|
import org.jetbrains.kotlin.idea.core.SmartCastCalculator
|
||||||
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
|
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
class IterableVariableMacro : BaseKotlinVariableMacro() {
|
class SuitableVariableMacro : BaseKotlinVariableMacro() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val ITERABLE_TYPES_DETECTOR_KEY = Key<IterableTypesDetector>("ITERABLE_TYPES_DETECTOR_KEY")
|
val EXPECTED_INFOS_KEY = Key<Collection<ExpectedInfo>>("EXPECTED_INFOS_KEY")
|
||||||
val SMART_CAST_CALCULATOR_KEY = Key<SmartCastCalculator>("SMART_CAST_CALCULATOR_KEY")
|
val SMART_CAST_CALCULATOR_KEY = Key<SmartCastCalculator>("SMART_CAST_CALCULATOR_KEY")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getName() = "kotlinIterableVariable"
|
override fun getName() = "kotlinVariable"
|
||||||
override fun getPresentableName() = "kotlinIterableVariable()"
|
override fun getPresentableName() = "kotlinVariable()"
|
||||||
|
|
||||||
override fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) {
|
override fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) {
|
||||||
val resolutionFacade = contextElement.getResolutionFacade()
|
val resolutionFacade = contextElement.getResolutionFacade()
|
||||||
val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
if (contextElement is KtNameReferenceExpression) {
|
||||||
val detector = resolutionFacade.getIdeService(IterableTypesDetection::class.java).createDetector(scope)
|
val callTypeAndReceiver = CallTypeAndReceiver.detect(contextElement)
|
||||||
val smartCastCalculator = SmartCastCalculator(bindingContext, scope.ownerDescriptor, contextElement, null, resolutionFacade)
|
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
userData.putUserData(ITERABLE_TYPES_DETECTOR_KEY, detector)
|
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade).calculate(contextElement)
|
||||||
userData.putUserData(SMART_CAST_CALCULATOR_KEY, smartCastCalculator)
|
if (expectedInfos.isNotEmpty()) {
|
||||||
|
userData.putUserData(EXPECTED_INFOS_KEY, expectedInfos)
|
||||||
|
|
||||||
|
val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
|
val smartCastCalculator = SmartCastCalculator(bindingContext, scope.ownerDescriptor, contextElement, null, resolutionFacade)
|
||||||
|
userData.putUserData(SMART_CAST_CALCULATOR_KEY, smartCastCalculator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder): Boolean {
|
override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder): Boolean {
|
||||||
val detector = userData.getUserData(ITERABLE_TYPES_DETECTOR_KEY)!!
|
val expectedInfos = userData.getUserData(EXPECTED_INFOS_KEY) ?: return true
|
||||||
val smartCastCalculator = userData.getUserData(SMART_CAST_CALCULATOR_KEY)!!
|
val smartCastCalculator = userData.getUserData(SMART_CAST_CALCULATOR_KEY)!!
|
||||||
val types = smartCastCalculator.types(variableDescriptor)
|
val types = smartCastCalculator.types(variableDescriptor)
|
||||||
return types.any { detector.isIterable(it, null) }
|
return expectedInfos.any { expectedInfo -> types.any { expectedInfo.filter.matchingSubstitutor(FuzzyType(it, emptyList())) != null } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user