Skip to content

Commit b30520a

Browse files
committed
Convert ClassUsageRecorder & checker objects to classes
1 parent 493d67f commit b30520a

File tree

12 files changed

+111
-123
lines changed

12 files changed

+111
-123
lines changed

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenComponentRegistrar.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ class JdepsGenComponentRegistrar : CompilerPluginRegistrar() {
3434

3535
private fun ExtensionStorage.registerForK2(configuration: CompilerConfiguration) {
3636
val projectRoot = Paths.get("").toAbsolutePath().toString() + "/"
37-
ClassUsageRecorder.init(projectRoot)
38-
JdepsGenExtension2(configuration).run {
39-
FirExtensionRegistrarAdapter.registerExtension(JdepsFirExtensions())
37+
val classUsageRecorder = ClassUsageRecorder(rootPath = projectRoot)
38+
JdepsGenExtension2(classUsageRecorder, configuration).run {
39+
FirExtensionRegistrarAdapter.registerExtension(JdepsFirExtensions(classUsageRecorder))
4040
ClassFileFactoryFinalizerExtension.registerExtension(this)
4141
}
4242
}

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/k2/ClassUsageRecorder.kt

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,14 @@ import java.util.SortedSet
1717
private const val JAR_FILE_SEPARATOR = "!/"
1818
private const val ANONYMOUS = "<anonymous>"
1919

20-
internal object ClassUsageRecorder {
21-
private val explicitClassesCanonicalPaths = mutableSetOf<String>()
22-
private val implicitClassesCanonicalPaths = mutableSetOf<String>()
23-
24-
private val results by lazy { sortedMapOf<String, SortedSet<String>>() }
25-
private val seen = mutableSetOf<ClassId>()
20+
class ClassUsageRecorder(
21+
internal val explicitClassesCanonicalPaths: MutableSet<String> = mutableSetOf(),
22+
internal val implicitClassesCanonicalPaths: MutableSet<String> = mutableSetOf(),
23+
private val seen: MutableSet<ClassId> = mutableSetOf(),
24+
private val results: MutableMap<String, SortedSet<String>> = sortedMapOf(),
25+
private val rootPath: String = Paths.get("").toAbsolutePath().toString() + "/",
26+
) {
2627
private val javaHome: String by lazy { System.getenv()["JAVA_HOME"] ?: "<not set>" }
27-
private var rootPath: String = Paths.get("").toAbsolutePath().toString() + "/"
28-
29-
fun init(rootPath: String) {
30-
this.rootPath = rootPath
31-
results.clear()
32-
explicitClassesCanonicalPaths.clear()
33-
implicitClassesCanonicalPaths.clear()
34-
seen.clear()
35-
}
36-
37-
fun getExplicitClassesCanonicalPaths(): Set<String> = explicitClassesCanonicalPaths
38-
39-
fun getImplicitClassesCanonicalPaths(): Set<String> = implicitClassesCanonicalPaths
4028

4129
internal fun recordTypeRef(
4230
typeRef: FirTypeRef,
@@ -61,20 +49,22 @@ internal object ClassUsageRecorder {
6149
if (ANONYMOUS in classId.toString()) return@forEachType
6250
context.session.symbolProvider
6351
.getClassLikeSymbolByClassId(classId)
64-
?.recordClass(context, isExplicit, collectTypeArguments, visited)
52+
?.let { recordClass(it, context, isExplicit, collectTypeArguments, visited) }
6553
}
6654
} else {
6755
coneKotlinType.classId?.let { classId ->
68-
context.session.symbolProvider.getClassLikeSymbolByClassId(classId)
69-
?.recordClass(context, isExplicit, collectTypeArguments, visited)
56+
if (!classId.isLocal) {
57+
context.session.symbolProvider.getClassLikeSymbolByClassId(classId)
58+
?.let { recordClass(it, context, isExplicit, collectTypeArguments, visited) }
59+
}
7060
}
7161
}
7262
}
7363

7464
internal fun recordClass(
7565
firClass: FirClassLikeSymbol<*>,
7666
context: CheckerContext,
77-
isExplicit: Boolean,
67+
isExplicit: Boolean = true,
7868
collectTypeArguments: Boolean = true,
7969
visited: MutableSet<Pair<ClassId, Boolean>> = mutableSetOf(),
8070
) {

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/k2/JdepsFirExtensions.kt

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,40 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirResolvedQualifie
2020
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
2121
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
2222

23-
internal class JdepsFirExtensions : FirExtensionRegistrar() {
23+
internal class JdepsFirExtensions(
24+
private val classUsageRecorder: ClassUsageRecorder,
25+
) : FirExtensionRegistrar() {
2426
override fun ExtensionRegistrarContext.configurePlugin() {
2527
+::JdepsFirCheckersExtension
2628
}
27-
}
2829

29-
internal class JdepsFirCheckersExtension(session: FirSession) :
30-
FirAdditionalCheckersExtension(session) {
31-
override val declarationCheckers: DeclarationCheckers =
32-
object : DeclarationCheckers() {
33-
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> =
34-
setOf(BasicDeclarationChecker)
30+
internal inner class JdepsFirCheckersExtension(session: FirSession) :
31+
FirAdditionalCheckersExtension(session) {
32+
override val declarationCheckers: DeclarationCheckers =
33+
object : DeclarationCheckers() {
34+
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> =
35+
setOf(BasicDeclarationChecker(classUsageRecorder))
3536

36-
override val fileCheckers: Set<FirFileChecker> = setOf(FileChecker)
37+
override val fileCheckers: Set<FirFileChecker> =
38+
setOf(FileChecker(classUsageRecorder))
3739

38-
override val classLikeCheckers: Set<FirClassLikeChecker> = setOf(ClassLikeChecker)
40+
override val classLikeCheckers: Set<FirClassLikeChecker> =
41+
setOf(ClassLikeChecker(classUsageRecorder))
3942

40-
override val functionCheckers: Set<FirFunctionChecker> = setOf(FunctionChecker)
43+
override val functionCheckers: Set<FirFunctionChecker> =
44+
setOf(FunctionChecker(classUsageRecorder))
4145

42-
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker> =
43-
setOf(CallableChecker)
44-
}
46+
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker> =
47+
setOf(CallableChecker(classUsageRecorder))
48+
}
4549

46-
override val expressionCheckers: ExpressionCheckers =
47-
object : ExpressionCheckers() {
48-
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> =
49-
setOf(QualifiedAccessChecker)
50+
override val expressionCheckers: ExpressionCheckers =
51+
object : ExpressionCheckers() {
52+
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> =
53+
setOf(QualifiedAccessChecker(classUsageRecorder))
5054

51-
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker> =
52-
setOf(ResolvedQualifierChecker)
53-
}
55+
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker> =
56+
setOf(ResolvedQualifierChecker(classUsageRecorder))
57+
}
58+
}
5459
}

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/k2/JdepsGenExtension2.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtensio
66
import org.jetbrains.kotlin.config.CompilerConfiguration
77

88
internal class JdepsGenExtension2(
9+
private val classUsageRecorder: ClassUsageRecorder,
910
configuration: CompilerConfiguration,
1011
) : BaseJdepsGenExtension(configuration), ClassFileFactoryFinalizerExtension {
1112
override fun finalizeClassFactory(factory: ClassFileFactory) {
1213
onAnalysisCompleted(
13-
ClassUsageRecorder.getExplicitClassesCanonicalPaths(),
14-
ClassUsageRecorder.getImplicitClassesCanonicalPaths(),
14+
classUsageRecorder.explicitClassesCanonicalPaths,
15+
classUsageRecorder.implicitClassesCanonicalPaths,
1516
)
1617
}
1718
}
Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package io.bazel.kotlin.plugin.jdeps.k2
22

33
import org.jetbrains.kotlin.descriptors.SourceElement
4-
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
54
import org.jetbrains.kotlin.fir.java.JavaBinarySourceElement
6-
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
7-
import org.jetbrains.kotlin.fir.types.ConeKotlinType
8-
import org.jetbrains.kotlin.fir.types.FirTypeRef
95
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
106
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
117
import org.jetbrains.kotlin.name.ClassId
@@ -46,35 +42,3 @@ internal fun DeserializedContainerSource.binaryClass(): String? {
4642
else -> null
4743
}
4844
}
49-
50-
// Extension functions to clean up checker logic
51-
52-
internal fun FirClassLikeSymbol<*>.recordClass(
53-
context: CheckerContext,
54-
isExplicit: Boolean = true,
55-
collectTypeArguments: Boolean = true,
56-
visited: MutableSet<Pair<ClassId, Boolean>> = mutableSetOf(),
57-
) {
58-
ClassUsageRecorder.recordClass(this, context, isExplicit, collectTypeArguments, visited)
59-
}
60-
61-
internal fun FirTypeRef.recordTypeRef(
62-
context: CheckerContext,
63-
isExplicit: Boolean = true,
64-
collectTypeArguments: Boolean = true,
65-
visited: MutableSet<Pair<ClassId, Boolean>> = mutableSetOf(),
66-
) {
67-
ClassUsageRecorder.recordTypeRef(this, context, isExplicit, collectTypeArguments, visited)
68-
}
69-
70-
internal fun ConeKotlinType.recordConeType(
71-
context: CheckerContext,
72-
isExplicit: Boolean = true,
73-
collectTypeArguments: Boolean = true,
74-
) {
75-
ClassUsageRecorder.recordConeType(this, context, isExplicit, collectTypeArguments)
76-
}
77-
78-
internal fun String.recordClassBinaryPath(isExplicit: Boolean = true) {
79-
ClassUsageRecorder.recordClass(this, isExplicit)
80-
}
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
package io.bazel.kotlin.plugin.jdeps.k2.checker.declaration
22

3-
import io.bazel.kotlin.plugin.jdeps.k2.recordClass
3+
import io.bazel.kotlin.plugin.jdeps.k2.ClassUsageRecorder
44
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
55
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
66
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
77
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
88
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
99
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
1010

11-
internal object BasicDeclarationChecker : FirBasicDeclarationChecker(MppCheckerKind.Common) {
11+
internal class BasicDeclarationChecker(
12+
private val classUsageRecorder: ClassUsageRecorder,
13+
) : FirBasicDeclarationChecker(MppCheckerKind.Common) {
1214
override fun check(
1315
declaration: FirDeclaration,
1416
context: CheckerContext,
1517
reporter: DiagnosticReporter,
1618
) {
1719
declaration.annotations.forEach { annotation ->
18-
annotation.toAnnotationClassLikeSymbol(context.session)?.recordClass(context)
20+
annotation.toAnnotationClassLikeSymbol(context.session)?.let {
21+
classUsageRecorder.recordClass(it, context)
22+
}
1923
}
2024
}
2125
}
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.bazel.kotlin.plugin.jdeps.k2.checker.declaration
22

3-
import io.bazel.kotlin.plugin.jdeps.k2.recordTypeRef
3+
import io.bazel.kotlin.plugin.jdeps.k2.ClassUsageRecorder
44
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
55
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
66
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -9,7 +9,9 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
99
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
1010
import org.jetbrains.kotlin.fir.declarations.utils.isExtension
1111

12-
internal object CallableChecker : FirCallableDeclarationChecker(MppCheckerKind.Common) {
12+
internal class CallableChecker(
13+
private val classUsageRecorder: ClassUsageRecorder,
14+
) : FirCallableDeclarationChecker(MppCheckerKind.Common) {
1315
/**
1416
* Tracks the return type & type parameters of a callable declaration. Function parameters are
1517
* tracked in [FunctionChecker].
@@ -20,19 +22,20 @@ internal object CallableChecker : FirCallableDeclarationChecker(MppCheckerKind.C
2022
reporter: DiagnosticReporter,
2123
) {
2224
// return type
23-
declaration.returnTypeRef.recordTypeRef(context)
25+
declaration.returnTypeRef.let { classUsageRecorder.recordTypeRef(it, context) }
2426

2527
// type params
2628
declaration.typeParameters.forEach { typeParam ->
2729
typeParam.symbol.resolvedBounds.forEach { typeParamBound ->
28-
typeParamBound.recordTypeRef(context)
30+
typeParamBound.let { classUsageRecorder.recordTypeRef(it, context) }
2931
}
3032
}
3133

3234
// receiver param for extensions
3335
if (declaration !is FirAnonymousFunction) {
34-
declaration.receiverParameter?.typeRef
35-
?.recordTypeRef(context, isExplicit = declaration.isExtension)
36+
declaration.receiverParameter?.typeRef?.let {
37+
classUsageRecorder.recordTypeRef(it, context, isExplicit = declaration.isExtension)
38+
}
3639
}
3740
}
3841
}
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
package io.bazel.kotlin.plugin.jdeps.k2.checker.declaration
22

3-
import io.bazel.kotlin.plugin.jdeps.k2.recordClass
4-
import io.bazel.kotlin.plugin.jdeps.k2.recordConeType
3+
import io.bazel.kotlin.plugin.jdeps.k2.ClassUsageRecorder
54
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
65
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
76
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
87
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassLikeChecker
98
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
109
import org.jetbrains.kotlin.fir.resolve.getSuperTypes
1110

12-
internal object ClassLikeChecker : FirClassLikeChecker(MppCheckerKind.Common) {
11+
internal class ClassLikeChecker(
12+
private val classUsageRecorder: ClassUsageRecorder,
13+
) : FirClassLikeChecker(MppCheckerKind.Common) {
1314
override fun check(
1415
declaration: FirClassLikeDeclaration,
1516
context: CheckerContext,
1617
reporter: DiagnosticReporter,
1718
) {
18-
declaration.symbol.recordClass(context)
19+
declaration.symbol.let { classUsageRecorder.recordClass(it, context) }
1920
// [recordClass] also handles supertypes, but this marks direct supertypes as explicit
2021
declaration.symbol.getSuperTypes(context.session, recursive = false).forEach {
21-
it.recordConeType(context)
22+
classUsageRecorder.recordConeType(it, context)
2223
}
2324
}
2425
}

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/k2/checker/declaration/FileChecker.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package io.bazel.kotlin.plugin.jdeps.k2.checker.declaration
22

33
import io.bazel.kotlin.plugin.jdeps.k2.ClassUsageRecorder
44
import io.bazel.kotlin.plugin.jdeps.k2.binaryClass
5-
import io.bazel.kotlin.plugin.jdeps.k2.recordClass
65
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
76
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
87
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -18,7 +17,9 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
1817
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
1918
import org.jetbrains.kotlin.name.ClassId
2019

21-
internal object FileChecker : FirFileChecker(MppCheckerKind.Common) {
20+
internal class FileChecker(
21+
private val classUsageRecorder: ClassUsageRecorder,
22+
) : FirFileChecker(MppCheckerKind.Common) {
2223
override fun check(
2324
declaration: FirFile,
2425
context: CheckerContext,
@@ -27,15 +28,19 @@ internal object FileChecker : FirFileChecker(MppCheckerKind.Common) {
2728
declaration.imports.filterIsInstance<FirResolvedImport>().forEach { import ->
2829
// check for classlike import (class, interface, object, enum, annotation, etc)
2930
if (import.resolvesToClass(context)) {
30-
import.classId()?.resolveToClass(context)?.recordClass(context)
31+
import.classId()?.resolveToClass(context)?.let {
32+
classUsageRecorder.recordClass(it, context)
33+
}
3134
} else {
3235
// check for function import
3336
val callableBinaryClass = import.resolveToFun(context)?.containerSource?.binaryClass()
3437
if (callableBinaryClass != null) {
35-
ClassUsageRecorder.recordClass(callableBinaryClass)
38+
classUsageRecorder.recordClass(callableBinaryClass)
3639
} else {
3740
// for other symbols, track the parent class
38-
import.resolvedParentClassId?.resolveToClass(context)?.recordClass(context)
41+
import.resolvedParentClassId?.resolveToClass(context)?.let {
42+
classUsageRecorder.recordClass(it, context)
43+
}
3944
}
4045
}
4146
}

src/main/kotlin/io/bazel/kotlin/plugin/jdeps/k2/checker/declaration/FunctionChecker.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.bazel.kotlin.plugin.jdeps.k2.checker.declaration
22

3-
import io.bazel.kotlin.plugin.jdeps.k2.recordTypeRef
3+
import io.bazel.kotlin.plugin.jdeps.k2.ClassUsageRecorder
44
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
55
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
66
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
77
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker
88
import org.jetbrains.kotlin.fir.declarations.FirFunction
99

10-
internal object FunctionChecker : FirFunctionChecker(MppCheckerKind.Common) {
10+
internal class FunctionChecker(
11+
private val classUsageRecorder: ClassUsageRecorder,
12+
) : FirFunctionChecker(MppCheckerKind.Common) {
1113
/**
1214
* Tracks the value parameters of a function declaration. Return type & type parameters are
1315
* tracked in [CallableChecker].
@@ -19,7 +21,7 @@ internal object FunctionChecker : FirFunctionChecker(MppCheckerKind.Common) {
1921
) {
2022
// function parameters
2123
declaration.valueParameters.forEach { valueParam ->
22-
valueParam.returnTypeRef.recordTypeRef(context)
24+
valueParam.returnTypeRef.let { classUsageRecorder.recordTypeRef(it, context) }
2325
}
2426
}
2527
}

0 commit comments

Comments
 (0)