diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/AnyVariableMacro.kt b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/AnyVariableMacro.kt index a587f2e09cb..f167fe22202 100644 --- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/AnyVariableMacro.kt +++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/AnyVariableMacro.kt @@ -17,12 +17,12 @@ package org.jetbrains.kotlin.idea.liveTemplates.macro import com.intellij.openapi.project.Project +import com.intellij.openapi.util.UserDataHolder import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.idea.core.IterableTypesDetector class AnyVariableMacro : BaseKotlinVariableMacro() { override fun getName() = "kotlinVariable" override fun getPresentableName() = "kotlinVariable()" - override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, iterableTypesDetector: IterableTypesDetector) = true + override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder) = true } diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/BaseKotlinVariableMacro.kt b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/BaseKotlinVariableMacro.kt index b4b175ca994..53e15ecbff7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/BaseKotlinVariableMacro.kt +++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/BaseKotlinVariableMacro.kt @@ -23,6 +23,7 @@ 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.util.UserDataHolder import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiNamedElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -30,17 +31,16 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper -import org.jetbrains.kotlin.idea.core.IterableTypesDetection -import org.jetbrains.kotlin.idea.core.IterableTypesDetector import org.jetbrains.kotlin.idea.core.isVisible import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.util.slicedMap.UserDataHolderImpl import java.util.* abstract class BaseKotlinVariableMacro : Macro() { @@ -63,13 +63,13 @@ abstract class BaseKotlinVariableMacro : Macro() { return descriptor !is DeclarationDescriptorWithVisibility || descriptor.isVisible(contextElement, null, bindingContext, resolutionFacade) } - val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade) - val detector = resolutionFacade.getIdeService(IterableTypesDetection::class.java).createDetector(scope) + val userData = UserDataHolderImpl() + initUserData(userData, contextElement, bindingContext) val helper = ReferenceVariantsHelper(bindingContext, resolutionFacade, resolutionFacade.moduleDescriptor, ::isVisible) val variants = helper .getReferenceVariants(contextElement, CallTypeAndReceiver.DEFAULT, DescriptorKindFilter.VARIABLES, { true }) - .filter { isSuitable(it as VariableDescriptor, project, detector) } + .filter { isSuitable(it as VariableDescriptor, project, userData) } val declarations = ArrayList() for (descriptor in variants) { @@ -79,10 +79,13 @@ abstract class BaseKotlinVariableMacro : Macro() { return declarations } + protected open fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) { + } + protected abstract fun isSuitable( variableDescriptor: VariableDescriptor, project: Project, - iterableTypesDetector: IterableTypesDetector): Boolean + userData: UserDataHolder): Boolean override fun calculateResult(params: Array, context: ExpressionContext): Result? { val vars = getVariables(params, context) diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/IterableVariableMacro.kt b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/IterableVariableMacro.kt index f9c7d562b89..9fa5c2ea4d6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/IterableVariableMacro.kt +++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/IterableVariableMacro.kt @@ -17,18 +17,34 @@ package org.jetbrains.kotlin.idea.liveTemplates.macro import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.UserDataHolder import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.core.IterableTypesDetection import org.jetbrains.kotlin.idea.core.IterableTypesDetector +import org.jetbrains.kotlin.idea.util.getResolutionScope +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.BindingContext class IterableVariableMacro : BaseKotlinVariableMacro() { + private companion object { + val ITERABLE_TYPES_DETECTOR_KEY = Key("ITERABLE_TYPES_DETECTOR_KEY") + } + override fun getName() = "kotlinIterableVariable" override fun getPresentableName() = "kotlinIterableVariable()" - override fun isSuitable( - variableDescriptor: VariableDescriptor, - project: Project, - iterableTypesDetector: IterableTypesDetector): Boolean { + override fun initUserData(userData: UserDataHolder, contextElement: KtElement, bindingContext: BindingContext) { + val resolutionFacade = contextElement.getResolutionFacade() + val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade) + val detector = resolutionFacade.getIdeService(IterableTypesDetection::class.java).createDetector(scope) + userData.putUserData(ITERABLE_TYPES_DETECTOR_KEY, detector) + } + + override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder): Boolean { + val detector = userData.getUserData(ITERABLE_TYPES_DETECTOR_KEY)!! //TODO: smart-casts - return iterableTypesDetector.isIterable(variableDescriptor.type, null) + return detector.isIterable(variableDescriptor.type, null) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/SuggestVariableNameMacro.kt b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/SuggestVariableNameMacro.kt index 3d6f6f56600..c1f10391851 100644 --- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/SuggestVariableNameMacro.kt +++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/macro/SuggestVariableNameMacro.kt @@ -17,17 +17,14 @@ package org.jetbrains.kotlin.idea.liveTemplates.macro import com.intellij.openapi.project.Project +import com.intellij.openapi.util.UserDataHolder import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.idea.core.IterableTypesDetector class SuggestVariableNameMacro : BaseKotlinVariableMacro() { override fun getName() = "kotlinSuggestVariableName" override fun getPresentableName() = "kotlinSuggestVariableName()" - override fun isSuitable( - variableDescriptor: VariableDescriptor, - project: Project, - iterableTypesDetector: IterableTypesDetector): Boolean { + override fun isSuitable(variableDescriptor: VariableDescriptor, project: Project, userData: UserDataHolder): Boolean { return variableDescriptor.type.isMarkedNullable } }