@@ -262,7 +262,7 @@ This approach allows us to focus on the most relevant parts of the code (defined
262262 *
263263 * @param captures - The captures to process
264264 * @param lines - The lines of the file
265- * @param minComponentLines - Minimum number of lines for a component to be included
265+ * @param language - The programming language of the file
266266 * @returns A formatted string with definitions
267267 */
268268function processCaptures ( captures : QueryCapture [ ] , lines : string [ ] , language : string ) : string | null {
@@ -310,7 +310,7 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
310310 const lineCount = endLine - startLine + 1
311311
312312 // Skip components that don't span enough lines
313- if ( lineCount < getMinComponentLines ( ) ) {
313+ if ( shouldSkip ( lineCount , capture , language ) ) {
314314 return
315315 }
316316
@@ -323,8 +323,14 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
323323 return
324324 }
325325
326+ let outputLineIdx = startLine
327+ // For Java method definitions, find the first non-annotation line
328+ if ( language === "java" && name === "definition.method" ) {
329+ outputLineIdx = skipJavaAnnotations ( lines , startLine , endLine )
330+ }
331+
326332 // Check if this is a valid component definition (not an HTML element)
327- const startLineContent = lines [ startLine ] . trim ( )
333+ const startLineContent = lines [ outputLineIdx ] . trim ( )
328334
329335 // Special handling for component name definitions
330336 if ( name . includes ( "name.definition" ) ) {
@@ -333,13 +339,13 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
333339
334340 // Add component name to output regardless of HTML filtering
335341 if ( ! processedLines . has ( lineKey ) && componentName ) {
336- formattedOutput += `${ startLine + 1 } --${ endLine + 1 } | ${ lines [ startLine ] } \n`
342+ formattedOutput += `${ outputLineIdx + 1 } --${ endLine + 1 } | ${ lines [ outputLineIdx ] } \n`
337343 processedLines . add ( lineKey )
338344 }
339345 }
340346 // For other component definitions
341347 else if ( isNotHtmlElement ( startLineContent ) ) {
342- formattedOutput += `${ startLine + 1 } --${ endLine + 1 } | ${ lines [ startLine ] } \n`
348+ formattedOutput += `${ outputLineIdx + 1 } --${ endLine + 1 } | ${ lines [ outputLineIdx ] } \n`
343349 processedLines . add ( lineKey )
344350
345351 // If this is part of a larger definition, include its non-HTML context
@@ -413,3 +419,84 @@ async function parseFile(
413419 return null
414420 }
415421}
422+ function shouldSkip ( lineCount : number , capture : QueryCapture , language : string ) {
423+ if ( language === "java" ) {
424+ if ( [ "definition.method" ] . includes ( capture . name ) ) {
425+ return false
426+ }
427+ }
428+ return lineCount < getMinComponentLines ( )
429+ }
430+
431+ /**
432+ * Skip Java annotations and find the first line that contains the actual method declaration
433+ *
434+ * @param lines - Array of lines from the file
435+ * @param startLine - Starting line index
436+ * @param endLine - Ending line index
437+ * @returns The line index of the first non-annotation line
438+ */
439+ function skipJavaAnnotations ( lines : string [ ] , startLine : number , endLine : number ) : number {
440+ let currentLine = startLine
441+ let inAnnotation = false
442+ let annotationDepth = 0
443+
444+ while ( currentLine <= endLine ) {
445+ const line = lines [ currentLine ] . trim ( )
446+
447+ // Skip empty lines
448+ if ( line . length === 0 ) {
449+ currentLine ++
450+ continue
451+ }
452+
453+ // Check if this line starts an annotation
454+ if ( line . startsWith ( "@" ) ) {
455+ inAnnotation = true
456+ annotationDepth = 0
457+
458+ // Count opening and closing parentheses to track annotation completion
459+ for ( const char of line ) {
460+ if ( char === "(" ) {
461+ annotationDepth ++
462+ } else if ( char === ")" ) {
463+ annotationDepth --
464+ }
465+ }
466+
467+ // If annotation is complete on this line, mark as not in annotation
468+ if ( annotationDepth <= 0 ) {
469+ inAnnotation = false
470+ }
471+
472+ currentLine ++
473+ continue
474+ }
475+
476+ // If we're still inside a multi-line annotation
477+ if ( inAnnotation ) {
478+ // Count parentheses to track when annotation ends
479+ for ( const char of line ) {
480+ if ( char === "(" ) {
481+ annotationDepth ++
482+ } else if ( char === ")" ) {
483+ annotationDepth --
484+ }
485+ }
486+
487+ // If annotation is complete, mark as not in annotation
488+ if ( annotationDepth <= 0 ) {
489+ inAnnotation = false
490+ }
491+
492+ currentLine ++
493+ continue
494+ }
495+
496+ // If we're not in an annotation and this line has content, this is our target
497+ return currentLine
498+ }
499+
500+ // If we couldn't find a non-annotation line, return the start line
501+ return startLine
502+ }
0 commit comments