Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/services/tree-sitter/__tests__/simple-java-override.test.ts
Original file line number Diff line number Diff line change
@@ -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 () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test description says 'should show what gets captured for @OverRide methods' but it's actually testing that @OverRide is NOT shown without the method name. Would it be clearer to rename this to something like 'should correctly display method names with @OverRide annotations'?

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 ===")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these console.log statements be removed or converted to debug-level logging? They're helpful for debugging but might clutter test output in CI/CD pipelines.

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)
}
})
})
38 changes: 36 additions & 2 deletions src/services/tree-sitter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The heuristic for locating the method declaration line (checking for 'public', 'private', 'protected', 'void', or 'static') may fail for package‑private methods or those with non‑void return types. Consider a more robust approach (e.g., skipping lines that start with '@').

lines[i].includes("public") ||
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method detection logic here only checks for specific keywords like 'public', 'private', 'protected', 'void', and 'static'. This might miss methods that return non-void types or don't use these modifiers. Could we consider a more robust approach?

For example, methods like:

  • String getName() { ... }
  • List<Item> getItems() { ... }
  • Methods without access modifiers

Would these be correctly identified? Perhaps checking for method signature patterns with parentheses would be more reliable?

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`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some code duplication here with the formattedOutput and processedLines.add() pattern. Could we extract this into a small helper function to reduce duplication?

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) {
Expand Down
3 changes: 2 additions & 1 deletion src/services/tree-sitter/queries/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading