mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-09 03:17:58 +00:00
fix: improve Java annotation handling in listCodeDefinitionNames
- Made annotation detection more generic (not hard-coded for specific annotations) - Skip lines starting with @ when looking for method signatures - Filter out standalone annotation definitions - Handles any number of annotations on methods/fields dynamically Fixes #7330
This commit is contained in:
parent
7f0f2c83b2
commit
0b1b51c226
2 changed files with 164 additions and 26 deletions
|
|
@ -0,0 +1,133 @@
|
|||
import { describe, it, expect } from "vitest"
|
||||
import { testParseSourceCodeDefinitions } from "./helpers"
|
||||
import { javaQuery } from "../queries"
|
||||
|
||||
describe("Java interface methods and annotations", () => {
|
||||
it("should correctly parse interface methods", async () => {
|
||||
const interfaceContent = `interface TestInterface {
|
||||
/**
|
||||
* This is a test method
|
||||
*/
|
||||
void testMethod();
|
||||
|
||||
String getName();
|
||||
|
||||
int calculate(int a, int b);
|
||||
}`
|
||||
|
||||
const testOptions = {
|
||||
language: "java",
|
||||
wasmFile: "tree-sitter-java.wasm",
|
||||
queryString: javaQuery,
|
||||
extKey: "java",
|
||||
}
|
||||
|
||||
const parseResult = await testParseSourceCodeDefinitions(
|
||||
"/test/TestInterface.java",
|
||||
interfaceContent,
|
||||
testOptions,
|
||||
)
|
||||
|
||||
console.log("\n=== INTERFACE PARSE RESULT ===")
|
||||
console.log(parseResult)
|
||||
console.log("==============================\n")
|
||||
|
||||
// Interface methods should be detected
|
||||
expect(parseResult).toBeTruthy()
|
||||
|
||||
// Force test to fail to see output
|
||||
if (!parseResult) {
|
||||
throw new Error("No parse result for interface")
|
||||
}
|
||||
if (!parseResult.includes("testMethod")) {
|
||||
throw new Error(`Interface methods not detected. Result:\n${parseResult}`)
|
||||
}
|
||||
expect(parseResult).toContain("testMethod")
|
||||
expect(parseResult).toContain("getName")
|
||||
expect(parseResult).toContain("calculate")
|
||||
})
|
||||
|
||||
it("should correctly handle multiple annotations on methods", async () => {
|
||||
const classContent = `class TestClass implements TestInterface {
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testMethod() {
|
||||
// Implementation goes here
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TestClass";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int calculate(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void helperMethod() {
|
||||
// Helper implementation
|
||||
}
|
||||
}`
|
||||
|
||||
const testOptions = {
|
||||
language: "java",
|
||||
wasmFile: "tree-sitter-java.wasm",
|
||||
queryString: javaQuery,
|
||||
extKey: "java",
|
||||
}
|
||||
|
||||
const parseResult = await testParseSourceCodeDefinitions("/test/TestClass.java", classContent, testOptions)
|
||||
|
||||
console.log("\n=== CLASS PARSE RESULT ===")
|
||||
console.log(parseResult)
|
||||
console.log("==========================\n")
|
||||
|
||||
if (parseResult) {
|
||||
const lines = parseResult.split("\n").filter((line) => line.trim())
|
||||
|
||||
// Check that method names are shown, not annotations
|
||||
const hasMethodNames = lines.some((line) => line.includes("testMethod"))
|
||||
const hasGetName = lines.some((line) => line.includes("getName"))
|
||||
const hasCalculate = lines.some((line) => line.includes("calculate"))
|
||||
const hasHelper = lines.some((line) => line.includes("helperMethod"))
|
||||
|
||||
// Check for the bug: annotations shown as method names
|
||||
const hasStandaloneOverride = lines.some(
|
||||
(line) =>
|
||||
line.includes("@Override") &&
|
||||
!line.includes("testMethod") &&
|
||||
!line.includes("getName") &&
|
||||
!line.includes("calculate"),
|
||||
)
|
||||
const hasStandaloneTest = lines.some((line) => line.includes("@Test") && !line.includes("testMethod"))
|
||||
const hasStandaloneDeprecated = lines.some(
|
||||
(line) => line.includes("@Deprecated") && !line.includes("calculate"),
|
||||
)
|
||||
|
||||
console.log("Method detection:")
|
||||
console.log(" testMethod:", hasMethodNames)
|
||||
console.log(" getName:", hasGetName)
|
||||
console.log(" calculate:", hasCalculate)
|
||||
console.log(" helperMethod:", hasHelper)
|
||||
console.log("\nAnnotation issues:")
|
||||
console.log(" Standalone @Override:", hasStandaloneOverride)
|
||||
console.log(" Standalone @Test:", hasStandaloneTest)
|
||||
console.log(" Standalone @Deprecated:", hasStandaloneDeprecated)
|
||||
|
||||
// All methods should be detected
|
||||
expect(hasMethodNames).toBe(true)
|
||||
expect(hasGetName).toBe(true)
|
||||
expect(hasCalculate).toBe(true)
|
||||
expect(hasHelper).toBe(true)
|
||||
|
||||
// Annotations should not appear as standalone method names
|
||||
expect(hasStandaloneOverride).toBe(false)
|
||||
expect(hasStandaloneTest).toBe(false)
|
||||
expect(hasStandaloneDeprecated).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -339,40 +339,45 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
|
|||
}
|
||||
// For other component definitions
|
||||
else if (isNotHtmlElement(startLineContent)) {
|
||||
// For Java, special handling to avoid showing @Override as a separate line
|
||||
// when it's part of a method declaration
|
||||
// For Java, special handling for methods with annotations
|
||||
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
|
||||
}
|
||||
// Find the actual method declaration line (skip annotation lines)
|
||||
let methodDeclarationLine = startLine
|
||||
for (let i = startLine; i <= endLine; i++) {
|
||||
const line = lines[i].trim()
|
||||
// Skip empty lines and annotation lines (lines starting with @)
|
||||
if (line && !line.startsWith("@") && !line.startsWith("//") && !line.startsWith("/*")) {
|
||||
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)
|
||||
}
|
||||
// Output the method with its proper line range, showing the method declaration line
|
||||
formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[methodDeclarationLine]}\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 if (language === "java" && name.includes("definition.annotation")) {
|
||||
// Skip standalone annotation definitions - they're not useful for code structure overview
|
||||
// Annotations will be shown as part of the methods/fields they annotate
|
||||
return
|
||||
} else {
|
||||
formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[startLine]}\n`
|
||||
// For Java, check if this line is just an annotation
|
||||
if (language === "java" && lines[startLine].trim().startsWith("@")) {
|
||||
// Find the next non-annotation line
|
||||
let actualDefinitionLine = startLine
|
||||
for (let i = startLine + 1; i <= endLine; i++) {
|
||||
const line = lines[i].trim()
|
||||
if (line && !line.startsWith("@")) {
|
||||
actualDefinitionLine = i
|
||||
break
|
||||
}
|
||||
}
|
||||
formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[actualDefinitionLine]}\n`
|
||||
} else {
|
||||
formattedOutput += `${startLine + 1}--${endLine + 1} | ${lines[startLine]}\n`
|
||||
}
|
||||
processedLines.add(lineKey)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue