From 7f0f2c83b245efc35a7e9964a54e6717f8634260 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Fri, 22 Aug 2025 18:09:01 +0000 Subject: [PATCH] fix: correctly handle Java methods with @Override annotations in listCodeDefinitionNames - Skip class definition captures for Java to avoid duplication - When processing Java methods with annotations, find the actual method declaration line - Add test case to verify @Override methods are correctly identified Fixes #7330 --- .../__tests__/simple-java-override.test.ts | 52 +++++++++++++++++++ src/services/tree-sitter/index.ts | 38 +++++++++++++- src/services/tree-sitter/queries/java.ts | 3 +- 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/services/tree-sitter/__tests__/simple-java-override.test.ts diff --git a/src/services/tree-sitter/__tests__/simple-java-override.test.ts b/src/services/tree-sitter/__tests__/simple-java-override.test.ts new file mode 100644 index 0000000000..b37fa7f304 --- /dev/null +++ b/src/services/tree-sitter/__tests__/simple-java-override.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect } from "vitest" +import { testParseSourceCodeDefinitions } from "./helpers" +import { javaQuery } from "../queries" + +describe("Simple Java @Override test", () => { + it("should show what gets captured for @Override methods", async () => { + const overrideTestContent = `class TestClass { + @Override + public void testMethod() { + // Implementation goes here + } +}` + + const testOptions = { + language: "java", + wasmFile: "tree-sitter-java.wasm", + queryString: javaQuery, + extKey: "java", + } + + const parseResult = await testParseSourceCodeDefinitions("/test/file.java", overrideTestContent, testOptions) + + console.log("\n=== PARSE RESULT ===") + console.log(parseResult) + console.log("====================\n") + + if (parseResult) { + const lines = parseResult.split("\n").filter((line) => line.trim()) + console.log("\n=== INDIVIDUAL LINES ===") + lines.forEach((line, i) => { + console.log(`Line ${i}: ${line}`) + }) + console.log("========================\n") + + // Check for the issue + const hasOverrideLine = lines.some((line) => line.includes("@Override") && !line.includes("testMethod")) + + if (hasOverrideLine) { + console.log("❌ BUG CONFIRMED: @Override is shown without the method name") + const problematicLines = lines.filter( + (line) => line.includes("@Override") && !line.includes("testMethod"), + ) + console.log("Problematic lines:", problematicLines) + } else { + console.log("✅ No issue found - @Override appears with method name") + } + + // This test will fail if the bug exists + expect(hasOverrideLine).toBe(false) + } + }) +}) diff --git a/src/services/tree-sitter/index.ts b/src/services/tree-sitter/index.ts index 145ba84730..12fdf84a36 100644 --- a/src/services/tree-sitter/index.ts +++ b/src/services/tree-sitter/index.ts @@ -339,8 +339,42 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st } // For other component definitions else if (isNotHtmlElement(startLineContent)) { - formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[startLine]}\n` - processedLines.add(lineKey) + // For Java, special handling to avoid showing @Override as a separate line + // when it's part of a method declaration + if (language === "java" && name === "definition.method") { + // Check if the method has an annotation like @Override + const methodText = definitionNode.text + if (methodText.includes("@Override")) { + // Find the actual method declaration line (not the annotation line) + let methodDeclarationLine = startLine + for (let i = startLine; i <= endLine; i++) { + if ( + lines[i].includes("public") || + lines[i].includes("private") || + lines[i].includes("protected") || + lines[i].includes("void") || + lines[i].includes("static") + ) { + methodDeclarationLine = i + break + } + } + // Output the method with its proper line range, but show the method declaration line + formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[methodDeclarationLine]}\n` + processedLines.add(lineKey) + } else { + // Normal method without annotations + formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[startLine]}\n` + processedLines.add(lineKey) + } + } else if (language === "java" && name === "definition.class") { + // For Java classes, skip the entire class definition to avoid duplication + // The class name will be handled by name.definition.class + return + } else { + formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[startLine]}\n` + processedLines.add(lineKey) + } // If this is part of a larger definition, include its non-HTML context if (node.parent && node.parent.lastChild) { diff --git a/src/services/tree-sitter/queries/java.ts b/src/services/tree-sitter/queries/java.ts index 63cb663e88..01b007dee1 100644 --- a/src/services/tree-sitter/queries/java.ts +++ b/src/services/tree-sitter/queries/java.ts @@ -29,7 +29,8 @@ export default ` (record_declaration name: (identifier) @name.definition.record) @definition.record -; Annotation declarations +; Annotation type declarations (e.g., @interface MyAnnotation) +; Note: This captures annotation type declarations, not annotation usages like @Override (annotation_type_declaration name: (identifier) @name.definition.annotation) @definition.annotation