diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicabilityRange.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicabilityRange.kt index 5cb51b9376f..e0d962f0e13 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicabilityRange.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicabilityRange.kt @@ -10,10 +10,23 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.util.textRangeIn import org.jetbrains.kotlin.psi.KtElement +/** + * Provide list of ranges on which [HLApplicator] is available + * + * It should not do some additional checks to verify that [HLApplicator] is applicable + * as it is responsibility of [HLApplicator.isApplicableByPsi] + * + * No resolve operations should be called inside [getApplicabilityRanges] + * I.e no [org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession] or [PsiElement] resolve can be used inside + * + * [getApplicabilityRanges] is guarantied to be called inside read action + */ sealed class HLApplicabilityRange { /** - * Returns the list of ranges on which [HLApplicator] is available + * Return the list of ranges on which [HLApplicator] is available + * * The ranges are relative to [element] + * i.e. if range covers the whole element when it should return `[0, element.length)` */ abstract fun getApplicabilityRanges(element: ELEMENT): List } @@ -25,17 +38,60 @@ private class HLApplicabilityRangeImpl( getApplicabilityRanges.invoke(element) } +/** + * Create [HLApplicabilityRange] by list of possible ranges + * [getRanges] should return `empty list if no applicability ranges found + * [getRanges] should return ranges relative to passed [ELEMENT] + * i.e. if range covers the whole element when it should return `[0, element.length)` + * + * No resolve operations should be called inside [getRanges] + * I.e no [KtAnalyisSession] or [PsiElement] resolve can be used inside + * + * [getRanges] is guarantied to be called inside read action + * + * @see applicabilityRange + * @see applicabilityTarget + */ fun applicabilityRanges( getRanges: (ELEMENT) -> List ): HLApplicabilityRange = HLApplicabilityRangeImpl(getRanges) +/** + * Create [HLApplicabilityRange] with a single applicability range + * [getRange] should return `null` if no applicability ranges found + * + * No resolve operations should be called inside [getRanges] + * I.e no [KtAnalyisSession] or [PsiElement] resolve can be used inside + * + * [getRange] should return range relative to passed [ELEMENT] + * i.e. if range covers the whole element when it should return `[0, element.length)` + * + * [getRange] is guarantied to be called inside read action + * + * @see applicabilityRanges + * @see applicabilityTarget + */ fun applicabilityRange( getRange: (ELEMENT) -> TextRange? ): HLApplicabilityRange = HLApplicabilityRangeImpl { listOfNotNull(getRange(it)) } +/** + * Create [HLApplicabilityRange] with a single applicability range represented by [PsiElement] + * [getTarget] should return [PsiElement] which range will be used or `null` if no applicability ranges found + * + * No resolve operations should be called inside [getTarget] + * I.e no [KtAnalyisSession] or [PsiElement] resolve can be used inside + * + * [getTarget] should return element inside the element passed + * + * [getTarget] is guarantied to be called inside read action + * + * @see applicabilityRanges + * @see applicabilityTarget + */ fun applicabilityTarget( getTarget: (ELEMENT) -> PsiElement? ): HLApplicabilityRange =