From 7d59ea2af9be2a6ec6070431cf8c2741dcce1d31 Mon Sep 17 00:00:00 2001 From: AntonButov <58133570+AntonButov@users.noreply.github.com> Date: Fri, 21 Feb 2025 21:03:10 +0300 Subject: [PATCH] rework main stream --- .../kotlin/com/code/factory/CodeFilter.kt | 12 +-- .../kotlin/com/code/factory/MainCodeWriter.kt | 41 ------- .../main/kotlin/com/code/factory/Storage.kt | 102 ------------------ .../kotlin/com/code/factory/TestCodeFilter.kt | 34 +++--- .../com/code/factory/TestFilesResolver.kt | 22 ++++ .../code/factory/TestSourcePathResolver.kt | 17 +++ .../kotlin/com/code/factory/bridge/Bridge.kt | 37 ++----- .../com/code/factory/bridge/BridgeImpl.kt | 55 +++------- .../com/code/factory/bridge/OpenAiService.kt | 31 +++--- .../com/code/factory/bridge/WriterData.kt | 7 ++ .../code/factory/coderesolver/CodeResolver.kt | 4 + .../factory/coderesolver/CodeResolverImpl.kt | 14 +-- .../com/code/factory/ksp/KspProcessor.kt | 41 ++++--- .../code/factory/ksp/KspProcessorProvider.kt | 22 ++-- .../com/code/factory/writer/StorageWriter.kt | 39 ------- .../kotlin/com/code/factory/writer/Writer.kt | 24 ----- .../com/code/factory/writer/WriterImpl.kt | 42 -------- .../src/test/kotlin/BridgeTestTest.kt | 54 ++-------- .../src/test/kotlin/CodeFilterTest.kt | 8 +- .../src/test/kotlin/GetSourceResolverTest.kt | 30 ++++++ .../src/test/kotlin/KspProcessorTest.kt | 10 +- .../src/test/kotlin/StorageTest.kt | 100 ----------------- .../src/test/kotlin/StorageWriterTest.kt | 32 ------ .../src/test/kotlin/TestCodeFilterTest.kt | 49 +++++---- .../src/test/kotlin/TestFileResolverTest.kt | 29 +++++ .../src/test/kotlin/WriterTest.kt | 40 ------- 26 files changed, 266 insertions(+), 630 deletions(-) delete mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/MainCodeWriter.kt delete mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/Storage.kt create mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/TestFilesResolver.kt create mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/TestSourcePathResolver.kt create mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/bridge/WriterData.kt delete mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/writer/StorageWriter.kt delete mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/writer/Writer.kt delete mode 100644 code-factory-processor/src/main/kotlin/com/code/factory/writer/WriterImpl.kt create mode 100644 code-factory-processor/src/test/kotlin/GetSourceResolverTest.kt delete mode 100644 code-factory-processor/src/test/kotlin/StorageTest.kt delete mode 100644 code-factory-processor/src/test/kotlin/StorageWriterTest.kt create mode 100644 code-factory-processor/src/test/kotlin/TestFileResolverTest.kt delete mode 100644 code-factory-processor/src/test/kotlin/WriterTest.kt diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/CodeFilter.kt b/code-factory-processor/src/main/kotlin/com/code/factory/CodeFilter.kt index 48cc3f2..971d666 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/CodeFilter.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/CodeFilter.kt @@ -6,9 +6,9 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSDeclaration interface CodeFilter { - fun getFilteredDeclarations( + fun getFilteredCodeDeclarations( resolver: Resolver, - interfaceWithOutDeclaration: Sequence, + interfaceWithOutDeclaration: KSClassDeclaration, ): Sequence } @@ -21,14 +21,14 @@ internal class CodeFilterImpl( private val getAllDeclarationFinder: AllDeclarationFinder, private val codeResolver: CodeResolver, ) : CodeFilter { - override fun getFilteredDeclarations( + override fun getFilteredCodeDeclarations( resolver: Resolver, - interfaceWithOutDeclaration: Sequence, + interfaceWithOutDeclaration: KSClassDeclaration, ): Sequence { - val codeInterfaceWithOutDeclaration = codeResolver.getCodeString(interfaceWithOutDeclaration).joinToString("\n") // #81 + val codeInterfaceWithOutDeclarationCode = codeResolver.getCodeString(interfaceWithOutDeclaration) return getAllDeclarationFinder.getAllDeclaration(resolver) .filter { - it.qualifiedName!!.asString() in codeInterfaceWithOutDeclaration + it.qualifiedName!!.asString() in codeInterfaceWithOutDeclarationCode } } } diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/MainCodeWriter.kt b/code-factory-processor/src/main/kotlin/com/code/factory/MainCodeWriter.kt deleted file mode 100644 index ad57345..0000000 --- a/code-factory-processor/src/main/kotlin/com/code/factory/MainCodeWriter.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.code.factory - -import com.code.factory.writer.StorageWriter -import com.code.factory.writer.WriterData -import com.code.factory.writer.appendText -import java.io.File -import java.io.File.separator -import java.io.FileOutputStream - -interface MainCodeWriter { - fun write(writerData: WriterData) -} - -fun mainCodeWriter(storageWriter: StorageWriter): MainCodeWriter = MainCodeWriterImpl(storageWriter) - -class MainCodeWriterImpl( - private val storageWriter: StorageWriter, -) : MainCodeWriter { - override fun write(writerData: WriterData) { - val baseFile = File(storageWriter.getKotlinPath()) - val file = File(baseFile, pathOf(writerData.packageName, writerData.name)) - - if (file.parentFile.exists().not()) { - file.parentFile.mkdirs() - } - - FileOutputStream(file).use { - it.appendText(writerData.code) - } - } - - private fun pathOf( - packageName: String, - fileName: String, - extensionName: String = "kt", - ): String { - val packageDirs = if (packageName != "") "${packageName.split(".").joinToString(separator)}$separator" else "" - val extension = if (extensionName != "") ".$extensionName" else "" - return "$packageDirs$fileName$extension" - } -} diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/Storage.kt b/code-factory-processor/src/main/kotlin/com/code/factory/Storage.kt deleted file mode 100644 index ee7c82e..0000000 --- a/code-factory-processor/src/main/kotlin/com/code/factory/Storage.kt +++ /dev/null @@ -1,102 +0,0 @@ -import com.code.factory.writer.WriterData -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import org.jetbrains.kotlin.konan.file.File -import java.nio.file.Files -import kotlin.io.path.Path - -interface Storage { - fun getDeclarationCode(): String? - - fun getNamesForTestFilter(): List - - fun saveDeclarationsCode(declarationsCode: String) - - fun saveDeclarationsNames(names: List) - - fun getInterfaceWithOutImplementation(): WriterData? - - fun setInterfaceWithOutImplementation(writerData: WriterData) - - fun clean() -} - -fun storage(): Storage = StorageImp() - -private val TmpDir = File("build/tmp/code-factory") -private val allDeclarationsFile = File(TmpDir, "DeclarationsCode.txt") -private val declarationsNamesFile = File(TmpDir, "DeclarationsNames.txt") -private val interfaceWithOutDeclarationFile = File(TmpDir, "InterfaceWithOutImplementation.txt") - -internal class StorageImp() : Storage { - private var allDeclarations: String? = readDeclarationsCode() - private var interfaceWithOutImplementation: WriterData? = readInterfaceWithOutImplementation() - - init { - if (!TmpDir.exists) { - TmpDir.mkdirs() - } - } - - override fun getInterfaceWithOutImplementation(): WriterData? { - return interfaceWithOutImplementation - } - - override fun getDeclarationCode(): String? { - return allDeclarations - } - - override fun getNamesForTestFilter(): List { - return readDeclarationsNames() - } - - override fun saveDeclarationsCode(declarationsCode: String) { - allDeclarations = allDeclarations?.let { - "$allDeclarations \n$declarationsCode" - } ?: declarationsCode - saveAllDeclarationsCode(declarationsCode) - } - - override fun saveDeclarationsNames(names: List) { - declarationsNamesFile.writeText(Json.encodeToString(names)) - } - - private fun saveAllDeclarationsCode(allDeclarations: String) { - allDeclarationsFile.writeText(allDeclarations) - } - - private fun saveInterfaceWithOutImplementation(writerData: WriterData) { - interfaceWithOutDeclarationFile.writeText(Json.encodeToString(writerData)) - } - - private fun readInterfaceWithOutImplementation(): WriterData? = - runCatching { - Json.decodeFromString(Files.readString(Path(interfaceWithOutDeclarationFile.path))) - }.getOrNull() - - private fun readDeclarationsCode(): String? = - runCatching { - Files.readString(Path(allDeclarationsFile.path)) - }.getOrNull() - - private fun readDeclarationsNames(): List = Json.decodeFromString(Files.readString(Path(declarationsNamesFile.path))) - - override fun setInterfaceWithOutImplementation(writerData: WriterData) { - interfaceWithOutImplementation = writerData - saveInterfaceWithOutImplementation(writerData) - } - - override fun clean() { - allDeclarations = null - interfaceWithOutImplementation = null - runCatching { - allDeclarationsFile.delete() - } - runCatching { - interfaceWithOutDeclarationFile.delete() - } - runCatching { - declarationsNamesFile.delete() - } - } -} diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/TestCodeFilter.kt b/code-factory-processor/src/main/kotlin/com/code/factory/TestCodeFilter.kt index c41a2be..b5e6ea6 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/TestCodeFilter.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/TestCodeFilter.kt @@ -1,30 +1,34 @@ package com.code.factory -import Storage import com.code.factory.coderesolver.CodeResolver -import com.code.factory.coderesolver.codeResolver -import com.google.devtools.ksp.processing.Resolver -import com.google.devtools.ksp.symbol.KSDeclaration interface TestCodeFilter { - fun getFilteredTestDeclarations(resolver: Resolver): Sequence + fun getFilteredTestCode( + declarations: Sequence, + basePath: String, + ): Sequence } fun testCodeFilter( - storage: Storage, + testFilesResolver: TestFilesResolver, codeResolver: CodeResolver, -): TestCodeFilter = TestCodeFilterImpl(storage, codeResolver) +): TestCodeFilter = TestCodeFilterImpl(testFilesResolver, codeResolver) class TestCodeFilterImpl( - private val storage: Storage, + private val testFilesResolver: TestFilesResolver, private val codeResolver: CodeResolver, ) : TestCodeFilter { - override fun getFilteredTestDeclarations(resolver: Resolver): Sequence { - val declarationsNames = storage.getNamesForTestFilter() - return resolver.getAllFiles() - .filter { - val codeOfTest = codeResolver.getCodeString(it) - declarationsNames.any { it in codeOfTest } - }.getAllDeclarations() + override fun getFilteredTestCode( + declarationNames: Sequence, + basePath: String, + ): Sequence { + val testFiles = testFilesResolver.getTestFiles(basePath) + return testFiles + .map { + codeResolver.getCode(it.path) + } + .filter { codeOfTest -> + declarationNames.any { it in codeOfTest } + } } } diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/TestFilesResolver.kt b/code-factory-processor/src/main/kotlin/com/code/factory/TestFilesResolver.kt new file mode 100644 index 0000000..2aae9c7 --- /dev/null +++ b/code-factory-processor/src/main/kotlin/com/code/factory/TestFilesResolver.kt @@ -0,0 +1,22 @@ +package com.code.factory + +import java.io.File + +interface TestFilesResolver { + fun getTestFiles(basePath: String): Sequence +} + +fun testFileResolver(): TestFilesResolver { + return TestFilesResolverImpl() +} + +internal class TestFilesResolverImpl : TestFilesResolver { + override fun getTestFiles(basePath: String): Sequence { + return findKtFiles(File(basePath)) + } + + private fun findKtFiles(directory: File): Sequence { + return directory.walkTopDown() + .filter { it.isFile && it.extension == "kt" } + } +} diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/TestSourcePathResolver.kt b/code-factory-processor/src/main/kotlin/com/code/factory/TestSourcePathResolver.kt new file mode 100644 index 0000000..f8de960 --- /dev/null +++ b/code-factory-processor/src/main/kotlin/com/code/factory/TestSourcePathResolver.kt @@ -0,0 +1,17 @@ +package com.code.factory + +import com.google.devtools.ksp.processing.Resolver + +interface TestSourcePathResolver { + fun getSourcesPath(mainResolver: Resolver): String +} + +fun testSourcePathResolver(): TestSourcePathResolver { + return GetTestSourcePathResolver() +} + +internal class GetTestSourcePathResolver : TestSourcePathResolver { + override fun getSourcesPath(mainResolver: Resolver): String { + return "${mainResolver.getAllFiles().first().filePath.split("main").first()}test/" + } +} diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/Bridge.kt b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/Bridge.kt index 7923f26..d11262e 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/Bridge.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/Bridge.kt @@ -1,9 +1,6 @@ package com.code.factory.bridge -import Storage -import com.code.factory.CompileChecker import com.code.factory.coderesolver.CodeResolver -import com.code.factory.writer.WriterData import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSDeclaration @@ -20,29 +17,25 @@ interface BridgeFactory { sealed interface Bridge { interface BridgeMain : Bridge { - fun saveDeclarations(allDeclarations: Sequence) - - fun saveInterFaceWithOutDeclaration(interfaceWithOutImpl: KSClassDeclaration) + suspend fun getCode( + testCode: Sequence, + declarations: Sequence, + interfaceWithOutImpl: KSClassDeclaration, + ): WriterData? } - interface BridgeTest : Bridge { - suspend fun getCode(testDeclarations: Sequence): WriterData? - } + interface BridgeTest : Bridge interface BridgeGenerated : Bridge } fun bridgeFactory( - storage: Storage, - compileChecker: CompileChecker, codeResolver: CodeResolver, logger: KSPLogger, path: String, -): BridgeFactory = BridgeFactoryImpl(storage, compileChecker, codeResolver, logger, path) +): BridgeFactory = BridgeFactoryImpl(codeResolver, logger, path) internal class BridgeFactoryImpl( - private val storage: Storage, - private val compileChecker: CompileChecker, private val codeResolver: CodeResolver, private val logger: KSPLogger, private val path: String, @@ -52,21 +45,13 @@ internal class BridgeFactoryImpl( override fun createMain(): Bridge.BridgeMain = keyLogic( - mock = BridgeMainWork(storage, codeResolver), - work = BridgeMainWork(storage, codeResolver), + mock = BridgeMainWork(codeResolver, openAiServiceMock(logger)), + work = BridgeMainWork(codeResolver, openAiService(apiKey, logger)), ) - override fun createTest(): Bridge.BridgeTest = - keyLogic( - mock = BridgeTestWork(codeResolver, storage, openAiServiceMock(logger), compileChecker), - work = BridgeTestWork(codeResolver, storage, openAiService(apiKey, logger), compileChecker), - ) + override fun createTest(): Bridge.BridgeTest = BridgeTestWork() - override fun createGenerated(): Bridge.BridgeGenerated = - keyLogic( - mock = BridgeGeneratedMock(), - work = BridgeGeneratedWork(), - ) + override fun createGenerated(): Bridge.BridgeGenerated = BridgeGeneratedWork() private fun keyLogic( mock: B, diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/BridgeImpl.kt b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/BridgeImpl.kt index 3bde74d..b5f5a7a 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/BridgeImpl.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/BridgeImpl.kt @@ -1,59 +1,30 @@ package com.code.factory.bridge -import Storage -import com.code.factory.CompileChecker import com.code.factory.coderesolver.CodeResolver -import com.code.factory.writer.WriterData import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSDeclaration import removeChatComment internal class BridgeMainWork( - private val storage: Storage, private val codeResolver: CodeResolver, + private val openAi: OpenAiService, ) : Bridge.BridgeMain { - override fun saveDeclarations(declarations: Sequence) { + override suspend fun getCode( + testCode: Sequence, + declarations: Sequence, + interfaceWithOutImpl: KSClassDeclaration, + ): WriterData? { val allDeclarationsCode = codeResolver.getCodeString(declarations).joinToString("\n") - storage.saveDeclarationsCode(allDeclarationsCode) - val declarationsNames = declarations.map { it.simpleName.asString() }.toList() - storage.saveDeclarationsNames(declarationsNames) - } - - override fun saveInterFaceWithOutDeclaration(interfaceWithOutImpl: KSClassDeclaration) { - val writerData = - WriterData( - code = interfaceWithOutImpl.toString(), - packageName = interfaceWithOutImpl.packageName.asString(), - name = interfaceWithOutImpl.simpleName.asString(), - ) - storage.setInterfaceWithOutImplementation(writerData) - } -} - -internal class BridgeTestWork( - private val codeResolver: CodeResolver, - private val storage: Storage, - private val openAi: OpenAiService, - private val compileChecker: CompileChecker, -) : Bridge.BridgeTest { - override suspend fun getCode(testDeclarations: Sequence): WriterData? { - val writeData = storage.getInterfaceWithOutImplementation() ?: return null - val testDeclarations = codeResolver.getCodeString(testDeclarations).joinToString("\n") - storage.saveDeclarationsCode(testDeclarations) - val context: String = storage.getDeclarationCode() ?: "" - val code = openAi.getCode(context, writeData.code).removeChatComment() - if (compileChecker.checkCompile(context, writeData.code)) { - return null // #54 - } - storage.clean() + val context = "$allDeclarationsCode\n${testCode.toList().joinToString("\n")}" + val generatedCode = openAi.getCode(context, interfaceWithOutImpl.toString()).removeChatComment() return WriterData( - code = code, - packageName = writeData.packageName, - name = writeData.name, + code = generatedCode, + packageName = interfaceWithOutImpl.packageName.asString(), + name = interfaceWithOutImpl.simpleName.asString(), ) } } -internal class BridgeGeneratedWork : Bridge.BridgeGenerated +internal class BridgeTestWork() : Bridge.BridgeTest -internal class BridgeGeneratedMock() : Bridge.BridgeGenerated +internal class BridgeGeneratedWork : Bridge.BridgeGenerated diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/OpenAiService.kt b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/OpenAiService.kt index ec90852..cde33fc 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/OpenAiService.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/OpenAiService.kt @@ -92,6 +92,7 @@ internal class OpenAiServiceImpl( context: String, interfaceForCode: String, ): String { + val logString = StringBuilder() val chatCompletionRequest = ChatCompletionRequest( model = ModelId(MODEL), @@ -107,25 +108,25 @@ internal class OpenAiServiceImpl( ), ChatMessage( role = ChatRole.User, - content = "$USER_ASK_FIRST $interfaceForCode $USER_ASK_SECOND", + content = + "$USER_ASK_FIRST $interfaceForCode $USER_ASK_SECOND" + .also { + logString.append("Request: ---->") + logString.append("\n") + logString.append(it) + logString.append("\n") + logString.append(context) + logString.append("\n") + }, ), ), - ).also { - logger.warn( - "Request: ----> \n" + - "${ - it.messages.map { - it.content + "\n" - } - }", - ) - } + ) val code = openAi.chatCompletion(chatCompletionRequest).choices.first().message.content ?: "" + logString.append("Response: <----") + logString.append("\n") + logString.append(code) return code.also { - logger.warn( - "response: <----\n" + - "$code\n", - ) + logger.warn(logString.toString()) } } } diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/bridge/WriterData.kt b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/WriterData.kt new file mode 100644 index 0000000..8856957 --- /dev/null +++ b/code-factory-processor/src/main/kotlin/com/code/factory/bridge/WriterData.kt @@ -0,0 +1,7 @@ +package com.code.factory.bridge + +data class WriterData( + val packageName: String, + val name: String, + val code: String, +) diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolver.kt b/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolver.kt index dd832b4..a5c7ae1 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolver.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolver.kt @@ -4,9 +4,13 @@ import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFile interface CodeResolver { + fun getCodeString(declaration: KSDeclaration): String + fun getCodeString(declaration: Sequence): Sequence fun getCodeString(file: KSFile): String + + fun getCode(filePath: String): String } fun codeResolver(): CodeResolver = CodeResolverImpl() diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolverImpl.kt b/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolverImpl.kt index b70dfff..1dc90c0 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolverImpl.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/coderesolver/CodeResolverImpl.kt @@ -6,20 +6,22 @@ import java.nio.file.Files import kotlin.io.path.Path internal class CodeResolverImpl : CodeResolver { + override fun getCodeString(declaration: KSDeclaration): String { + return declaration.containingFile?.let { getCodeString(it) } ?: "" // todo #46 + } + @Throws(AssertionError::class) override fun getCodeString(declaration: Sequence): Sequence { assert(declaration.toList().isNotEmpty()) - return declaration.map { - it.containingFile?.let { getCodeString(it) } ?: "" // todo #46 - } + return declaration.map(::getCodeString) } override fun getCodeString(file: KSFile): String { - return fileCode(file.filePath) + return getCode(file.filePath) } - private fun fileCode(fileName: String): String { - val path = Path(fileName) + override fun getCode(filePath: String): String { + val path = Path(filePath) return Files.readString(path) } } diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessor.kt b/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessor.kt index 1fe12e1..78c830b 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessor.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessor.kt @@ -4,9 +4,11 @@ import com.code.factory.CodeFilter import com.code.factory.CompileChecker import com.code.factory.InterfaceFinder import com.code.factory.TestCodeFilter +import com.code.factory.TestSourcePathResolver import com.code.factory.bridge.BridgeFactory import com.code.factory.coderesolver.CodeResolver -import com.code.factory.writer.Writer +import com.google.devtools.ksp.processing.CodeGenerator +import com.google.devtools.ksp.processing.Dependencies import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor @@ -15,7 +17,6 @@ import kotlinx.coroutines.runBlocking class KspProcessor( private val logger: KSPLogger, - private val writer: Writer, private val codeFilter: CodeFilter, private val testCodeFilter: TestCodeFilter, private val interfaceFinder: InterfaceFinder, @@ -23,6 +24,8 @@ class KspProcessor( private val compileChecker: CompileChecker, private val phaseResolver: PhaseResolver, private val bridgeFactory: BridgeFactory, + private val testSourcePathResolver: TestSourcePathResolver, + private val codeGenerator: CodeGenerator, ) : SymbolProcessor { override fun process(resolver: Resolver): List { runBlocking { @@ -34,23 +37,33 @@ class KspProcessor( interfaceFinder .getInterfacesWithOutImplementation(resolver) .firstOrNull() ?: return@runBlocking // todo # 47 only one yet - val declarations = codeFilter.getFilteredDeclarations(resolver, sequenceOf(interfaceWithOutImpl)) - bridgeMain.saveDeclarations(declarations) - bridgeMain.saveInterFaceWithOutDeclaration(interfaceWithOutImpl) - writer.setKotlinPath( - interfaceWithOutImpl.packageName.asString(), - interfaceWithOutImpl.simpleName.asString(), - ) + val declarations = codeFilter.getFilteredCodeDeclarations(resolver, interfaceWithOutImpl) + if (declarations.toList().isEmpty()) { + logger.warn("No declarations found") + return@runBlocking + } + val basePath = testSourcePathResolver.getSourcesPath(resolver) + val codeOfTests = + testCodeFilter.getFilteredTestCode(declarations.map { it.simpleName.asString() }, basePath) + if (codeOfTests.toList().isEmpty()) { + logger.warn("No tests found.") + } + val generatedCode = bridgeMain.getCode(codeOfTests, declarations, interfaceWithOutImpl) + generatedCode?.let { + codeGenerator.createNewFile( + dependencies = Dependencies.ALL_FILES, + packageName = it.packageName, + fileName = it.name, + ).use { + outputStream -> + outputStream.write(it.code.toByteArray()) + } + } ?: logger.warn("Code not valid") } Phases.Tests -> { // logger.warn("Test") val bridgeTest = bridgeFactory.createTest() - val declarationTest = testCodeFilter.getFilteredTestDeclarations(resolver) - val generatedCode = bridgeTest.getCode(declarationTest) - generatedCode?.let { - writer.write(it) - } ?: logger.warn("Code not valid") } Phases.Generated -> { diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessorProvider.kt b/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessorProvider.kt index c0eb267..3be9ae2 100644 --- a/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessorProvider.kt +++ b/code-factory-processor/src/main/kotlin/com/code/factory/ksp/KspProcessorProvider.kt @@ -1,9 +1,9 @@ package com.code.factory.ksp -import Storage import com.code.factory.AllDeclarationFinder import com.code.factory.CompileChecker import com.code.factory.InterfaceFinder +import com.code.factory.TestFilesResolver import com.code.factory.allDeclarationFinder import com.code.factory.basePathProvider import com.code.factory.bridge.bridgeFactory @@ -12,47 +12,39 @@ import com.code.factory.coderesolver.CodeResolver import com.code.factory.coderesolver.codeResolver import com.code.factory.compileChecker import com.code.factory.interfaceFinder -import com.code.factory.mainCodeWriter import com.code.factory.testCodeFilter -import com.code.factory.writer.storageWriter -import com.code.factory.writer.writer +import com.code.factory.testFileResolver +import com.code.factory.testSourcePathResolver import com.google.auto.service.AutoService import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment import com.google.devtools.ksp.processing.SymbolProcessorProvider -import storage @AutoService(SymbolProcessorProvider::class) class KspProcessorProvider( private val allDeclarationFinder: AllDeclarationFinder = allDeclarationFinder(), private val interfaceFinder: InterfaceFinder = interfaceFinder(), private val codeResolver: CodeResolver = codeResolver(), - private val storage: Storage = storage(), + private val testFilterResolver: TestFilesResolver = testFileResolver(), ) : SymbolProcessorProvider { override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { val compileChecker: CompileChecker = compileChecker(environment.logger) return KspProcessor( logger = environment.logger, - writer = - writer( - mainCodeWriter = mainCodeWriter(storageWriter()), - codeGenerator = environment.codeGenerator, - storageWriter = storageWriter(), - ), codeFilter = codeFilter(allDeclarationFinder, codeResolver), - testCodeFilter = testCodeFilter(storage, codeResolver), + testCodeFilter = testCodeFilter(testFilterResolver, codeResolver), interfaceFinder = interfaceFinder, codeResolver = codeResolver, bridgeFactory = bridgeFactory( - storage = storage(), path = basePathProvider(environment.codeGenerator).getBasePath(), logger = environment.logger, codeResolver = codeResolver, - compileChecker = compileChecker, ), compileChecker = compileChecker, phaseResolver = PhaseResolverImpl(), + testSourcePathResolver = testSourcePathResolver(), + codeGenerator = environment.codeGenerator, ) } } diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/writer/StorageWriter.kt b/code-factory-processor/src/main/kotlin/com/code/factory/writer/StorageWriter.kt deleted file mode 100644 index 851703b..0000000 --- a/code-factory-processor/src/main/kotlin/com/code/factory/writer/StorageWriter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.code.factory.writer - -import java.io.File -import java.io.FileOutputStream -import java.nio.file.Files -import kotlin.io.path.Path - -interface StorageWriter { - fun setKotlinPath(path: String) - - fun getKotlinPath(): String - - fun clean() -} - -fun storageWriter(): StorageWriter = StorageWriterImpl() - -private val kotlinPathDir = File("build/tmp/kotlinPath") -private val kotlinPathFile = File(kotlinPathDir, "KotlinPath.txt") - -class StorageWriterImpl : StorageWriter { - override fun setKotlinPath(path: String) { - if (kotlinPathDir.exists().not()) { - kotlinPathDir.mkdirs() - } - - FileOutputStream(kotlinPathFile).use { - it.appendText(path) - } - } - - override fun getKotlinPath(): String { - return Files.readString(Path(kotlinPathFile.path)) - } - - override fun clean() { - kotlinPathDir.delete() - } -} diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/writer/Writer.kt b/code-factory-processor/src/main/kotlin/com/code/factory/writer/Writer.kt deleted file mode 100644 index 9b30d42..0000000 --- a/code-factory-processor/src/main/kotlin/com/code/factory/writer/Writer.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.code.factory.writer - -import com.code.factory.MainCodeWriter -import com.google.devtools.ksp.processing.CodeGenerator - -interface Writer { - fun setKotlinPath( - packageName: String, - name: String, - ) - - fun write(writerData: WriterData) -} - -fun writer( - storageWriter: StorageWriter, - mainCodeWriter: MainCodeWriter, - codeGenerator: CodeGenerator, -): Writer = - WriterImpl( - storageWriter, - mainCodeWriter, - codeGenerator, - ) diff --git a/code-factory-processor/src/main/kotlin/com/code/factory/writer/WriterImpl.kt b/code-factory-processor/src/main/kotlin/com/code/factory/writer/WriterImpl.kt deleted file mode 100644 index 41ae356..0000000 --- a/code-factory-processor/src/main/kotlin/com/code/factory/writer/WriterImpl.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.code.factory.writer - -import com.code.factory.MainCodeWriter -import com.google.devtools.ksp.processing.CodeGenerator -import com.google.devtools.ksp.processing.Dependencies -import kotlinx.serialization.Serializable -import java.io.OutputStream - -internal class WriterImpl( - private val storageWriter: StorageWriter, - private val mainCodeWriter: MainCodeWriter, - private val codeGenerator: CodeGenerator, -) : Writer { - override fun setKotlinPath( - packageName: String, - name: String, - ) { - codeGenerator.createNewFile(Dependencies.ALL_FILES, packageName, name) - val emptyFile = codeGenerator.generatedFile.first() - val kotlinPath = emptyFile.parentFile.path // #77 - storageWriter.setKotlinPath(kotlinPath) - } - - override fun write(writerData: WriterData) { - mainCodeWriter.write(writerData) - // - codeGenerator.createNewFile(Dependencies.ALL_FILES, writerData.packageName, writerData.name).use { - it.appendText(writerData.code) - } - } -} - -@Serializable -data class WriterData( - val packageName: String, - val name: String, - val code: String, -) - -fun OutputStream.appendText(str: String) { - this.write(str.toByteArray()) -} diff --git a/code-factory-processor/src/test/kotlin/BridgeTestTest.kt b/code-factory-processor/src/test/kotlin/BridgeTestTest.kt index da1c07e..57b0554 100644 --- a/code-factory-processor/src/test/kotlin/BridgeTestTest.kt +++ b/code-factory-processor/src/test/kotlin/BridgeTestTest.kt @@ -1,22 +1,17 @@ -import com.code.factory.CompileChecker import com.code.factory.bridge.Bridge -import com.code.factory.bridge.BridgeTestWork +import com.code.factory.bridge.BridgeMainWork import com.code.factory.bridge.OpenAiService import com.code.factory.coderesolver.CodeResolver -import com.code.factory.writer.WriterData import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.mockk.coEvery -import io.mockk.every import io.mockk.mockk class BridgeTestTest : StringSpec({ - lateinit var bridgeTest: Bridge.BridgeTest + lateinit var bridgeMain: Bridge.BridgeMain lateinit var openAi: OpenAiService - lateinit var storage: Storage lateinit var codeResolver: CodeResolver - lateinit var compileChecker: CompileChecker beforeTest { openAi = mockk(relaxed = true) @@ -26,55 +21,22 @@ class BridgeTestTest : StringSpec({ AiCode ``` """.trimIndent() - storage = mockk(relaxed = true) codeResolver = mockk(relaxed = true) - compileChecker = mockk(relaxed = true) - bridgeTest = - BridgeTestWork( - codeResolver = codeResolver, - storage = storage, - openAi = openAi, - compileChecker = compileChecker, - ) + bridgeMain = BridgeMainWork(codeResolver, openAi) } - val writeData = - WriterData( - code = "I am code.", - packageName = "PackageName", - name = "Name", - ) - "when InterfaceFinder find interfaces bridge should to request code resolver for resolve it" { - every { - storage.getDeclarationCode() - } returns "We are declarations." - every { - storage.getInterfaceWithOutImplementation() - } returns writeData - val writeData = bridgeTest.getCode(mockk(relaxed = true)) + val writeData = bridgeMain.getCode(mockk(relaxed = true), mockk(relaxed = true), mockk(relaxed = true)) writeData!!.code shouldBe "AiCode" } "when allDeclarations is empty code should generate" { - every { - storage.getDeclarationCode() - } returns null - every { - storage.getInterfaceWithOutImplementation() - } returns writeData - val writeData = bridgeTest.getCode(mockk(relaxed = true)) + val writeData = bridgeMain.getCode(mockk(relaxed = true), emptySequence(), mockk(relaxed = true)) writeData!!.code shouldBe "AiCode" } - "when interfaceWithOutImplementation is null get code should return null" { - every { - storage.getDeclarationCode() - } returns "We are declarations." - every { - storage.getInterfaceWithOutImplementation() - } returns null - val writeData = bridgeTest.getCode(mockk(relaxed = true)) - writeData shouldBe null + "when interfaceWithOutImplementation is not null get code should return code" { + val writeData = bridgeMain.getCode(mockk(relaxed = true), mockk(relaxed = true), mockk(relaxed = true)) + writeData!!.code shouldBe "AiCode" } }) diff --git a/code-factory-processor/src/test/kotlin/CodeFilterTest.kt b/code-factory-processor/src/test/kotlin/CodeFilterTest.kt index c08765c..a68a24d 100644 --- a/code-factory-processor/src/test/kotlin/CodeFilterTest.kt +++ b/code-factory-processor/src/test/kotlin/CodeFilterTest.kt @@ -44,8 +44,12 @@ class CodeFilterTest : StringSpec({ } """.trimIndent() compilationForAssertations(simpleClass, interfaceWithOutDeclarations, secretClass) { resolver -> - val interfaceWithOutDeclarations = interfaceFinder.getInterfacesWithOutImplementation(resolver) - val result = codeFilter.getFilteredDeclarations(resolver, interfaceWithOutDeclarations).map { it.qualifiedName!!.asString() } + val interfaceWithOutDeclarations = interfaceFinder.getInterfacesWithOutImplementation(resolver).first() + val result = + codeFilter.getFilteredCodeDeclarations( + resolver, + interfaceWithOutDeclarations, + ).map { it.qualifiedName!!.asString() } result.toList() shouldBe listOf("SimpleClass", "InterfaceWithOutDeclarations") } } diff --git a/code-factory-processor/src/test/kotlin/GetSourceResolverTest.kt b/code-factory-processor/src/test/kotlin/GetSourceResolverTest.kt new file mode 100644 index 0000000..6815975 --- /dev/null +++ b/code-factory-processor/src/test/kotlin/GetSourceResolverTest.kt @@ -0,0 +1,30 @@ +import com.code.factory.testSourcePathResolver +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.KSFile +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk + +class GetSourceResolverTest : StringSpec({ + + val resolver: Resolver = mockk() + val file: KSFile = mockk() + val path = "/Users/antonbutov/StudioProjects/code-factory/integration-test/src/main/kotlin/ForGenerate.kt" + + beforeTest { + every { + file.filePath + } returns path + every { + resolver.getAllFiles() + } returns sequenceOf(file) + } + + "base case" { + val testSourcePathResolver = testSourcePathResolver() + + val result = testSourcePathResolver.getSourcesPath(resolver) + "/Users/antonbutov/StudioProjects/code-factory/integration-test/src/test/" shouldBe result + } +}) diff --git a/code-factory-processor/src/test/kotlin/KspProcessorTest.kt b/code-factory-processor/src/test/kotlin/KspProcessorTest.kt index 47b60a6..011491b 100644 --- a/code-factory-processor/src/test/kotlin/KspProcessorTest.kt +++ b/code-factory-processor/src/test/kotlin/KspProcessorTest.kt @@ -3,11 +3,13 @@ import com.code.factory.CodeFilter import com.code.factory.CompileChecker import com.code.factory.InterfaceFinder import com.code.factory.TestCodeFilter +import com.code.factory.TestSourcePathResolver import com.code.factory.bridge.BridgeFactory import com.code.factory.coderesolver.CodeResolver import com.code.factory.ksp.KspProcessor import com.code.factory.ksp.PhaseResolver import com.code.factory.ksp.Phases +import com.google.devtools.ksp.processing.CodeGenerator import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.symbol.KSDeclaration import io.kotest.core.spec.style.StringSpec @@ -29,6 +31,8 @@ class KspProcessorTest : StringSpec({ lateinit var phaseResolver: PhaseResolver lateinit var codeFilter: CodeFilter lateinit var testCodeFilter: TestCodeFilter + lateinit var testSourcePathResolver: TestSourcePathResolver + lateinit var codeGenerator: CodeGenerator beforeTest { bridgeFactory = mockk(relaxed = true) @@ -48,11 +52,11 @@ class KspProcessorTest : StringSpec({ phaseResolver = mockk(relaxed = true) codeFilter = mockk(relaxed = true) testCodeFilter = mockk(relaxed = true) - + testSourcePathResolver = mockk(relaxed = true) + codeGenerator = mockk(relaxed = true) kspProcessor = KspProcessor( logger = mockk(relaxed = true), - writer = mockk(relaxed = true), interfaceFinder = interfaceFinder, codeResolver = codeResolver, bridgeFactory = bridgeFactory, @@ -60,6 +64,8 @@ class KspProcessorTest : StringSpec({ phaseResolver = phaseResolver, codeFilter = codeFilter, testCodeFilter = testCodeFilter, + testSourcePathResolver = testSourcePathResolver, + codeGenerator = codeGenerator, ) } diff --git a/code-factory-processor/src/test/kotlin/StorageTest.kt b/code-factory-processor/src/test/kotlin/StorageTest.kt deleted file mode 100644 index e1c1d23..0000000 --- a/code-factory-processor/src/test/kotlin/StorageTest.kt +++ /dev/null @@ -1,100 +0,0 @@ -import com.code.factory.writer.WriterData -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.matchers.string.shouldContain - -class StorageTest : StringSpec({ - - lateinit var storage: Storage - - beforeTest { - storage = StorageImp() - } - - afterTest { - StorageImp().clean() - } - - "read default all declarations" { - val defaultAllDeclarations = storage.getDeclarationCode() - - defaultAllDeclarations shouldBe null - } - - "read allDeclaration test immediately" { - val allDeclarations = "Some code." - storage.saveDeclarationsCode(allDeclarations) - - val allDeclarationsRead = storage.getDeclarationCode() - allDeclarationsRead shouldBe allDeclarations - } - - "read test other phase" { - storage.clean() - val allDeclarations = "Some code other phase." - storage.saveDeclarationsCode(allDeclarations) - - val newStorage = StorageImp() - val allDeclarationsRead = newStorage.getDeclarationCode() - allDeclarationsRead shouldContain allDeclarations - } - - "when add first then add second should contaminate" { - val firstDeclaration = "Some code first." - storage.saveDeclarationsCode(firstDeclaration) - - val secondDeclaration = "Some code second." - storage.saveDeclarationsCode(secondDeclaration) - - val allDeclarationsRead = storage.getDeclarationCode() - allDeclarationsRead shouldContain firstDeclaration - allDeclarationsRead shouldContain secondDeclaration - } - - "when clean should return null" { - val allDeclarationsRead = storage.getDeclarationCode() - allDeclarationsRead shouldBe null - val interfaceWithOutImplementation = storage.getInterfaceWithOutImplementation() - interfaceWithOutImplementation shouldBe null - } - - "read default interfaceWithOutImplementation should be null" { - val interfaceWithOutImplementation = storage.getInterfaceWithOutImplementation() - - interfaceWithOutImplementation shouldBe null - } - - val interfaceWithOutImplementation = - WriterData( - code = "Some code interfaceWithOutImplementation.", - packageName = "packageName", - name = "name", - ) - - "save then read interfaceWithOutImplementation should return some immediate" { - storage.setInterfaceWithOutImplementation(interfaceWithOutImplementation) - val interfaceWithOutImplementationRead = storage.getInterfaceWithOutImplementation() - interfaceWithOutImplementationRead shouldBe interfaceWithOutImplementation - } - - "save then read interfaceWithOutImplementation should return some after restart" { - storage.setInterfaceWithOutImplementation(interfaceWithOutImplementation) - - val interfaceWithOutImplementationRead = StorageImp().getInterfaceWithOutImplementation() - interfaceWithOutImplementationRead shouldBe interfaceWithOutImplementation - } - - val declarationNames = listOf("FirstName", "SecondName") - - "save then save again then read interfaceWithOutImplementation should return last" { - storage.saveDeclarationsNames(declarationNames) - val declarationNamesRead = storage.getNamesForTestFilter() - declarationNamesRead shouldBe declarationNames - } - - "save then save again then read interfaceWithOutImplementation should return last after restart" { - storage.saveDeclarationsNames(declarationNames) - val declarationNamesRead = StorageImp().getNamesForTestFilter() - declarationNamesRead shouldBe declarationNames - } -}) diff --git a/code-factory-processor/src/test/kotlin/StorageWriterTest.kt b/code-factory-processor/src/test/kotlin/StorageWriterTest.kt deleted file mode 100644 index cdb60a4..0000000 --- a/code-factory-processor/src/test/kotlin/StorageWriterTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -import com.code.factory.writer.StorageWriter -import com.code.factory.writer.storageWriter -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe - -class StorageWriterTest : StringSpec({ - - lateinit var storageWriter: StorageWriter - - beforeTest { - storageWriter = storageWriter() - } - - afterTest { - storageWriter.clean() - } - - "writer and read immediately" { - storageWriter.setKotlinPath("kotlinPath") - - val readPath = storageWriter.getKotlinPath() - readPath shouldBe "kotlinPath" - } - - "writer and read new instance" { - storageWriter.setKotlinPath("KotlinPath") - - val readPathNewInstance = storageWriter().getKotlinPath() - - readPathNewInstance shouldBe "KotlinPath" - } -}) diff --git a/code-factory-processor/src/test/kotlin/TestCodeFilterTest.kt b/code-factory-processor/src/test/kotlin/TestCodeFilterTest.kt index 384bf83..e1dbbf1 100644 --- a/code-factory-processor/src/test/kotlin/TestCodeFilterTest.kt +++ b/code-factory-processor/src/test/kotlin/TestCodeFilterTest.kt @@ -1,22 +1,27 @@ import com.code.factory.TestCodeFilter +import com.code.factory.TestFilesResolver import com.code.factory.coderesolver.CodeResolver -import com.code.factory.compilation.compilationForAssertations import com.code.factory.testCodeFilter import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk +import java.io.File class TestCodeFilterTest : StringSpec({ - lateinit var storage: Storage lateinit var codeResolver: CodeResolver + lateinit var testFilesResolver: TestFilesResolver lateinit var testCodeFilter: TestCodeFilter beforeTest { - storage = mockk(relaxed = true) codeResolver = mockk(relaxed = true) - testCodeFilter = testCodeFilter(storage, codeResolver) + testFilesResolver = mockk(relaxed = true) + val testFile = File("testPath") + every { + testFilesResolver.getTestFiles(any()) + } returns sequenceOf(testFile) + testCodeFilter = testCodeFilter(testFilesResolver, codeResolver) } val testFile = @@ -30,15 +35,13 @@ class TestCodeFilterTest : StringSpec({ } """.trimIndent() - "when have empty declaration names should all return" { - val declarationsNames = listOf() + "when have empty declaration names should return nothing" { + val declarationsNames = emptySequence() every { - storage.getNamesForTestFilter() - } returns declarationsNames - compilationForAssertations(testFile) { resolver -> - val result = testCodeFilter.getFilteredTestDeclarations(resolver).toList() - result shouldBe emptyList() - } + codeResolver.getCodeString(file = any()) + } returns testFile + val result = testCodeFilter.getFilteredTestCode(declarationsNames, "path").toList() + result shouldBe emptyList() } val secretTest = @@ -51,17 +54,21 @@ class TestCodeFilterTest : StringSpec({ } """.trimIndent() - "when have a declaration should return the test" { - val declarationsNames = listOf("SomeClass") - every { - storage.getNamesForTestFilter() - } returns declarationsNames + "when secret not contain in test code the test should not return" { + val declarationsNames = sequenceOf("SomeClass") every { codeResolver.getCodeString(file = any()) } returns secretTest - compilationForAssertations(secretTest) { resolver -> - val result = testCodeFilter.getFilteredTestDeclarations(resolver).map { it.simpleName.asString() }.toList() - result shouldBe emptyList() - } + val result = testCodeFilter.getFilteredTestCode(declarationsNames, "path").toList() + result shouldBe emptyList() + } + + "when names contains in test should return the test" { + val declarationsNames = sequenceOf("SomeClass") + every { + codeResolver.getCode(any()) + } returns testFile // ! + val result = testCodeFilter.getFilteredTestCode(declarationsNames, "path").toList().first() + result shouldBe testFile } }) diff --git a/code-factory-processor/src/test/kotlin/TestFileResolverTest.kt b/code-factory-processor/src/test/kotlin/TestFileResolverTest.kt new file mode 100644 index 0000000..a7190e1 --- /dev/null +++ b/code-factory-processor/src/test/kotlin/TestFileResolverTest.kt @@ -0,0 +1,29 @@ +import com.code.factory.testFileResolver +import io.kotest.core.spec.style.StringSpec +import kotlin.io.path.createTempDirectory +import kotlin.test.assertEquals + +class TestFileResolverTest : StringSpec({ + + "base case" { + val testFileResolver = testFileResolver() + val tempDir = createTempDirectory().toFile() + + val file1 = java.io.File(tempDir, "Test1.kt") + val file2 = java.io.File(tempDir, "Test2.kt") + val subDir = java.io.File(tempDir, "subdir") + subDir.mkdir() + val file3 = java.io.File(subDir, "Test3.kt") + val otherFile = java.io.File(subDir, "Test.txt") + + file1.createNewFile() + file2.createNewFile() + file3.createNewFile() + otherFile.createNewFile() + + val result = testFileResolver.getTestFiles(tempDir.path).toList() + + assertEquals(3, result.size) + assert(result.containsAll(listOf(file1, file2, file3))) + } +}) diff --git a/code-factory-processor/src/test/kotlin/WriterTest.kt b/code-factory-processor/src/test/kotlin/WriterTest.kt deleted file mode 100644 index e0633ef..0000000 --- a/code-factory-processor/src/test/kotlin/WriterTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -import com.code.factory.MainCodeWriter -import com.code.factory.writer.StorageWriter -import com.code.factory.writer.WriterData -import com.code.factory.writer.writer -import com.google.devtools.ksp.processing.CodeGenerator -import io.kotest.core.spec.style.StringSpec -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify - -class WriterTest : StringSpec({ - - "when writer write code generator should to invoke create file" { - val storageWriter = mockk(relaxed = true) - every { - storageWriter.getKotlinPath() - } returns "Some path" - val mainCodeWriter = mockk(relaxed = true) - val codeGenerator = mockk(relaxed = true) - - val writer = writer(storageWriter, mainCodeWriter, codeGenerator) - val writeData = - WriterData( - code = "Some code", - packageName = "SomePackage", - name = "name", - ) - - writer.write( - writerData = writeData, - ) - - verify { - mainCodeWriter.write(writeData) - } - verify { - codeGenerator.createNewFile(any(), any(), any()) - } - } -})