Skip to content

Commit

Permalink
Merge pull request #131 from AntonButov/refactoring-dependencies
Browse files Browse the repository at this point in the history
add DI
  • Loading branch information
AntonButov authored Mar 4, 2025
2 parents 67a1492 + edd2664 commit c9b84bb
Show file tree
Hide file tree
Showing 26 changed files with 336 additions and 285 deletions.
6 changes: 4 additions & 2 deletions code-factory-processor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
alias(libs.plugins.vanniktech)
`java-gradle-plugin`
alias(libs.plugins.ktlint)
kotlin("kapt")
}

group = "io.github.antonbutov"
Expand All @@ -21,15 +22,16 @@ dependencies {
runtimeOnly(libs.ktor.okhttp)

implementation(kotlin("stdlib"))
implementation(libs.kotlin.kspApi)
implementation(libs.autoservice.annotations)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.tschuchortdev.testing.ksp)

implementation(libs.mockk)

implementation(libs.dagger)
kapt(libs.dagger.compiler)

testImplementation(kotlin("test"))
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotest.assertions)
testImplementation(libs.kotest.runner.junit5.jvm)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package com.code.factory

import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSDeclaration
import javax.inject.Inject

interface AllDeclarationFinder {
fun getAllDeclaration(resolver: Resolver): Sequence<KSDeclaration>
}

