Skip to content

Commit d4e089a

Browse files
nicolas-guichardantonsviridov-src
authored andcommitted
Bug 1971083 - Add support for type operators.
This adds support for emitting type references in type operators: - `is Type` - `!is Type` - `as Type` - `as? Type`
1 parent aa2ba2c commit d4e089a

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

semanticdb-kotlinc/src/main/kotlin/com/sourcegraph/semanticdb_kotlinc/AnalyzerCheckers.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.sourcegraph.semanticdb_kotlinc
22

33
import java.nio.file.Path
44
import kotlin.contracts.ExperimentalContracts
5+
import kotlin.math.exp
56
import org.jetbrains.kotlin.*
67
import org.jetbrains.kotlin.com.intellij.lang.LighterASTNode
78
import org.jetbrains.kotlin.com.intellij.util.diff.FlyweightCapableTreeStructure
@@ -11,18 +12,26 @@ import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
1112
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
1213
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
1314
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
15+
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
16+
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirClassReferenceExpressionChecker
1417
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
18+
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirTypeOperatorCallChecker
1519
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
1620
import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol
1721
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
1822
import org.jetbrains.kotlin.fir.declarations.*
23+
import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
1924
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
25+
import org.jetbrains.kotlin.fir.expressions.FirStatement
26+
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
2027
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
2128
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
2229
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
2330
import org.jetbrains.kotlin.fir.resolve.toClassLikeSymbol
2431
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
2532
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
33+
import org.jetbrains.kotlin.fir.types.coneType
34+
import org.jetbrains.kotlin.fir.types.resolvedType
2635
import org.jetbrains.kotlin.lexer.KtTokens
2736
import org.jetbrains.kotlin.name.ClassId
2837
import org.jetbrains.kotlin.name.FqName
@@ -47,6 +56,9 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
4756
override val qualifiedAccessExpressionCheckers:
4857
Set<FirQualifiedAccessExpressionChecker> =
4958
setOf(SemanticQualifiedAccessExpressionChecker())
59+
60+
override val typeOperatorCallCheckers:
61+
Set<SemanticClassReferenceExpressionChecker> = setOf(SemanticClassReferenceExpressionChecker())
5062
}
5163

5264
open class AnalyzerDeclarationCheckers(sourceroot: Path) : DeclarationCheckers() {
@@ -409,4 +421,22 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
409421
}
410422
}
411423
}
424+
425+
private class SemanticClassReferenceExpressionChecker :
426+
FirTypeOperatorCallChecker(MppCheckerKind.Common) {
427+
@OptIn(ExperimentalContracts::class)
428+
override fun check(
429+
expression: FirTypeOperatorCall,
430+
context: CheckerContext,
431+
reporter: DiagnosticReporter
432+
) {
433+
val typeRef = expression.conversionTypeRef
434+
val source = typeRef.source ?: return
435+
val classSymbol = expression.conversionTypeRef.toClassLikeSymbol(context.session) ?: return
436+
val ktFile = context.containingFile?.sourceFile ?: return
437+
val visitor = visitors[ktFile]
438+
439+
visitor?.visitClassReference(classSymbol, getIdentifier(expression.conversionTypeRef.source ?: source), context)
440+
}
441+
}
412442
}

semanticdb-kotlinc/src/test/kotlin/com/sourcegraph/semanticdb_kotlinc/test/AnalyzerTest.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,50 @@ class AnalyzerTest {
688688
}
689689
}
690690

691+
@Test
692+
fun `type operators`(@TempDir path: Path) {
693+
val document =
694+
compileSemanticdb(
695+
path,
696+
"""
697+
package sample
698+
699+
fun foo(x: Any) {
700+
when (x) {
701+
is Int -> true
702+
else -> x as Float
703+
}
704+
}
705+
""")
706+
707+
val occurrences =
708+
arrayOf(
709+
SymbolOccurrence {
710+
role = Role.REFERENCE
711+
symbol = "kotlin/Int#"
712+
range {
713+
startLine = 4
714+
startCharacter = 11
715+
endLine = 4
716+
endCharacter = 14
717+
}
718+
},
719+
SymbolOccurrence {
720+
role = Role.REFERENCE
721+
symbol = "kotlin/Float#"
722+
range {
723+
startLine = 5
724+
startCharacter = 21
725+
endLine = 5
726+
endCharacter = 26
727+
}
728+
},
729+
)
730+
assertSoftly(document.occurrencesList) {
731+
withClue(this) { occurrences.forEach(::shouldContain) }
732+
}
733+
}
734+
691735
@Test
692736
fun `exception test`(@TempDir path: Path) {
693737
val buildPath = File(path.resolve("build").toString()).apply { mkdir() }

0 commit comments

Comments
 (0)