Analysis API: Add tests for KtCallResolver.resolveCandidates().
This commit is contained in:
committed by
Ilya Kirillov
parent
f62bdf5826
commit
0ed802bca4
+2
-3
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.analysis.api.symbols.*
|
|||||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir.getTowerContextProvider
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
||||||
@@ -640,7 +639,7 @@ internal class KtFirCallResolver(
|
|||||||
override fun resolveCandidates(psi: KtElement): List<KtCallInfo> = withValidityAssertion {
|
override fun resolveCandidates(psi: KtElement): List<KtCallInfo> = withValidityAssertion {
|
||||||
val firCall = when (val fir = psi.getOrBuildFir(firResolveState)) {
|
val firCall = when (val fir = psi.getOrBuildFir(firResolveState)) {
|
||||||
is FirFunctionCall -> fir
|
is FirFunctionCall -> fir
|
||||||
is FirSafeCallExpression -> fir.regularQualifiedAccess.safeAs<FirFunctionCall>()
|
is FirSafeCallExpression -> fir.selector.safeAs<FirFunctionCall>()
|
||||||
// TODO: FirDelegatedConstructorColl, FirAnnotationCall, FirArrayOfCall, FirConstructor
|
// TODO: FirDelegatedConstructorColl, FirAnnotationCall, FirArrayOfCall, FirConstructor
|
||||||
else -> null
|
else -> null
|
||||||
} ?: return@withValidityAssertion emptyList()
|
} ?: return@withValidityAssertion emptyList()
|
||||||
@@ -671,7 +670,7 @@ internal class KtFirCallResolver(
|
|||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
fun getAllCandidates(functionCall: FirFunctionCall, element: KtElement): List<KtCallInfo> {
|
fun getAllCandidates(functionCall: FirFunctionCall, element: KtElement): List<KtCallInfo> {
|
||||||
val towerContext = firResolveState.getTowerContextProvider().getClosestAvailableParentContext(element)
|
val towerContext = firResolveState.getTowerContextProvider(element.containingKtFile).getClosestAvailableParentContext(element)
|
||||||
towerContext?.let { bodyResolveComponents.context.replaceTowerDataContext(it) }
|
towerContext?.let { bodyResolveComponents.context.replaceTowerDataContext(it) }
|
||||||
// Note: All candidate symbols should have the same name
|
// Note: All candidate symbols should have the same name
|
||||||
val name =
|
val name =
|
||||||
|
|||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* 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.components;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService;
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractResolveCandidatesTest;
|
||||||
|
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/callResolver/resolveCandidates")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirResolveCandidatesTestGenerated extends AbstractResolveCandidatesTest {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public FrontendApiTestConfiguratorService getConfigurator() {
|
||||||
|
return FirFrontendApiTestConfiguratorService.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInResolveCandidates() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCandidates"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("noCandidates.kt")
|
||||||
|
public void testNoCandidates() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/noCandidates.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class SingleCandidate {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSingleCandidate() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("functionCall.kt")
|
||||||
|
public void testFunctionCall() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("functionCallWithNotEnoughArgs.kt")
|
||||||
|
public void testFunctionCallWithNotEnoughArgs() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/functionCallWithNotEnoughArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("indexedGet.kt")
|
||||||
|
public void testIndexedGet() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/indexedGet.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("indexedGetWithNotEnoughArgs.kt")
|
||||||
|
public void testIndexedGetWithNotEnoughArgs() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/indexedGetWithNotEnoughArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("indexedSet.kt")
|
||||||
|
public void testIndexedSet() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/indexedSet.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("indexedSetWithNotEnoughArgs.kt")
|
||||||
|
public void testIndexedSetWithNotEnoughArgs() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/indexedSetWithNotEnoughArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("samConstructorCall.kt")
|
||||||
|
public void testSamConstructorCall() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/samConstructorCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("variableAsFunction.kt")
|
||||||
|
public void testVariableAsFunction() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/variableAsFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("variableAsFunctionLikeCall.kt")
|
||||||
|
public void testVariableAsFunctionLikeCall() throws Exception {
|
||||||
|
runTest("analysis/analysis-api/testData/components/callResolver/resolveCandidates/singleCandidate/variableAsFunctionLikeCall.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-93
@@ -8,23 +8,12 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.components
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
|
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
|
||||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
|
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor
|
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer.render
|
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.test.services.assertions
|
import org.jetbrains.kotlin.test.services.assertions
|
||||||
import kotlin.reflect.KProperty1
|
|
||||||
import kotlin.reflect.KVisibility
|
|
||||||
import kotlin.reflect.full.memberProperties
|
|
||||||
|
|
||||||
abstract class AbstractResolveCallTest : AbstractHLApiSingleModuleTest() {
|
abstract class AbstractResolveCallTest : AbstractHLApiSingleModuleTest() {
|
||||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||||
@@ -56,85 +45,3 @@ abstract class AbstractResolveCallTest : AbstractHLApiSingleModuleTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.stringRepresentation(call: KtCallInfo): String {
|
|
||||||
fun Any.stringValue(): String {
|
|
||||||
fun KtType.render() = asStringForDebugging().replace('/', '.')
|
|
||||||
fun String.indented() = replace("\n", "\n ")
|
|
||||||
return when (this) {
|
|
||||||
is KtFunctionLikeSymbol -> buildString {
|
|
||||||
append(
|
|
||||||
when (this@stringValue) {
|
|
||||||
is KtFunctionSymbol -> callableIdIfNonLocal ?: name
|
|
||||||
is KtSamConstructorSymbol -> callableIdIfNonLocal ?: name
|
|
||||||
is KtConstructorSymbol -> "<constructor>"
|
|
||||||
is KtPropertyGetterSymbol -> callableIdIfNonLocal ?: "<getter>"
|
|
||||||
is KtPropertySetterSymbol -> callableIdIfNonLocal ?: "<setter>"
|
|
||||||
else -> error("unexpected symbol kind in KtCall: ${this@stringValue::class.java}")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
append("(")
|
|
||||||
(this@stringValue as? KtFunctionSymbol)?.receiverType?.let { receiver ->
|
|
||||||
append("<extension receiver>: ${receiver.render()}")
|
|
||||||
if (valueParameters.isNotEmpty()) append(", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
(this@stringValue as? KtCallableSymbol)?.getDispatchReceiverType()?.let { dispatchReceiverType ->
|
|
||||||
append("<dispatch receiver>: ${dispatchReceiverType.render()}")
|
|
||||||
if (valueParameters.isNotEmpty()) append(", ")
|
|
||||||
}
|
|
||||||
valueParameters.joinTo(this) { it.stringValue() }
|
|
||||||
append(")")
|
|
||||||
append(": ${returnType.render()}")
|
|
||||||
}
|
|
||||||
is KtValueParameterSymbol -> "${if (isVararg) "vararg " else ""}$name: ${returnType.render()}"
|
|
||||||
is KtTypeParameterSymbol -> this.nameOrAnonymous.asString()
|
|
||||||
is KtVariableSymbol -> "${if (isVal) "val" else "var"} $name: ${returnType.render()}"
|
|
||||||
is KtSymbol -> render(this)
|
|
||||||
is Boolean -> toString()
|
|
||||||
is Map<*, *> -> if (isEmpty()) "{}" else entries.joinToString(
|
|
||||||
separator = ",\n ",
|
|
||||||
prefix = "{\n ",
|
|
||||||
postfix = "\n}"
|
|
||||||
) { (k, v) -> "${k?.stringValue()?.indented()} -> (${v?.stringValue()?.indented()})" }
|
|
||||||
is Collection<*> -> if (isEmpty()) "[]" else joinToString(
|
|
||||||
separator = ",\n ",
|
|
||||||
prefix = "[\n ",
|
|
||||||
postfix = "\n]"
|
|
||||||
) {
|
|
||||||
it?.stringValue()?.indented() ?: "null"
|
|
||||||
}
|
|
||||||
is PsiElement -> this.text
|
|
||||||
is KtSubstitutor.Empty -> "<empty substitutor>"
|
|
||||||
is KtMapBackedSubstitutor -> {
|
|
||||||
val mappingText = getAsMap().entries
|
|
||||||
.joinToString(prefix = "{", postfix = "}") { (k, v) -> k.stringValue() + " = " + v.asStringForDebugging() }
|
|
||||||
"<map substitutor: $mappingText>"
|
|
||||||
}
|
|
||||||
is KtSubstitutor -> "<complex substitutor>"
|
|
||||||
is KtDiagnostic -> "$severity<$factoryName: $defaultMessage>"
|
|
||||||
is KtType -> render()
|
|
||||||
is Enum<*> -> name
|
|
||||||
is Name -> asString()
|
|
||||||
else -> buildString {
|
|
||||||
val clazz = this@stringValue::class
|
|
||||||
append(clazz.simpleName!!)
|
|
||||||
appendLine(":")
|
|
||||||
clazz.memberProperties
|
|
||||||
.filter { it.name != "token" && it.visibility == KVisibility.PUBLIC }
|
|
||||||
.joinTo(this, separator = "\n ", prefix = " ") { property ->
|
|
||||||
val name = property.name
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val value =
|
|
||||||
(property as KProperty1<Any, *>).get(this@stringValue)?.stringValue()?.indented()
|
|
||||||
"$name = $value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return call.stringValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.impl.base.test.components
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.analysis.api.calls.KtCall
|
||||||
|
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
import org.jetbrains.kotlin.test.services.assertions
|
||||||
|
|
||||||
|
abstract class AbstractResolveCandidatesTest : AbstractHLApiSingleModuleTest() {
|
||||||
|
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||||
|
val ktFile = ktFiles.first()
|
||||||
|
val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
|
||||||
|
|
||||||
|
val actual = executeOnPooledThreadInReadAction {
|
||||||
|
analyseForTest(expression) {
|
||||||
|
val candidates = resolveCandidates(expression)
|
||||||
|
if (candidates.isEmpty()) {
|
||||||
|
"NO_CANDIDATES"
|
||||||
|
} else {
|
||||||
|
candidates.joinToString("\n\n") { stringRepresentation(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtAnalysisSession.resolveCandidates(element: PsiElement): List<KtCallInfo> = when (element) {
|
||||||
|
is KtValueArgument -> resolveCandidates(element.getArgumentExpression()!!)
|
||||||
|
is KtDeclarationModifierList -> {
|
||||||
|
val annotationEntry = element.annotationEntries.singleOrNull()
|
||||||
|
?: error("Only single annotation entry is supported for now")
|
||||||
|
annotationEntry.resolveCandidates()
|
||||||
|
}
|
||||||
|
is KtFileAnnotationList -> {
|
||||||
|
val annotationEntry = element.annotationEntries.singleOrNull()
|
||||||
|
?: error("Only single annotation entry is supported for now")
|
||||||
|
annotationEntry.resolveCandidates()
|
||||||
|
}
|
||||||
|
is KtElement -> element.resolveCandidates()
|
||||||
|
else -> error("Selected element type (${element::class.simpleName}) is not supported for resolveCandidates()")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.impl.base.test.components
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
|
||||||
|
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor
|
||||||
|
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||||
|
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||||
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
import kotlin.reflect.KVisibility
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
|
internal fun KtAnalysisSession.stringRepresentation(call: KtCallInfo): String {
|
||||||
|
fun Any.stringValue(): String {
|
||||||
|
fun KtType.render() = asStringForDebugging().replace('/', '.')
|
||||||
|
fun String.indented() = replace("\n", "\n ")
|
||||||
|
return when (this) {
|
||||||
|
is KtFunctionLikeSymbol -> buildString {
|
||||||
|
append(
|
||||||
|
when (this@stringValue) {
|
||||||
|
is KtFunctionSymbol -> callableIdIfNonLocal ?: name
|
||||||
|
is KtSamConstructorSymbol -> callableIdIfNonLocal ?: name
|
||||||
|
is KtConstructorSymbol -> "<constructor>"
|
||||||
|
is KtPropertyGetterSymbol -> callableIdIfNonLocal ?: "<getter>"
|
||||||
|
is KtPropertySetterSymbol -> callableIdIfNonLocal ?: "<setter>"
|
||||||
|
else -> error("unexpected symbol kind in KtCall: ${this@stringValue::class.java}")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
append("(")
|
||||||
|
(this@stringValue as? KtFunctionSymbol)?.receiverType?.let { receiver ->
|
||||||
|
append("<extension receiver>: ${receiver.render()}")
|
||||||
|
if (valueParameters.isNotEmpty()) append(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
(this@stringValue as? KtCallableSymbol)?.getDispatchReceiverType()?.let { dispatchReceiverType ->
|
||||||
|
append("<dispatch receiver>: ${dispatchReceiverType.render()}")
|
||||||
|
if (valueParameters.isNotEmpty()) append(", ")
|
||||||
|
}
|
||||||
|
valueParameters.joinTo(this) { it.stringValue() }
|
||||||
|
append(")")
|
||||||
|
append(": ${returnType.render()}")
|
||||||
|
}
|
||||||
|
is KtValueParameterSymbol -> "${if (isVararg) "vararg " else ""}$name: ${returnType.render()}"
|
||||||
|
is KtTypeParameterSymbol -> this.nameOrAnonymous.asString()
|
||||||
|
is KtVariableSymbol -> "${if (isVal) "val" else "var"} $name: ${returnType.render()}"
|
||||||
|
is KtSymbol -> DebugSymbolRenderer.render(this)
|
||||||
|
is Boolean -> toString()
|
||||||
|
is Map<*, *> -> if (isEmpty()) "{}" else entries.joinToString(
|
||||||
|
separator = ",\n ",
|
||||||
|
prefix = "{\n ",
|
||||||
|
postfix = "\n}"
|
||||||
|
) { (k, v) -> "${k?.stringValue()?.indented()} -> (${v?.stringValue()?.indented()})" }
|
||||||
|
is Collection<*> -> if (isEmpty()) "[]" else joinToString(
|
||||||
|
separator = ",\n ",
|
||||||
|
prefix = "[\n ",
|
||||||
|
postfix = "\n]"
|
||||||
|
) {
|
||||||
|
it?.stringValue()?.indented() ?: "null"
|
||||||
|
}
|
||||||
|
is PsiElement -> this.text
|
||||||
|
is KtSubstitutor.Empty -> "<empty substitutor>"
|
||||||
|
is KtMapBackedSubstitutor -> {
|
||||||
|
val mappingText = getAsMap().entries
|
||||||
|
.joinToString(prefix = "{", postfix = "}") { (k, v) -> k.stringValue() + " = " + v.asStringForDebugging() }
|
||||||
|
"<map substitutor: $mappingText>"
|
||||||
|
}
|
||||||
|
is KtSubstitutor -> "<complex substitutor>"
|
||||||
|
is KtDiagnostic -> "$severity<$factoryName: $defaultMessage>"
|
||||||
|
is KtType -> render()
|
||||||
|
is Enum<*> -> name
|
||||||
|
is Name -> asString()
|
||||||
|
else -> buildString {
|
||||||
|
val clazz = this@stringValue::class
|
||||||
|
append(clazz.simpleName!!)
|
||||||
|
appendLine(":")
|
||||||
|
clazz.memberProperties
|
||||||
|
.filter { it.name != "token" && it.visibility == KVisibility.PUBLIC }
|
||||||
|
.joinTo(this, separator = "\n ", prefix = " ") { property ->
|
||||||
|
val name = property.name
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val value =
|
||||||
|
(property as KProperty1<Any, *>).get(this@stringValue)?.stringValue()?.indented()
|
||||||
|
"$name = $value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return call.stringValue()
|
||||||
|
}
|
||||||
+1
-4
@@ -31,9 +31,6 @@ public interface KtCallResolverMixIn : KtAnalysisSessionMixIn {
|
|||||||
public fun KtArrayAccessExpression.resolveCall(): KtCallInfo =
|
public fun KtArrayAccessExpression.resolveCall(): KtCallInfo =
|
||||||
analysisSession.callResolver.resolveCall(this) ?: error("KtArrayAccessExpression should always resolve to a KtCallInfo")
|
analysisSession.callResolver.resolveCall(this) ?: error("KtArrayAccessExpression should always resolve to a KtCallInfo")
|
||||||
|
|
||||||
public fun KtCallElement.resolveCandidates(): List<KtCallInfo> =
|
public fun KtElement.resolveCandidates(): List<KtCallInfo> =
|
||||||
analysisSession.callResolver.resolveCandidates(this)
|
|
||||||
|
|
||||||
public fun KtArrayAccessExpression.resolveCandidates(): List<KtCallInfo> =
|
|
||||||
analysisSession.callResolver.resolveCandidates(this)
|
analysisSession.callResolver.resolveCandidates(this)
|
||||||
}
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun call() {
|
||||||
|
<expr>function(1)</expr>
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
NO_CANDIDATES
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun function(a: Int) {}
|
||||||
|
|
||||||
|
fun call() {
|
||||||
|
<expr>function(1)</expr>
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Unit
|
||||||
|
symbol = /function(a: kotlin.Int): kotlin.Unit
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun function(a: Int, b: String) {}
|
||||||
|
|
||||||
|
fun call() {
|
||||||
|
<expr>function(1)</expr>
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
KtErrorCallInfo:
|
||||||
|
candidateCalls = [
|
||||||
|
KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Unit
|
||||||
|
symbol = /function(a: kotlin.Int, b: kotlin.String): kotlin.Unit
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'b'>
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
class C {
|
||||||
|
operator fun get(a: Int, b: String): Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun call(c: C) {
|
||||||
|
val res = <expr>c[1, "foo"]</expr>
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = KtExplicitReceiverValue:
|
||||||
|
expression = c
|
||||||
|
isSafeNavigation = false
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = /C.get(<dispatch receiver>: C, a: kotlin.Int, b: kotlin.String): kotlin.Boolean
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int),
|
||||||
|
"foo" -> (KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String)
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
class C {
|
||||||
|
operator fun get(a: Int, b: String): Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun call(c: C) {
|
||||||
|
val res = <expr>c[1]</expr>
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
KtErrorCallInfo:
|
||||||
|
candidateCalls = [
|
||||||
|
KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = KtExplicitReceiverValue:
|
||||||
|
expression = c
|
||||||
|
isSafeNavigation = false
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = /C.get(<dispatch receiver>: C, a: kotlin.Int, b: kotlin.String): kotlin.Boolean
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'b'>
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
class C {
|
||||||
|
operator fun set(a: Int, b: String, value: Boolean) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun call(c: C) {
|
||||||
|
<expr>c[1, "foo"]</expr> = false
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = KtExplicitReceiverValue:
|
||||||
|
expression = c
|
||||||
|
isSafeNavigation = false
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Unit
|
||||||
|
symbol = /C.set(<dispatch receiver>: C, a: kotlin.Int, b: kotlin.String, value: kotlin.Boolean): kotlin.Unit
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = value
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = value: kotlin.Boolean
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int),
|
||||||
|
"foo" -> (KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String),
|
||||||
|
false -> (KtVariableLikeSignature:
|
||||||
|
name = value
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = value: kotlin.Boolean)
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
class C {
|
||||||
|
operator fun set(a: Int, b: String, value: Boolean) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun call(c: C) {
|
||||||
|
<expr>c[1]</expr> = false
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
KtErrorCallInfo:
|
||||||
|
candidateCalls = [
|
||||||
|
KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = KtExplicitReceiverValue:
|
||||||
|
expression = c
|
||||||
|
isSafeNavigation = false
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Unit
|
||||||
|
symbol = /C.set(<dispatch receiver>: C, a: kotlin.Int, b: kotlin.String, value: kotlin.Boolean): kotlin.Unit
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = b
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = b: kotlin.String,
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = value
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = value: kotlin.Boolean
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = a
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = a: kotlin.Int),
|
||||||
|
false -> (KtVariableLikeSignature:
|
||||||
|
name = value
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Boolean
|
||||||
|
symbol = value: kotlin.Boolean)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
diagnostic = ERROR<NO_VALUE_FOR_PARAMETER: No value passed for parameter 'b'>
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
val c = <expr>Comparator {x: Int, y: Int -> 1}</expr>
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = false
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = java.util.Comparator<ft<kotlin.Int, kotlin.Int?>>
|
||||||
|
symbol = java/util/Comparator(function: kotlin.Function2<ft<T, T?>, ft<T, T?>, kotlin.Int>): java.util.Comparator<T>
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = function
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Function2<ft<kotlin.Int, kotlin.Int?>, ft<kotlin.Int, kotlin.Int?>, kotlin.Int>
|
||||||
|
symbol = function: kotlin.Function2<ft<T, T?>, ft<T, T?>, kotlin.Int>
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
{x: Int, y: Int -> 1} -> (KtVariableLikeSignature:
|
||||||
|
name = function
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Function2<ft<kotlin.Int, kotlin.Int?>, ft<kotlin.Int, kotlin.Int?>, kotlin.Int>
|
||||||
|
symbol = function: kotlin.Function2<ft<T, T?>, ft<T, T?>, kotlin.Int>)
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun call(x: (Int) -> String) {
|
||||||
|
<expr>x(1)</expr>
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = true
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = kotlin/Function1.invoke(<dispatch receiver>: kotlin.Function1<P1, R>, p1: P1): R
|
||||||
|
valueParameters = [
|
||||||
|
KtVariableLikeSignature:
|
||||||
|
name = p1
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = p1: P1
|
||||||
|
]
|
||||||
|
argumentMapping = {
|
||||||
|
1 -> (KtVariableLikeSignature:
|
||||||
|
name = p1
|
||||||
|
receiverType = null
|
||||||
|
returnType = kotlin.Int
|
||||||
|
symbol = p1: P1)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
operator fun Int.invoke(): String {}
|
||||||
|
|
||||||
|
fun call(x: kotlin.Int) {
|
||||||
|
<expr>x()</expr>
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
KtSuccessCallInfo:
|
||||||
|
call = KtSimpleFunctionCall:
|
||||||
|
isImplicitInvoke = true
|
||||||
|
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||||
|
dispatchReceiver = null
|
||||||
|
extensionReceiver = null
|
||||||
|
signature = KtFunctionLikeSignature:
|
||||||
|
receiverType = kotlin.Int
|
||||||
|
returnType = kotlin.String
|
||||||
|
symbol = /invoke(<extension receiver>: kotlin.Int): kotlin.String
|
||||||
|
valueParameters = []
|
||||||
|
argumentMapping = {}
|
||||||
+7
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnal
|
|||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnFilesTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnFilesTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnTypesTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.annotations.AbstractAnalysisApiAnnotationsOnTypesTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractResolveCallTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractResolveCallTest
|
||||||
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractResolveCandidatesTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.compileTimeConstantProvider.AbstractCompileTimeConstantEvaluatorTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.compileTimeConstantProvider.AbstractCompileTimeConstantEvaluatorTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.diagnosticProvider.AbstractCollectDiagnosticsTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.diagnosticProvider.AbstractCollectDiagnosticsTest
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionInfoProvider.AbstractReturnTargetSymbolTest
|
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionInfoProvider.AbstractReturnTargetSymbolTest
|
||||||
@@ -134,6 +135,12 @@ private fun TestGroupSuite.generateAnalysisApiComponentsTests() {
|
|||||||
test(AbstractResolveCallTest::class) {
|
test(AbstractResolveCallTest::class) {
|
||||||
model("resolveCall")
|
model("resolveCall")
|
||||||
}
|
}
|
||||||
|
test(
|
||||||
|
AbstractResolveCandidatesTest::class,
|
||||||
|
generateFe10 = false // TODO: Not yet implemented
|
||||||
|
) {
|
||||||
|
model("resolveCandidates")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component("compileTimeConstantProvider") {
|
component("compileTimeConstantProvider") {
|
||||||
|
|||||||
Reference in New Issue
Block a user