diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/signatureSubstitution/Fe10IdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/signatureSubstitution/Fe10IdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java new file mode 100644 index 00000000000..b8066be80d9 --- /dev/null +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/signatureSubstitution/Fe10IdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java @@ -0,0 +1,60 @@ +/* + * 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.fe10.test.cases.generated.cases.components.signatureSubstitution; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.fe10.test.configurator.AnalysisApiFe10TestConfiguratorFactory; +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.components.signatureSubstitution.AbstractAnalysisApiSignatureContractsTest; +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/components/signatureSubstitution/signatureContracts") +@TestDataPath("$PROJECT_ROOT") +public class Fe10IdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated extends AbstractAnalysisApiSignatureContractsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFe10TestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fe10, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInSignatureContracts() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("members.kt") + public void testMembers() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt"); + } + + @Test + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt"); + } +} diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/signatureSubstitution/FirIdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/signatureSubstitution/FirIdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java new file mode 100644 index 00000000000..8bbc8ee278c --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/signatureSubstitution/FirIdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java @@ -0,0 +1,60 @@ +/* + * 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.components.signatureSubstitution; + +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.components.signatureSubstitution.AbstractAnalysisApiSignatureContractsTest; +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/components/signatureSubstitution/signatureContracts") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated extends AbstractAnalysisApiSignatureContractsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInSignatureContracts() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("members.kt") + public void testMembers() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt"); + } + + @Test + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt"); + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt new file mode 100644 index 00000000000..d9740c7953d --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt @@ -0,0 +1,134 @@ +/* + * 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.components.signatureSubstitution + +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.components.buildClassType +import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.* +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions +import kotlin.math.pow + +abstract class AbstractAnalysisApiSignatureContractsTest : AbstractAnalysisApiSingleFileTest() { + override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) { + ktFile.collectDescendantsOfType().forEach { + testContractsOnDeclaration(it, testServices) + } + } + + private fun testContractsOnDeclaration( + callableDeclaration: KtCallableDeclaration, + testServices: TestServices + ) { + analyseForTest(callableDeclaration) { + val typesToCheckOn = buildList { + add(builtinTypes.INT) + add(buildClassType(StandardClassIds.List) { argument(builtinTypes.LONG) }) + } + + val symbol = callableDeclaration.getSymbolOfType() + val typeParameters = buildList { + addAll(symbol.typeParameters) + (symbol.getContainingSymbol() as? KtClassOrObjectSymbol)?.let { addAll(it.typeParameters) } + } + val combinations = buildList { combinations(typesToCheckOn, persistentListOf(), typeParameters.size) } + check(combinations.size == typesToCheckOn.size.toDouble().pow(typeParameters.size).toInt()) + val allSubstitutors = buildList { + combinations.forEach { typesPermutation -> + add(buildSubstitutor { substitutions(typeParameters.zip(typesPermutation).toMap()) }) + } + } + + allSubstitutors.forEach { substitutor -> + testContractsOnDeclarationSymbol(symbol, substitutor, testServices) + } + } + } + + private fun KtAnalysisSession.testContractsOnDeclarationSymbol( + symbol: KtCallableSymbol, + substitutor: KtSubstitutor, + testServices: TestServices + ) { + run { + val substitutedViaSignature = symbol.asSignature().substitute(substitutor) + val directlySubstituted = symbol.substitute(substitutor) + testServices.assertions.assertEquals(directlySubstituted, substitutedViaSignature) + testServices.assertions.assertEquals(symbol, directlySubstituted.symbol) + testServices.assertions.assertEquals(symbol, substitutedViaSignature.symbol) + } + when (symbol) { + is KtFunctionLikeSymbol -> { + val substitutedViaSignature: KtFunctionLikeSignature = symbol.asSignature().substitute(substitutor) + val directlySubstituted: KtFunctionLikeSignature = symbol.substitute(substitutor) + + testServices.assertions.assertEquals(directlySubstituted, substitutedViaSignature) + testServices.assertions.assertEquals(symbol, directlySubstituted.symbol) + testServices.assertions.assertEquals(symbol, substitutedViaSignature.symbol) + + checkSubstitutionResult(symbol, directlySubstituted, substitutor, testServices) + } + is KtVariableLikeSymbol -> { + val substitutedViaSignature: KtVariableLikeSignature = symbol.asSignature().substitute(substitutor) + val directlySubstituted: KtVariableLikeSignature = symbol.substitute(substitutor) + + testServices.assertions.assertEquals(directlySubstituted, substitutedViaSignature) + testServices.assertions.assertEquals(symbol, directlySubstituted.symbol) + testServices.assertions.assertEquals(symbol, substitutedViaSignature.symbol) + + checkSubstitutionResult(symbol, directlySubstituted, substitutor, testServices) + } + } + } + + private fun KtAnalysisSession.checkSubstitutionResult( + symbol: KtFunctionLikeSymbol, + signature: KtFunctionLikeSignature<*>, + substitutor: KtSubstitutor, + testServices: TestServices + ) { + testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substituteOrSelf), signature.receiverType) + testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substituteOrSelf), signature.returnType) + + testServices.assertions.assertEquals(symbol.valueParameters.size, signature.valueParameters.size) + + for ((unsubstituted, substituted) in symbol.valueParameters.zip(signature.valueParameters)) { + testServices.assertions.assertEquals(substituted.returnType, unsubstituted.returnType.let(substitutor::substituteOrSelf)) + } + } + + private fun KtAnalysisSession.checkSubstitutionResult( + symbol: KtVariableLikeSymbol, + signature: KtVariableLikeSignature<*>, + substitutor: KtSubstitutor, + testServices: TestServices + ) { + testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substituteOrSelf), signature.receiverType) + testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substituteOrSelf), signature.returnType) + } + + private fun MutableList>.combinations(list: List, state: PersistentList, size: Int) { + if (size == 0) { + add(state) + } else { + for (e in list) { + combinations(list, state.add(e), size - 1) + } + } + } +} \ No newline at end of file diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/signatureSubstitution/FirStandaloneNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/signatureSubstitution/FirStandaloneNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java new file mode 100644 index 00000000000..55d1a8c4baa --- /dev/null +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/signatureSubstitution/FirStandaloneNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated.java @@ -0,0 +1,60 @@ +/* + * 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.components.signatureSubstitution; + +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.components.signatureSubstitution.AbstractAnalysisApiSignatureContractsTest; +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/components/signatureSubstitution/signatureContracts") +@TestDataPath("$PROJECT_ROOT") +public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiSignatureContractsTestGenerated extends AbstractAnalysisApiSignatureContractsTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirStandaloneModeTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Standalone + ) + ); + } + + @Test + public void testAllFilesPresentInSignatureContracts() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("members.kt") + public void testMembers() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt"); + } + + @Test + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + runTest("analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt"); + } +} diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubsitutor.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubsitutor.kt index f7356e6c3b2..466fac51cf6 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubsitutor.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubsitutor.kt @@ -79,7 +79,7 @@ public interface KtSignatureSubsitutorMixIn : KtAnalysisSessionMixIn { * * @see KtSubstitutor.substituteOrSelf */ - public fun S.substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature = + public fun S.substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature = withValidityAssertion { analysisSession.substitutionProvider.substitute(this, substitutor) } /** diff --git a/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt b/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt new file mode 100644 index 00000000000..5e0e406cc5a --- /dev/null +++ b/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/members.kt @@ -0,0 +1,16 @@ +class X { + fun foo(): T {} + + fun A.foo1(t: T) {} + + fun foo2(a: A) {} + + fun T.foo3(a: A): Map> {} + + fun , C : A> foo4(a: A, T): B {} + + val A.bar1: T get() = 10 + + val A.bar2: Map get() = mapOf() + +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt b/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt new file mode 100644 index 00000000000..617419b95ee --- /dev/null +++ b/analysis/analysis-api/testData/components/signatureSubstitution/signatureContracts/topLevel.kt @@ -0,0 +1,13 @@ +fun foo(): A {} + +fun A.foo1() {} + +fun foo2(a: A) {} + +fun foo3(a: A): Map> {} + +fun , C : A> foo4(a: A): B {} + +val A.bar1: Int get() = 10 + +val A.bar2: List get() = listOf(this) \ No newline at end of file diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt index 59e1da8914f..02aa054788d 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.express import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.importOptimizer.AbstractAnalysisApiImportOptimizerTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.psiTypeProvider.AbstractAnalysisApiExpressionPsiTypeProviderTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.psiTypeProvider.AbstractAnalysisApiPsiTypeProviderTest +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.signatureSubstitution.AbstractAnalysisApiSignatureContractsTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.signatureSubstitution.AbstractAnalysisApiSignatureSubstitutionTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.signatureSubstitution.AbstractAnalysisApiSymbolAsSignatureTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.signatureSubstitution.AbstractAnalysisApiSymbolSubstitutionTest @@ -267,6 +268,10 @@ private fun AnalysisApiTestGroup.generateAnalysisApiComponentsTests() { test(AbstractAnalysisApiSignatureSubstitutionTest::class) { model("signatureSubstitution") } + + test(AbstractAnalysisApiSignatureContractsTest::class) { + model("signatureContracts") + } } }