internal class AllDeclarationFinderImpl : AllDeclarationFinder {
override fun getAllDeclaration(resolver: Resolver): Sequence<KSDeclaration> {
return resolver.getAllFiles().getAllDeclarations()
class AllDeclarationFinderImpl
@Inject
constructor() : AllDeclarationFinder {
override fun getAllDeclaration(resolver: Resolver): Sequence<KSDeclaration> {
return resolver.getAllFiles().getAllDeclarations()
}
}
}

fun allDeclarationFinder(): AllDeclarationFinder = AllDeclarationFinderImpl()
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ package com.code.factory

import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import javax.inject.Inject

interface BasePathProvider {
fun getBasePath(): String
}

fun basePathProvider(codeGenerator: CodeGenerator): BasePathProvider = BasePathProviderImpl(codeGenerator)

// #62
class BasePathProviderImpl(private val codeGenerator: CodeGenerator) : BasePathProvider {
override fun getBasePath(): String {
codeGenerator.createNewFile(Dependencies.ALL_FILES, "", "tempFile") // #61
val emptyFile = codeGenerator.generatedFile.first()
val emptyFilePath = emptyFile.path
return emptyFilePath.split("build").first()
class BasePathProviderImpl
@Inject
constructor(private val codeGenerator: CodeGenerator) : BasePathProvider {
override fun getBasePath(): String {
codeGenerator.createNewFile(Dependencies.ALL_FILES, "", "tempFile") // #61
val emptyFile = codeGenerator.generatedFile.first()
val emptyFilePath = emptyFile.path
return emptyFilePath.split("build").first()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.code.factory.coderesolver.CodeResolver
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import javax.inject.Inject

interface CodeFilter {
fun getFilteredCodeDeclarations(
Expand All @@ -12,23 +13,20 @@ interface CodeFilter {
): Sequence<KSDeclaration>
}

fun codeFilter(
getAllDeclarationFinder: AllDeclarationFinder,
codeResolver: CodeResolver,
): CodeFilter = CodeFilterImpl(getAllDeclarationFinder, codeResolver)

internal class CodeFilterImpl(
private val getAllDeclarationFinder: AllDeclarationFinder,
private val codeResolver: CodeResolver,
) : CodeFilter {
override fun getFilteredCodeDeclarations(
resolver: Resolver,
interfaceWithOutDeclaration: KSClassDeclaration,
): Sequence<KSDeclaration> {
val codeInterfaceWithOutDeclarationCode = codeResolver.getCodeString(interfaceWithOutDeclaration)
return getAllDeclarationFinder.getAllDeclaration(resolver)
.filter {
it.qualifiedName!!.asString() in codeInterfaceWithOutDeclarationCode
}
class CodeFilterImpl
@Inject
constructor(
private val getAllDeclarationFinder: AllDeclarationFinder,
private val codeResolver: CodeResolver,
) : CodeFilter {
override fun getFilteredCodeDeclarations(
resolver: Resolver,
interfaceWithOutDeclaration: KSClassDeclaration,
): Sequence<KSDeclaration> {
val codeInterfaceWithOutDeclarationCode = codeResolver.getCodeString(interfaceWithOutDeclaration)
return getAllDeclarationFinder.getAllDeclaration(resolver)
.filter {
it.qualifiedName!!.asString() in codeInterfaceWithOutDeclarationCode
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.code.factory

import com.google.devtools.ksp.processing.KSPLogger
import com.tschuchort.compiletesting.KotlinCompilation
import com.tschuchort.compiletesting.SourceFile
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi

fun compileChecker(logger: KSPLogger): CompileChecker = CompileCheckerImpl()
import javax.inject.Inject

interface CompileChecker {
fun checkCompile(
Expand All @@ -16,27 +14,29 @@ interface CompileChecker {
}

@OptIn(ExperimentalCompilerApi::class)
internal class CompileCheckerImpl() : CompileChecker {
override fun checkCompile(
context: String,
test: String,
): Boolean {
return compile(context, test).exitCode == KotlinCompilation.ExitCode.OK
}
class CompileCheckerImpl
@Inject
constructor() : CompileChecker {
override fun checkCompile(
context: String,
test: String,
): Boolean {
return compile(context, test).exitCode == KotlinCompilation.ExitCode.OK
}

private fun compile(
@Language("kotlin") context: String,
@Language("kotlin") generatedCode: String,
): KotlinCompilation.Result {
return KotlinCompilation().apply {
sources =
buildList {
add(SourceFile.kotlin("Context.kt", context))
add(SourceFile.kotlin("GeneratedCode.kt", generatedCode))
}
messageOutputStream = System.out
verbose = true
inheritClassPath = true
}.compile()
private fun compile(
@Language("kotlin") context: String,
@Language("kotlin") generatedCode: String,
): KotlinCompilation.Result {
return KotlinCompilation().apply {
sources =
buildList {
add(SourceFile.kotlin("Context.kt", context))
add(SourceFile.kotlin("GeneratedCode.kt", generatedCode))
}
messageOutputStream = System.out
verbose = true
inheritClassPath = true
}.compile()
}
}
}
73 changes: 73 additions & 0 deletions code-factory-processor/src/main/kotlin/com/code/factory/DI.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.code.factory

import com.code.factory.bridge.BridgeFactory
import com.code.factory.bridge.BridgeFactoryImpl
import com.code.factory.coderesolver.CodeResolver
import com.code.factory.coderesolver.CodeResolverImpl
import com.code.factory.ksp.KspProcessor
import com.code.factory.ksp.PhaseResolver
import com.code.factory.ksp.PhaseResolverImpl
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.SymbolProcessor
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import javax.inject.Singleton

@Singleton
@Component(modules = [ProcessorBindModule::class])
interface ProcessorComponent {
fun getKSPProcessor(): KspProcessor

@Component.Builder
interface Builder {
@BindsInstance
fun logger(logger: KSPLogger): Builder

@BindsInstance
fun codeGenerator(codeGenerator: CodeGenerator): Builder

fun build(): ProcessorComponent
}
}

@Module
interface ProcessorBindModule {
@Binds
abstract fun provideAllDeclarationFinder(impl: AllDeclarationFinderImpl): AllDeclarationFinder

@Binds
abstract fun provideCodeResolver(impl: CodeResolverImpl): CodeResolver

@Binds
abstract fun provideTestCodeFilter(impl: TestCodeFilterImpl): TestCodeFilter

@Binds
abstract fun provideTestFilesResolver(impl: TestFilesResolverImpl): TestFilesResolver

@Binds
abstract fun provideCodeFilter(impl: CodeFilterImpl): CodeFilter

@Binds
abstract fun provideTestSourcePathResolver(impl: TestSourcePathResolverImpl): TestSourcePathResolver

@Binds
abstract fun provideBasePathProvider(impl: BasePathProviderImpl): BasePathProvider

@Binds
abstract fun provideCompileChecker(impl: CompileCheckerImpl): CompileChecker

@Binds
abstract fun provideBridgeFactory(impl: BridgeFactoryImpl): BridgeFactory

@Binds
abstract fun provideSymbolProcessor(impl: KspProcessor): SymbolProcessor

@Binds
abstract fun provideInterfaceFinder(impl: InterfaceFinderImpl): InterfaceFinder

@Binds
abstract fun providePhaseResolver(impl: PhaseResolverImpl): PhaseResolver
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@ import com.code.factory.usescases.getClassKind
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSClassDeclaration
import javax.inject.Inject

interface InterfaceFinder {
fun getInterfacesWithOutImplementation(resolver: Resolver): Sequence<KSClassDeclaration>
}

internal class InterfaceFinderImpl() : InterfaceFinder {
override fun getInterfacesWithOutImplementation(resolver: Resolver): Sequence<KSClassDeclaration> {
val interfaces = resolver.getClassKind(ClassKind.INTERFACE)
val classes = resolver.getClassKind(ClassKind.CLASS)
class InterfaceFinderImpl
@Inject
constructor() : InterfaceFinder {
override fun getInterfacesWithOutImplementation(resolver: Resolver): Sequence<KSClassDeclaration> {
val interfaces = resolver.getClassKind(ClassKind.INTERFACE)
val classes = resolver.getClassKind(ClassKind.CLASS)

return interfaces.filter { interfaceItem ->
classes.none { classItem ->
classItem.superTypes.any { superType ->
superType.resolve().declaration.qualifiedName?.asString() ==
interfaceItem.qualifiedName?.asString()
return interfaces.filter { interfaceItem ->
classes.none { classItem ->
classItem.superTypes.any { superType ->
superType.resolve().declaration.qualifiedName?.asString() ==
interfaceItem.qualifiedName?.asString()
}
}
}
}
}
}

fun interfaceFinder(): InterfaceFinder = InterfaceFinderImpl()
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.code.factory

import com.code.factory.coderesolver.CodeResolver
import javax.inject.Inject

interface TestCodeFilter {
fun getFilteredTestCode(
Expand All @@ -9,26 +10,23 @@ interface TestCodeFilter {
): Sequence<String>
}

fun testCodeFilter(
testFilesResolver: TestFilesResolver,
codeResolver: CodeResolver,
): TestCodeFilter = TestCodeFilterImpl(testFilesResolver, codeResolver)

class TestCodeFilterImpl(
private val testFilesResolver: TestFilesResolver,
private val codeResolver: CodeResolver,
) : TestCodeFilter {
override fun getFilteredTestCode(
declarationNames: Sequence<String>,
basePath: String,
): Sequence<String> {
val testFiles = testFilesResolver.getTestFiles(basePath)
return testFiles
.map {
codeResolver.getCode(it.path)
}
.filter { codeOfTest ->
declarationNames.any { it in codeOfTest }
}
class TestCodeFilterImpl
@Inject
constructor(
private val testFilesResolver: TestFilesResolver,
private val codeResolver: CodeResolver,
) : TestCodeFilter {
override fun getFilteredTestCode(
declarationNames: Sequence<String>,
basePath: String,
): Sequence<String> {
val testFiles = testFilesResolver.getTestFiles(basePath)
return testFiles
.map {
codeResolver.getCode(it.path)
}
.filter { codeOfTest ->
declarationNames.any { it in codeOfTest }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
package com.code.factory

import java.io.File
import javax.inject.Inject

interface TestFilesResolver {
fun getTestFiles(basePath: String): Sequence<File>
}

fun testFileResolver(): TestFilesResolver {
return TestFilesResolverImpl()
}

internal class TestFilesResolverImpl : TestFilesResolver {
override fun getTestFiles(basePath: String): Sequence<File> {
return findKtFiles(File(basePath))
}
class TestFilesResolverImpl
@Inject
constructor() : TestFilesResolver {
override fun getTestFiles(basePath: String): Sequence<File> {
return findKtFiles(File(basePath))
}

private fun findKtFiles(directory: File): Sequence<File> {
return directory.walkTopDown()
.filter { it.isFile && it.extension == "kt" }
private fun findKtFiles(directory: File): Sequence<File> {
return directory.walkTopDown()
.filter { it.isFile && it.extension == "kt" }
}
}
}
Loading

0 comments on commit c9b84bb

Please sign in to comment.