Support toRegex() standard function
#KT-8088 Fixed
This commit is contained in:
@@ -5,5 +5,8 @@
|
|||||||
<place><![CDATA[
|
<place><![CDATA[
|
||||||
psiParameter().ofMethod(0, psiMethod().withName("Regex").definedInClass("kotlin.text.Regex"))
|
psiParameter().ofMethod(0, psiMethod().withName("Regex").definedInClass("kotlin.text.Regex"))
|
||||||
]]></place>
|
]]></place>
|
||||||
|
<place><![CDATA[
|
||||||
|
receiver().ofMethod(psiMethod().withName("toRegex").withReceiver("kotlin.String").definedInPackage("kotlin.text"))
|
||||||
|
]]></place>
|
||||||
</injection>
|
</injection>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -18,13 +18,11 @@ package org.jetbrains.kotlin.idea.injection
|
|||||||
|
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.InjectedLanguagePlaces
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.LanguageInjector
|
|
||||||
import com.intellij.psi.PsiLanguageInjectionHost
|
|
||||||
import com.intellij.psi.PsiMethod
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.intellij.plugins.intelliLang.Configuration
|
import org.intellij.plugins.intelliLang.Configuration
|
||||||
import org.intellij.plugins.intelliLang.inject.InjectorUtils
|
import org.intellij.plugins.intelliLang.inject.InjectorUtils
|
||||||
|
import org.intellij.plugins.intelliLang.inject.config.BaseInjection
|
||||||
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport
|
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -41,6 +39,7 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
val injectionInfo =
|
val injectionInfo =
|
||||||
injectWithExplicitCodeInstruction(ktHost)
|
injectWithExplicitCodeInstruction(ktHost)
|
||||||
?: injectWithCall(ktHost)
|
?: injectWithCall(ktHost)
|
||||||
|
?: injectWithReceiver(ktHost)
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
val language = InjectorUtils.getLanguageByString(injectionInfo.languageId) ?: return
|
val language = InjectorUtils.getLanguageByString(injectionInfo.languageId) ?: return
|
||||||
@@ -53,6 +52,28 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
return InjectionInfo(languageId, null, null)
|
return InjectionInfo(languageId, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun injectWithReceiver(host: KtElement): InjectionInfo? {
|
||||||
|
val qualifiedExpression = host.parent as? KtDotQualifiedExpression ?: return null
|
||||||
|
if (qualifiedExpression.receiverExpression != host) return null
|
||||||
|
|
||||||
|
val callExpression = qualifiedExpression.selectorExpression as? KtCallExpression ?: return null
|
||||||
|
val callee = callExpression.calleeExpression ?: return null
|
||||||
|
|
||||||
|
for (reference in callee.references) {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
|
||||||
|
val resolvedTo = reference.resolve()
|
||||||
|
if (resolvedTo is KtFunction) {
|
||||||
|
val injectionInfo = findInjection(resolvedTo.receiverTypeReference, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID))
|
||||||
|
if (injectionInfo != null) {
|
||||||
|
return injectionInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun injectWithCall(host: KtElement): InjectionInfo? {
|
private fun injectWithCall(host: KtElement): InjectionInfo? {
|
||||||
val ktHost: KtElement = host
|
val ktHost: KtElement = host
|
||||||
val argument = ktHost.parent as? KtValueArgument ?: return null
|
val argument = ktHost.parent as? KtValueArgument ?: return null
|
||||||
@@ -85,26 +106,19 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
||||||
val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null
|
val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null
|
||||||
|
|
||||||
val injections = Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)
|
return findInjection(psiParameter, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
|
||||||
|
|
||||||
for (injection in injections) {
|
|
||||||
if (injection.acceptsPsiElement(psiParameter)) {
|
|
||||||
// ?? if (!processXmlInjections(injection, owner, method, paramIndex)) {
|
|
||||||
return InjectionInfo(injection.injectedLanguageId, injection.prefix, injection.suffix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction): InjectionInfo? {
|
private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction): InjectionInfo? {
|
||||||
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
||||||
val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null
|
val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null
|
||||||
|
|
||||||
val injections = Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID)
|
return findInjection(ktParameter, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findInjection(element: PsiElement?, injections: List<BaseInjection>): InjectionInfo? {
|
||||||
for (injection in injections) {
|
for (injection in injections) {
|
||||||
if (injection.acceptsPsiElement(ktParameter)) {
|
if (injection.acceptsPsiElement(element)) {
|
||||||
return InjectionInfo(injection.injectedLanguageId, injection.prefix, injection.suffix)
|
return InjectionInfo(injection.injectedLanguageId, injection.prefix, injection.suffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|||||||
object KotlinPatterns: StandardPatterns() {
|
object KotlinPatterns: StandardPatterns() {
|
||||||
@JvmStatic fun psiParameter() = KtParameterPattern()
|
@JvmStatic fun psiParameter() = KtParameterPattern()
|
||||||
@JvmStatic fun psiMethod() = KotlinFunctionPattern()
|
@JvmStatic fun psiMethod() = KotlinFunctionPattern()
|
||||||
|
@JvmStatic fun receiver() = KotlinReceiverPattern()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods in this class are used through reflection during pattern construction
|
// Methods in this class are used through reflection during pattern construction
|
||||||
@@ -119,3 +120,21 @@ class KtParameterPattern : PsiElementPattern<KtParameter, KtParameterPattern>(Kt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class KotlinReceiverPattern : PsiElementPattern<KtTypeReference, KotlinReceiverPattern>(KtTypeReference::class.java) {
|
||||||
|
fun ofMethod(pattern: ElementPattern<Any>): KotlinReceiverPattern {
|
||||||
|
return with(object : PatternConditionPlus<KtTypeReference, KtFunction>("KtReceiverPattern-ofMethod", pattern) {
|
||||||
|
override fun processValues(typeReference: KtTypeReference, context: ProcessingContext?, processor: PairProcessor<KtFunction, ProcessingContext>): Boolean {
|
||||||
|
return processor.process(typeReference.parent as? KtFunction, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun accepts(typeReference: KtTypeReference, context: ProcessingContext?): Boolean {
|
||||||
|
val ktFunction = typeReference.parent as? KtFunction ?: return false
|
||||||
|
if (ktFunction.receiverTypeReference != typeReference) return false
|
||||||
|
|
||||||
|
return super.accepts(typeReference, context)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,27 @@ class KotlinStdlibInjectionTest : AbstractInjectionTest() {
|
|||||||
RegExpLanguage.INSTANCE.id
|
RegExpLanguage.INSTANCE.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun testToRegex0() = testInjection(
|
||||||
|
"""
|
||||||
|
|val test = "hi<caret>".toRegex()
|
||||||
|
""",
|
||||||
|
RegExpLanguage.INSTANCE.id
|
||||||
|
)
|
||||||
|
|
||||||
|
fun testToRegex1() = testInjection(
|
||||||
|
"""
|
||||||
|
|val test = "hi<caret>".toRegex(RegexOption.CANON_EQ)
|
||||||
|
""",
|
||||||
|
RegExpLanguage.INSTANCE.id
|
||||||
|
)
|
||||||
|
|
||||||
|
fun testToRegex2() = testInjection(
|
||||||
|
"""
|
||||||
|
|val test = "hi<caret>".toRegex(setOf(RegexOption.LITERAL))
|
||||||
|
""",
|
||||||
|
RegExpLanguage.INSTANCE.id
|
||||||
|
)
|
||||||
|
|
||||||
private fun testInjection(text: String, languageId: String) {
|
private fun testInjection(text: String, languageId: String) {
|
||||||
testInjectionPresent(text, languageId, false)
|
testInjectionPresent(text, languageId, false)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user