diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..5967193 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.caching=true +org.gradle.parallel=true +org.gradle.workers.max=4 +org.gradle.jvmargs=-Xmx4g -Xms4g -XX:MaxMetaspaceSize=1g -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError diff --git a/src/main/kotlin/mcp/code/analysis/service/CodeAnalyzer.kt b/src/main/kotlin/mcp/code/analysis/service/CodeAnalyzer.kt index f2808ce..f3454f2 100644 --- a/src/main/kotlin/mcp/code/analysis/service/CodeAnalyzer.kt +++ b/src/main/kotlin/mcp/code/analysis/service/CodeAnalyzer.kt @@ -49,7 +49,7 @@ data class CodeAnalyzer( logger.info("Collected ${snippets.size} code snippets from ${repoDir.absolutePath}") logger.debug( """Snippets Found: - |${snippets.joinToString("\n")}""" + |${snippets.joinToString("\n")}""" .trimIndent() ) } diff --git a/src/test/kotlin/mcp/code/analysis/service/CodeAnalyzerTest.kt b/src/test/kotlin/mcp/code/analysis/service/CodeAnalyzerTest.kt index fc2aa89..da69ccf 100644 --- a/src/test/kotlin/mcp/code/analysis/service/CodeAnalyzerTest.kt +++ b/src/test/kotlin/mcp/code/analysis/service/CodeAnalyzerTest.kt @@ -20,7 +20,6 @@ class CodeAnalyzerTest { analyzer = CodeAnalyzer(logger = logger) } - // Test cases for findReadmeFile function data class ReadmeTestCase( val name: String, val files: Map, @@ -28,6 +27,13 @@ class CodeAnalyzerTest { val containsLogMessage: String, ) + data class SnippetsTestCase( + val name: String, + val files: Map, + val expectedSnippetCount: Int, + val shouldContainFiles: List, + ) + @Test fun `test findReadmeFile with various scenarios`() { val testCases = @@ -87,20 +93,33 @@ class CodeAnalyzerTest { } } - // Test cases for analyzeStructure function @Test fun `test analyzeStructure with different directory structures`() { // Arrange val subDir = File(tempDir, "src").apply { mkdir() } File(subDir, "Helper.java").apply { writeText("public class Helper { public void help() {} }") } - File(tempDir, "main.kt").apply { writeText("""fun main() { println("Hello") }""") } + File(tempDir, "main.kt").apply { writeText("""fun main() { println("Hello from Kotlin") }""") } + File(tempDir, "main.scala").apply { + writeText("""object Main { def main(args: Array[String]): Unit = println("Hello from Scala") }""") + } + File(tempDir, "main.py").apply { writeText("""print("Hello from Python")""") } + File(tempDir, "main.go").apply { writeText("""import "fmt"; func main() { fmt.Println("Hello from Go!") }""") } + File(tempDir, "main.ts").apply { writeText("""console.log("Hello from TypeScript")""") } + File(tempDir, "main.js").apply { writeText("""console.log("Hello from JavaScript")""") } + File(tempDir, "main.rb").apply { writeText("""puts "Hello from Ruby"""") } // Act val result = analyzer.analyzeStructure(tempDir) // Assert - assertTrue(result.containsKey("main.kt"), "Should contain main.kt file") assertTrue(result.containsKey("src"), "Should contain src directory") + assertTrue(result.containsKey("main.kt"), "Should contain main.kt file") + assertTrue(result.containsKey("main.scala"), "Should contain main.scala file") + assertTrue(result.containsKey("main.py"), "Should contain main.py file") + assertTrue(result.containsKey("main.go"), "Should contain main.go file") + assertTrue(result.containsKey("main.ts"), "Should contain main.ts file") + assertTrue(result.containsKey("main.rb"), "Should contain main.rb file") + assertTrue(result.containsKey("main.js"), "Should contain main.js file") val srcContent = result["src"] as? Map<*, *> assertNotNull(srcContent, "src should be a map") @@ -109,14 +128,31 @@ class CodeAnalyzerTest { val mainKtInfo = result["main.kt"] as? Map<*, *> assertNotNull(mainKtInfo, "main.kt should have metadata") assertEquals("kotlin", mainKtInfo!!["language"], "Should identify Kotlin language") - } - data class SnippetsTestCase( - val name: String, - val files: Map, - val expectedSnippetCount: Int, - val shouldContainFiles: List, - ) + val mainScalaInfo = result["main.scala"] as? Map<*, *> + assertNotNull(mainScalaInfo, "main.scala should have metadata") + assertEquals("scala", mainScalaInfo!!["language"], "Should identify Scala language") + + val mainPyInfo = result["main.py"] as? Map<*, *> + assertNotNull(mainPyInfo, "main.py should have metadata") + assertEquals("python", mainPyInfo!!["language"], "Should identify Python language") + + val mainGoInfo = result["main.go"] as? Map<*, *> + assertNotNull(mainGoInfo, "main.go should have metadata") + assertEquals("go", mainGoInfo!!["language"], "Should identify Go language") + + val mainTsInfo = result["main.ts"] as? Map<*, *> + assertNotNull(mainTsInfo, "main.ts should have metadata") + assertEquals("typescript", mainTsInfo!!["language"], "Should identify TypeScript language") + + val mainJsInfo = result["main.js"] as? Map<*, *> + assertNotNull(mainJsInfo, "main.js should have metadata") + assertEquals("javascript", mainJsInfo!!["language"], "Should identify JavaScript language") + + val mainRbInfo = result["main.rb"] as? Map<*, *> + assertNotNull(mainRbInfo, "main.rb should have metadata") + assertEquals("ruby", mainRbInfo!!["language"], "Should identify Ruby language") + } @Test fun `test collectAllCodeSnippets with different file types`() { diff --git a/src/test/kotlin/mcp/code/analysis/service/ModelContextServiceTest.kt b/src/test/kotlin/mcp/code/analysis/service/ModelContextServiceTest.kt index b5a2601..a73a14a 100644 --- a/src/test/kotlin/mcp/code/analysis/service/ModelContextServiceTest.kt +++ b/src/test/kotlin/mcp/code/analysis/service/ModelContextServiceTest.kt @@ -20,6 +20,31 @@ class ModelContextServiceTest { private lateinit var mockHttpClient: HttpClient private lateinit var service: ModelContextService + // Test cases for buildInsightsPrompt function + data class InsightsPromptTestCase( + val name: String, + val readmeContent: String, + val expectedContains: List, + val shouldNotContain: List = listOf(), + ) + + // Test cases for generateResponse function + data class ResponseTestCase( + val name: String, + val prompt: String, + val mockResponse: String, + val expectedResult: String, + ) + + // Test cases for generateSummary function + data class SummaryTestCase( + val name: String, + val codeStructure: Map, + val codeSnippets: List, + val insights: String, + val expectedPromptContains: List, + ) + @BeforeEach fun setUp() { logger = mockk(relaxed = true) @@ -58,14 +83,6 @@ class ModelContextServiceTest { service = ModelContextService(config = config, httpClient = mockHttpClient, logger = logger) } - // Test cases for buildInsightsPrompt function - data class InsightsPromptTestCase( - val name: String, - val readmeContent: String, - val expectedContains: List, - val shouldNotContain: List = listOf(), - ) - @Test fun `test buildInsightsPrompt formats README correctly`() { val testCases = @@ -133,22 +150,6 @@ class ModelContextServiceTest { } } - // Test cases for parseInsights function - data class InsightParsingTestCase( - val name: String, - val input: String, - val expectedCount: Int, - val expectedContains: List, - ) - - // Test cases for generateResponse function - data class ResponseTestCase( - val name: String, - val prompt: String, - val mockResponse: String, - val expectedResult: String, - ) - @Test fun `test generateResponse returns model response`() = runBlocking { val testCases = @@ -203,15 +204,6 @@ class ModelContextServiceTest { } } - // Test cases for generateSummary function - data class SummaryTestCase( - val name: String, - val codeStructure: Map, - val codeSnippets: List, - val insights: String, - val expectedPromptContains: List, - ) - @Test fun `test generateSummary builds combined prompt with code and insights`() = runBlocking { // Arrange