[ANALYSIS API] introduce dedicated KtCall for incomplete code
KTIJ-23505 and duplicates
This commit is contained in:
+24
@@ -244,6 +244,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/checkNotNullCallAsCallee.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companionObjectReference.kt")
|
||||
public void testCompanionObjectReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/companionObjectReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("comparisonCall.kt")
|
||||
public void testComparisonCall() throws Exception {
|
||||
@@ -899,6 +905,24 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/getterAssignment.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeNoParenthesis.kt")
|
||||
public void testIncompleteCodeNoParenthesis() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeNoParenthesis.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeWithAmbiguity.kt")
|
||||
public void testIncompleteCodeWithAmbiguity() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeWithAmbiguity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCodeJavaDeclaration.kt")
|
||||
public void testIncorrectCodeJavaDeclaration() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterAsValue.kt")
|
||||
public void testTypeParameterAsValue() throws Exception {
|
||||
|
||||
+26
-6
@@ -150,6 +150,15 @@ internal class KtFirCallResolver(
|
||||
|
||||
createGenericTypeQualifierCallIfApplicable(this, psi)?.let { return it }
|
||||
|
||||
if (this is FirResolvedQualifier && psi is KtCallExpression) {
|
||||
val constructors = findQualifierConstructors()
|
||||
val calls = toKtCalls(constructors)
|
||||
return when (calls.size) {
|
||||
0 -> KtErrorCallInfo(listOf(KtQualifierCall(token, psi)), inapplicableCandidateDiagnostic(), token)
|
||||
else -> KtErrorCallInfo(calls, inapplicableCandidateDiagnostic(), token)
|
||||
}
|
||||
}
|
||||
|
||||
if (resolveCalleeExpressionOfFunctionCall && this is FirImplicitInvokeCall) {
|
||||
// For implicit invoke, we resolve the calleeExpression of the CallExpression to the call that creates the receiver of this
|
||||
// implicit invoke call. For example,
|
||||
@@ -231,6 +240,8 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun inapplicableCandidateDiagnostic() = KtNonBoundToPsiErrorDiagnostic(null, "Inapplicable candidate", token)
|
||||
|
||||
/**
|
||||
* Resolves call expressions like `Foo<Bar>` or `test.Foo<Bar>` in calls like `Foo<Bar>::foo`, `test.Foo<Bar>::foo` and class literals like `Foo<Bar>`::class.java.
|
||||
*
|
||||
@@ -877,22 +888,31 @@ internal class KtFirCallResolver(
|
||||
}
|
||||
|
||||
private fun FirResolvedQualifier.toKtCallCandidateInfos(): List<KtCallCandidateInfo> {
|
||||
return toKtCalls(findQualifierConstructors()).map {
|
||||
KtInapplicableCallCandidateInfo(
|
||||
it,
|
||||
isInBestCandidates = false,
|
||||
_diagnostic = inapplicableCandidateDiagnostic()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirResolvedQualifier.findQualifierConstructors(): List<KtConstructorSymbol> {
|
||||
val classSymbol = this.symbol?.fullyExpandedClass(analysisSession.useSiteSession) ?: return emptyList()
|
||||
val constructors = classSymbol.unsubstitutedScope(
|
||||
return classSymbol.unsubstitutedScope(
|
||||
analysisSession.useSiteSession,
|
||||
analysisSession.getScopeSessionFor(analysisSession.useSiteSession),
|
||||
withForcedTypeCalculator = true
|
||||
)
|
||||
.getConstructors(analysisSession.firSymbolBuilder)
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun FirResolvedQualifier.toKtCalls(constructors: List<KtConstructorSymbol>): List<KtCall> {
|
||||
analysisSession.apply {
|
||||
return constructors.map { constructor ->
|
||||
val partiallyAppliedSymbol = KtPartiallyAppliedFunctionSymbol(constructor.asSignature(), null, null)
|
||||
KtInapplicableCallCandidateInfo(
|
||||
KtSimpleFunctionCall(partiallyAppliedSymbol, LinkedHashMap(), toTypeArgumentsMapping(partiallyAppliedSymbol), false),
|
||||
isInBestCandidates = false,
|
||||
_diagnostic = KtNonBoundToPsiErrorDiagnostic(null, "Inapplicable candidate", token)
|
||||
)
|
||||
KtSimpleFunctionCall(partiallyAppliedSymbol, LinkedHashMap(), toTypeArgumentsMapping(partiallyAppliedSymbol), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -244,6 +244,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/checkNotNullCallAsCallee.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companionObjectReference.kt")
|
||||
public void testCompanionObjectReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/companionObjectReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("comparisonCall.kt")
|
||||
public void testComparisonCall() throws Exception {
|
||||
@@ -899,6 +905,24 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/getterAssignment.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeNoParenthesis.kt")
|
||||
public void testIncompleteCodeNoParenthesis() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeNoParenthesis.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeWithAmbiguity.kt")
|
||||
public void testIncompleteCodeWithAmbiguity() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeWithAmbiguity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCodeJavaDeclaration.kt")
|
||||
public void testIncorrectCodeJavaDeclaration() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterAsValue.kt")
|
||||
public void testTypeParameterAsValue() throws Exception {
|
||||
|
||||
+24
@@ -244,6 +244,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/checkNotNullCallAsCallee.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companionObjectReference.kt")
|
||||
public void testCompanionObjectReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/companionObjectReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("comparisonCall.kt")
|
||||
public void testComparisonCall() throws Exception {
|
||||
@@ -899,6 +905,24 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/getterAssignment.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeNoParenthesis.kt")
|
||||
public void testIncompleteCodeNoParenthesis() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeNoParenthesis.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incompleteCodeWithAmbiguity.kt")
|
||||
public void testIncompleteCodeWithAmbiguity() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incompleteCodeWithAmbiguity.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCodeJavaDeclaration.kt")
|
||||
public void testIncorrectCodeJavaDeclaration() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterAsValue.kt")
|
||||
public void testTypeParameterAsValue() throws Exception {
|
||||
|
||||
@@ -145,6 +145,25 @@ public class KtGenericTypeQualifier(
|
||||
public val qualifier: KtExpression get() = withValidityAssertion { _qualifier }
|
||||
}
|
||||
|
||||
/**
|
||||
* A special call for type qualifiers with generic parameters which represent [KtCallExpression] in incomplete code.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* fun test() {
|
||||
* List<String>
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public class KtQualifierCall(
|
||||
override val token: KtLifetimeToken,
|
||||
private val _qualifier: KtCallExpression,
|
||||
) : KtCall() {
|
||||
|
||||
public val qualifier: KtCallExpression get() = withValidityAssertion { _qualifier }
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable symbol partially applied with receivers and type arguments. Essentially, this is a call that misses some information. For
|
||||
* properties, the missing information is the type of access (read, write, or compound access) to this property. For functions, the missing
|
||||
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
open class Server() {
|
||||
companion object {
|
||||
val NAME = "Server"
|
||||
}
|
||||
}
|
||||
|
||||
class Client: Server() {
|
||||
val name = <expr>Server</expr>.NAME
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
null
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
KtSuccessCallInfo:
|
||||
call = KtSimpleFunctionCall:
|
||||
isImplicitInvoke = false
|
||||
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||
dispatchReceiver = null
|
||||
extensionReceiver = null
|
||||
signature = KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = ALE<kotlin.String>
|
||||
symbol = <constructor>(): ALE<T>
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = null
|
||||
typeArgumentsMapping = {}
|
||||
argumentMapping = {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class ALE<T> {}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val ale = <expr>ALE<String></expr>
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
KtErrorCallInfo:
|
||||
candidateCalls = [
|
||||
KtSimpleFunctionCall:
|
||||
isImplicitInvoke = false
|
||||
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||
dispatchReceiver = null
|
||||
extensionReceiver = null
|
||||
signature = KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = ALE<T>
|
||||
symbol = <constructor>(): ALE<T>
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = null
|
||||
typeArgumentsMapping = {
|
||||
T -> (kotlin.String)
|
||||
}
|
||||
argumentMapping = {}
|
||||
]
|
||||
diagnostic = ERROR<null: Inapplicable candidate>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
KtSuccessCallInfo:
|
||||
call = KtGenericTypeQualifier:
|
||||
qualifier = Foo<String>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class Foo<T>(len : Int) {
|
||||
constructor(s : String) : this(s.length) {}
|
||||
}
|
||||
|
||||
fun f() {
|
||||
<expr>Foo<String></expr>
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
KtErrorCallInfo:
|
||||
candidateCalls = [
|
||||
KtSimpleFunctionCall:
|
||||
isImplicitInvoke = false
|
||||
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||
dispatchReceiver = null
|
||||
extensionReceiver = null
|
||||
signature = KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = Foo<T>
|
||||
symbol = <constructor>(len: kotlin.Int): Foo<T>
|
||||
valueParameters = [
|
||||
KtVariableLikeSignature:
|
||||
name = len
|
||||
receiverType = null
|
||||
returnType = kotlin.Int
|
||||
symbol = len: kotlin.Int
|
||||
callableIdIfNonLocal = null
|
||||
]
|
||||
callableIdIfNonLocal = null
|
||||
typeArgumentsMapping = {
|
||||
T -> (kotlin.String)
|
||||
}
|
||||
argumentMapping = {},
|
||||
KtSimpleFunctionCall:
|
||||
isImplicitInvoke = false
|
||||
partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
|
||||
dispatchReceiver = null
|
||||
extensionReceiver = null
|
||||
signature = KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = Foo<T>
|
||||
symbol = <constructor>(s: kotlin.String): Foo<T>
|
||||
valueParameters = [
|
||||
KtVariableLikeSignature:
|
||||
name = s
|
||||
receiverType = null
|
||||
returnType = kotlin.String
|
||||
symbol = s: kotlin.String
|
||||
callableIdIfNonLocal = null
|
||||
]
|
||||
callableIdIfNonLocal = null
|
||||
typeArgumentsMapping = {
|
||||
T -> (kotlin.String)
|
||||
}
|
||||
argumentMapping = {}
|
||||
]
|
||||
diagnostic = ERROR<null: Inapplicable candidate>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
KtSuccessCallInfo:
|
||||
call = KtGenericTypeQualifier:
|
||||
qualifier = List<String>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun main(args: Array<Any>) {
|
||||
<expr>List<String></expr> s = new ArrayList<String>()
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
KtErrorCallInfo:
|
||||
candidateCalls = [
|
||||
KtQualifierCall:
|
||||
qualifier = List<String>
|
||||
]
|
||||
diagnostic = ERROR<null: Inapplicable candidate>
|
||||
Reference in New Issue
Block a user