Skip to content

Commit e015096

Browse files
committed
feat: Using regular expressions to optimize Java method signature matching
1 parent dafe76e commit e015096

File tree

1 file changed

+43
-67
lines changed

1 file changed

+43
-67
lines changed

src/services/tree-sitter/index.ts

Lines changed: 43 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import { QueryCapture } from "web-tree-sitter"
1010
// Private constant
1111
const DEFAULT_MIN_COMPONENT_LINES_VALUE = 4
1212

13+
// Language-specific rules
14+
const LANGUAGE_SKIP_RULES: Record<string, string[]> = {
15+
java: ["definition.method"],
16+
// Future languages can be added here
17+
}
18+
1319
// Getter function for MIN_COMPONENT_LINES (for easier testing)
1420
let currentMinComponentLines = DEFAULT_MIN_COMPONENT_LINES_VALUE
1521

@@ -27,6 +33,14 @@ export function setMinComponentLines(value: number): void {
2733
currentMinComponentLines = value
2834
}
2935

36+
function shouldSkipLineCountCheck(lineCount: number, capture: QueryCapture, language: string) {
37+
const skipRules = LANGUAGE_SKIP_RULES[language]
38+
if (skipRules && skipRules.includes(capture.name)) {
39+
return false
40+
}
41+
return lineCount < getMinComponentLines()
42+
}
43+
3044
const extensions = [
3145
"tla",
3246
"js",
@@ -310,7 +324,7 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
310324
const lineCount = endLine - startLine + 1
311325

312326
// Skip components that don't span enough lines
313-
if (shouldSkip(lineCount, capture, language)) {
327+
if (shouldSkipLineCountCheck(lineCount, capture, language)) {
314328
return
315329
}
316330

@@ -324,9 +338,9 @@ function processCaptures(captures: QueryCapture[], lines: string[], language: st
324338
}
325339

326340
let outputLineIdx = startLine
327-
// For Java method definitions, find the first non-annotation line
341+
// For Java method definitions, find the actual method signature line
328342
if (language === "java" && name === "definition.method") {
329-
outputLineIdx = skipJavaAnnotations(lines, startLine, endLine)
343+
outputLineIdx = findJavaMethodSignatureLine(lines, startLine, endLine)
330344
}
331345

332346
// Check if this is a valid component definition (not an HTML element)
@@ -419,84 +433,46 @@ async function parseFile(
419433
return null
420434
}
421435
}
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-
}
430436

431437
/**
432-
* Skip Java annotations and find the first line that contains the actual method declaration
438+
* Find the line containing the actual Java method signature
439+
* by looking for lines that match method declaration patterns
433440
*
434441
* @param lines - Array of lines from the file
435442
* @param startLine - Starting line index
436443
* @param endLine - Ending line index
437-
* @returns The line index of the first non-annotation line
444+
* @returns The line index of the method signature
438445
*/
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++
446+
function findJavaMethodSignatureLine(lines: string[], startLine: number, endLine: number): number {
447+
// Java method signature pattern:
448+
// - May start with access modifiers (public, private, protected, static, final, etc.)
449+
// - Followed by return type
450+
// - Followed by method name
451+
// - Followed by parentheses
452+
const methodSignaturePattern =
453+
/^\s*(public|private|protected|static|final|abstract|synchronized|native|strictfp|\w+\s+)*\w+\s*\(/
454+
455+
for (let i = startLine; i <= endLine; i++) {
456+
const line = lines[i].trim()
457+
458+
// Skip empty lines and annotation lines
459+
if (line.length === 0 || line.startsWith("@")) {
450460
continue
451461
}
452462

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
463+
// Check if this line looks like a method signature
464+
if (methodSignaturePattern.test(line)) {
465+
return i
474466
}
467+
}
475468

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
469+
// If no method signature found, return the first non-annotation, non-empty line
470+
for (let i = startLine; i <= endLine; i++) {
471+
const line = lines[i].trim()
472+
if (line.length > 0 && !line.startsWith("@")) {
473+
return i
494474
}
495-
496-
// If we're not in an annotation and this line has content, this is our target
497-
return currentLine
498475
}
499476

500-
// If we couldn't find a non-annotation line, return the start line
501477
return startLine
502478
}

0 commit comments

Comments
 (0)