[Analysis API] add tests for KtSubstitutor
This commit is contained in:
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.api.fir.test.cases.generated.cases.types;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.types.AbstractAnalysisApiSubstitutorsTest;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/substitutors/typeSubstitution")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirIdeDependentAnalysisSourceModuleAnalysisApiSubstitutorsTestGenerated extends AbstractAnalysisApiSubstitutorsTest {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AnalysisApiTestConfigurator getConfigurator() {
|
||||||
|
return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator(
|
||||||
|
new AnalysisApiTestConfiguratorFactoryData(
|
||||||
|
FrontendKind.Fir,
|
||||||
|
TestModuleKind.Source,
|
||||||
|
AnalysisSessionMode.Dependent,
|
||||||
|
AnalysisApiMode.Ide
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInTypeSubstitution() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/substitutors/typeSubstitution"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("directSubstitution.kt")
|
||||||
|
public void testDirectSubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/directSubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("emptySubstitution.kt")
|
||||||
|
public void testEmptySubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/emptySubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notApplicableSubstitutor.kt")
|
||||||
|
public void testNotApplicableSubstitutor() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/notApplicableSubstitutor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutionWithTypeParams.kt")
|
||||||
|
public void testSubstitutionWithTypeParams() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/substitutionWithTypeParams.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.api.fir.test.cases.generated.cases.types;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.types.AbstractAnalysisApiSubstitutorsTest;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/substitutors/typeSubstitution")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirIdeNormalAnalysisSourceModuleAnalysisApiSubstitutorsTestGenerated extends AbstractAnalysisApiSubstitutorsTest {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AnalysisApiTestConfigurator getConfigurator() {
|
||||||
|
return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator(
|
||||||
|
new AnalysisApiTestConfiguratorFactoryData(
|
||||||
|
FrontendKind.Fir,
|
||||||
|
TestModuleKind.Source,
|
||||||
|
AnalysisSessionMode.Normal,
|
||||||
|
AnalysisApiMode.Ide
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInTypeSubstitution() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/substitutors/typeSubstitution"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("directSubstitution.kt")
|
||||||
|
public void testDirectSubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/directSubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("emptySubstitution.kt")
|
||||||
|
public void testEmptySubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/emptySubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notApplicableSubstitutor.kt")
|
||||||
|
public void testNotApplicableSubstitutor() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/notApplicableSubstitutor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutionWithTypeParams.kt")
|
||||||
|
public void testSubstitutionWithTypeParams() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/substitutionWithTypeParams.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSing
|
|||||||
import org.jetbrains.kotlin.analysis.test.framework.services.SubstitutionParser
|
import org.jetbrains.kotlin.analysis.test.framework.services.SubstitutionParser
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
@@ -20,11 +21,11 @@ import org.jetbrains.kotlin.test.services.assertions
|
|||||||
|
|
||||||
abstract class AbstractAnalysisApiSignatureSubstitutionTest : AbstractAnalysisApiSingleFileTest() {
|
abstract class AbstractAnalysisApiSignatureSubstitutionTest : AbstractAnalysisApiSingleFileTest() {
|
||||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtDeclaration>(ktFile)
|
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtCallableDeclaration>(ktFile)
|
||||||
val actual = analyseForTest(declaration) {
|
val actual = analyseForTest(declaration) {
|
||||||
val symbol = declaration.getSymbolOfType<KtCallableSymbol>()
|
val symbol = declaration.getSymbolOfType<KtCallableSymbol>()
|
||||||
|
|
||||||
val substitutor = with(SubstitutionParser) { parseSubstitutors(module, ktFile) }.single()
|
val substitutor = SubstitutionParser.parseSubstitutor(ktFile, declaration)
|
||||||
|
|
||||||
val signatureBeforeSubstitution = symbol.asSignature()
|
val signatureBeforeSubstitution = symbol.asSignature()
|
||||||
val signatureAfterSubstitution = signatureBeforeSubstitution.substitute(substitutor)
|
val signatureAfterSubstitution = signatureBeforeSubstitution.substitute(substitutor)
|
||||||
|
|||||||
+3
-2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSing
|
|||||||
import org.jetbrains.kotlin.analysis.test.framework.services.SubstitutionParser
|
import org.jetbrains.kotlin.analysis.test.framework.services.SubstitutionParser
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
@@ -20,11 +21,11 @@ import org.jetbrains.kotlin.test.services.assertions
|
|||||||
|
|
||||||
abstract class AbstractAnalysisApiSymbolSubstitutionTest : AbstractAnalysisApiSingleFileTest() {
|
abstract class AbstractAnalysisApiSymbolSubstitutionTest : AbstractAnalysisApiSingleFileTest() {
|
||||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtDeclaration>(ktFile)
|
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtCallableDeclaration>(ktFile)
|
||||||
val actual = analyseForTest(declaration) {
|
val actual = analyseForTest(declaration) {
|
||||||
val symbol = declaration.getSymbolOfType<KtCallableSymbol>()
|
val symbol = declaration.getSymbolOfType<KtCallableSymbol>()
|
||||||
|
|
||||||
val substitutor = with(SubstitutionParser) { parseSubstitutors(module, ktFile) }.single()
|
val substitutor = SubstitutionParser.parseSubstitutor(ktFile, declaration)
|
||||||
|
|
||||||
val signature = symbol.substitute(substitutor)
|
val signature = symbol.substitute(substitutor)
|
||||||
prettyPrint {
|
prettyPrint {
|
||||||
|
|||||||
+2
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components
|
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.calls.KtCall
|
import org.jetbrains.kotlin.analysis.api.calls.KtCall
|
||||||
import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall
|
import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall
|
||||||
@@ -20,6 +21,7 @@ import kotlin.reflect.KProperty1
|
|||||||
import kotlin.reflect.KVisibility
|
import kotlin.reflect.KVisibility
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
|
@OptIn(KtAnalysisApiInternals::class)
|
||||||
internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any) {
|
internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any) {
|
||||||
fun KtType.render() = asStringForDebugging().replace('/', '.')
|
fun KtType.render() = asStringForDebugging().replace('/', '.')
|
||||||
fun String.indented() = replace("\n", "\n ")
|
fun String.indented() = replace("\n", "\n ")
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.getSymbolOfType
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.services.SubstitutionParser
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
import org.jetbrains.kotlin.test.services.assertions
|
||||||
|
|
||||||
|
abstract class AbstractAnalysisApiSubstitutorsTest : AbstractAnalysisApiSingleFileTest() {
|
||||||
|
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||||
|
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtCallableDeclaration>(ktFile)
|
||||||
|
val actual = analyseForTest(declaration) {
|
||||||
|
val substitutor = SubstitutionParser.parseSubstitutor(ktFile, declaration)
|
||||||
|
val symbol = declaration.getSymbolOfType<KtCallableSymbol>()
|
||||||
|
val type = symbol.returnType
|
||||||
|
val substituted = substitutor.substitute(type)
|
||||||
|
val substitutedOrNull = substitutor.substituteOrNull(type)
|
||||||
|
|
||||||
|
prettyPrint {
|
||||||
|
appendLine("PSI type: ${declaration.typeReference?.text}")
|
||||||
|
appendLine("KtType: ${type.render()}")
|
||||||
|
appendLine("substitutor.substitute: ${substituted.render()}")
|
||||||
|
appendLine("substitutor.substituteOrNull: ${substitutedOrNull?.render()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.api.standalone.fir.test.cases.generated.cases.types;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.standalone.fir.test.AnalysisApiFirStandaloneModeTestConfiguratorFactory;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.types.AbstractAnalysisApiSubstitutorsTest;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/substitutors/typeSubstitution")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiSubstitutorsTestGenerated extends AbstractAnalysisApiSubstitutorsTest {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AnalysisApiTestConfigurator getConfigurator() {
|
||||||
|
return AnalysisApiFirStandaloneModeTestConfiguratorFactory.INSTANCE.createConfigurator(
|
||||||
|
new AnalysisApiTestConfiguratorFactoryData(
|
||||||
|
FrontendKind.Fir,
|
||||||
|
TestModuleKind.Source,
|
||||||
|
AnalysisSessionMode.Normal,
|
||||||
|
AnalysisApiMode.Standalone
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInTypeSubstitution() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/substitutors/typeSubstitution"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("directSubstitution.kt")
|
||||||
|
public void testDirectSubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/directSubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("emptySubstitution.kt")
|
||||||
|
public void testEmptySubstitution() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/emptySubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("notApplicableSubstitutor.kt")
|
||||||
|
public void testNotApplicableSubstitutor() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/notApplicableSubstitutor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutionWithTypeParams.kt")
|
||||||
|
public void testSubstitutionWithTypeParams() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/substitutors/typeSubstitution/substitutionWithTypeParams.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
// SUBSTITUTOR: T->kotlin.collections.List<S>;S->kotlin.Long
|
// SUBSTITUTOR: T -> kotlin.collections.List<S>, S -> kotlin.Long
|
||||||
|
|
||||||
fun <T, S> f<caret>oo(x: List<T>, y: Map<T, List<S>>, k: String): T
|
fun <T, S> f<caret>oo(x: List<T>, y: Map<T, List<S>>, k: String): T
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
// SUBSTITUTOR: T->kotlin.collections.List<S>;S->kotlin.Long
|
// SUBSTITUTOR: T-> kotlin.collections.List<S>, S -> kotlin.Long
|
||||||
|
|
||||||
val <T, S> Map<T, S>.val<caret>ue: List<S>
|
val <T, S> Map<T, S>.val<caret>ue: List<S>
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
// SUBSTITUTOR: T->kotlin.collections.List<S>;S->kotlin.Long
|
// SUBSTITUTOR: T -> kotlin.collections.List<S>, S -> kotlin.Long
|
||||||
|
|
||||||
fun <T, S> f<caret>oo(x: List<T>, y: Map<T, List<S>>, k: String): T
|
fun <T, S> f<caret>oo(x: List<T>, y: Map<T, List<S>>, k: String): T
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
// SUBSTITUTOR: T->kotlin.collections.List<S>;S->kotlin.Long
|
// SUBSTITUTOR: T -> kotlin.collections.List<S>, S -> kotlin.Long
|
||||||
|
|
||||||
val <T, S> Map<T, S>.val<caret>ue: List<S>
|
val <T, S> Map<T, S>.val<caret>ue: List<S>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// SUBSTITUTOR: A -> kotlin.Int, B -> kotlin.String
|
||||||
|
|
||||||
|
fun <A, B> fo<caret>o(): Map<List<A>, B>
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
PSI type: Map<List<A>, B>
|
||||||
|
KtType: kotlin.collections.Map<kotlin.collections.List<A>, B>
|
||||||
|
substitutor.substitute: kotlin.collections.Map<kotlin.collections.List<kotlin.Int>, kotlin.String>
|
||||||
|
substitutor.substituteOrNull: kotlin.collections.Map<kotlin.collections.List<kotlin.Int>, kotlin.String>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// SUBSTITUTOR: A -> kotlin.Int
|
||||||
|
|
||||||
|
fun <A> fo<caret>o(): List<String>
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
PSI type: List<String>
|
||||||
|
KtType: kotlin.collections.List<kotlin.String>
|
||||||
|
substitutor.substitute: kotlin.collections.List<kotlin.String>
|
||||||
|
substitutor.substituteOrNull: null
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// SUBSTITUTOR:
|
||||||
|
|
||||||
|
fun <A> fo<caret>o(): List<String>
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
PSI type: List<String>
|
||||||
|
KtType: kotlin.collections.List<kotlin.String>
|
||||||
|
substitutor.substitute: kotlin.collections.List<kotlin.String>
|
||||||
|
substitutor.substituteOrNull: null
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// SUBSTITUTOR: A -> B, B -> kotlin.Int
|
||||||
|
|
||||||
|
fun <A, B> fo<caret>o(): Map<List<A>, B>
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
PSI type: Map<List<A>, B>
|
||||||
|
KtType: kotlin.collections.Map<kotlin.collections.List<A>, B>
|
||||||
|
substitutor.substitute: kotlin.collections.Map<kotlin.collections.List<B>, kotlin.Int>
|
||||||
|
substitutor.substituteOrNull: kotlin.collections.Map<kotlin.collections.List<B>, kotlin.Int>
|
||||||
@@ -33,3 +33,7 @@ projectTest(jUnitMode = JUnitMode.JUnit5) {
|
|||||||
|
|
||||||
testsJar()
|
testsJar()
|
||||||
|
|
||||||
|
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions.freeCompilerArgs += "-Xcontext-receivers"
|
||||||
|
}
|
||||||
-1
@@ -104,7 +104,6 @@ abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() {
|
|||||||
|
|
||||||
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
|
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
|
||||||
useDirectives(JvmEnvironmentConfigurationDirectives)
|
useDirectives(JvmEnvironmentConfigurationDirectives)
|
||||||
useDirectives(SubstitutionParser.Directives)
|
|
||||||
|
|
||||||
useSourcePreprocessor(::ExpressionMarkersSourceFilePreprocessor)
|
useSourcePreprocessor(::ExpressionMarkersSourceFilePreprocessor)
|
||||||
useAdditionalService { ExpressionMarkerProvider() }
|
useAdditionalService { ExpressionMarkerProvider() }
|
||||||
|
|||||||
+35
-18
@@ -5,45 +5,62 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.test.framework.services
|
package org.jetbrains.kotlin.analysis.test.framework.services
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor
|
import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||||
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
|
||||||
|
|
||||||
object SubstitutionParser {
|
object SubstitutionParser {
|
||||||
fun KtAnalysisSession.parseSubstitutors(module: TestModule, file: KtFile): List<KtSubstitutor> {
|
context(KtAnalysisSession)
|
||||||
val directives = module.directives[Directives.SUBSTITUTOR]
|
fun parseSubstitutor(declaration: KtCallableDeclaration): KtSubstitutor {
|
||||||
if (directives.isEmpty()) return emptyList()
|
val comment = declaration.firstChild as PsiComment
|
||||||
val allTypeParameterSymbols = file
|
return parseSubstitutor(comment, declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
context(KtAnalysisSession)
|
||||||
|
fun parseSubstitutor(ktFile: KtFile, declaration: KtCallableDeclaration): KtSubstitutor {
|
||||||
|
val comment = ktFile.children.filterIsInstance<PsiComment>().single { it.text.startsWith(SUBSTITUTOR_PREFIX) }
|
||||||
|
return parseSubstitutor(comment, declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
context(KtAnalysisSession)
|
||||||
|
fun parseSubstitutor(comment: PsiComment, scopeForTypeParameters: KtElement): KtSubstitutor {
|
||||||
|
val directivesAsString = comment.text.trim()
|
||||||
|
check(directivesAsString.startsWith(SUBSTITUTOR_PREFIX))
|
||||||
|
val substitutorAsMap = parseSubstitutions(directivesAsString.removePrefix(SUBSTITUTOR_PREFIX))
|
||||||
|
|
||||||
|
val allTypeParameterSymbols = scopeForTypeParameters
|
||||||
.collectDescendantsOfType<KtTypeParameter>()
|
.collectDescendantsOfType<KtTypeParameter>()
|
||||||
.map { it.getTypeParameterSymbol() }
|
.map { it.getTypeParameterSymbol() }
|
||||||
.groupBy { it.name.asString() }
|
.groupBy { it.name.asString() }
|
||||||
.mapValues { it.value.single() }
|
.mapValues { it.value.single() }
|
||||||
|
|
||||||
return directives.map { subsitutor ->
|
return buildSubstitutor {
|
||||||
buildSubstitutor {
|
substitutorAsMap.forEach { (typeParameterName, typeString) ->
|
||||||
subsitutor.forEach { (typeParameterName, typeString) ->
|
val typeParameterSymbol = allTypeParameterSymbols.getValue(typeParameterName)
|
||||||
val typeParameterSymbol = allTypeParameterSymbols.getValue(typeParameterName)
|
val type = TypeParser.parseTypeFromString(typeString, scopeForTypeParameters, allTypeParameterSymbols)
|
||||||
val type = with(TypeParser) { parseTypeFromString(typeString, file, allTypeParameterSymbols) }
|
substitution(typeParameterSymbol, type)
|
||||||
substitution(typeParameterSymbol, type)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Directives : SimpleDirectivesContainer() {
|
private fun parseSubstitutions(substitutionsAsString: String): List<Pair<String, String>> =
|
||||||
val SUBSTITUTOR by valueDirective("") { stringValue ->
|
substitutionsAsString.trim().split(",")
|
||||||
stringValue.trim().split(";").map { it.trim() }.map { substitution ->
|
.map { it.trim() }
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
|
.map { substitution ->
|
||||||
val asList = substitution.split("->").map { it.trim() }
|
val asList = substitution.split("->").map { it.trim() }
|
||||||
check(asList.size == 2) {
|
check(asList.size == 2) {
|
||||||
"Substitution should look like `x -> y` but was `$substitution`"
|
"Substitution should look like `x -> y` but was `$substitution`"
|
||||||
}
|
}
|
||||||
asList[0] to asList[1]
|
asList[0] to asList[1]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
const val SUBSTITUTOR_PREFIX = "// SUBSTITUTOR:"
|
||||||
}
|
}
|
||||||
+6
-4
@@ -15,16 +15,18 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
object TypeParser {
|
object TypeParser {
|
||||||
fun KtAnalysisSession.parseTypeFromString(
|
context (KtAnalysisSession)
|
||||||
|
fun parseTypeFromString(
|
||||||
stringType: String,
|
stringType: String,
|
||||||
ktFile: KtFile,
|
contextElement: KtElement,
|
||||||
typeParameterByName: Map<String, KtTypeParameterSymbol>
|
typeParameterByName: Map<String, KtTypeParameterSymbol>
|
||||||
): KtType {
|
): KtType {
|
||||||
val type = KtPsiFactory(ktFile).createType(stringType)
|
val type = KtPsiFactory(contextElement).createType(stringType)
|
||||||
return convertType(type.typeElement ?: incorrectType(type), typeParameterByName)
|
return convertType(type.typeElement ?: incorrectType(type), typeParameterByName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.convertType(type: KtTypeElement, typeParameterByName: Map<String, KtTypeParameterSymbol>): KtType =
|
context (KtAnalysisSession)
|
||||||
|
private fun convertType(type: KtTypeElement, typeParameterByName: Map<String, KtTypeParameterSymbol>): KtType =
|
||||||
when (type) {
|
when (type) {
|
||||||
is KtUserType -> {
|
is KtUserType -> {
|
||||||
val qualifier = fullQualifier(type)
|
val qualifier = fullQualifier(type)
|
||||||
|
|||||||
+7
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.scopes.AbstractSub
|
|||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByFqNameTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByFqNameTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByPsiTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByPsiTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByReferenceTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.AbstractSymbolByReferenceTest
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.types.AbstractAnalysisApiSubstitutorsTest
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
|
||||||
@@ -133,6 +134,12 @@ private fun AnalysisApiTestGroup.generateAnalysisApiNonComponentsTests() {
|
|||||||
model("annotationsOnFiles")
|
model("annotationsOnFiles")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group("substitutors", filter = frontendIs(FrontendKind.Fir)) {
|
||||||
|
test(AbstractAnalysisApiSubstitutorsTest::class) {
|
||||||
|
model("typeSubstitution")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user