@@ -10,44 +10,25 @@ function showOutputToUser(context: unknown, output: string): void {
1010 ctx . metadata ?.( { metadata : { output } } )
1111}
1212
13- /**
14- * JS/TS languages that require complete function declaration patterns
15- */
16- const JS_TS_LANGUAGES = [ "javascript" , "typescript" , "tsx" ] as const
17-
18- /**
19- * Validates AST pattern for common incomplete patterns that will fail silently.
20- * Only validates JS/TS languages where function declarations require body.
21- *
22- * @throws Error with helpful message if pattern is incomplete
23- */
24- function validatePatternForCli ( pattern : string , lang : CliLanguage ) : void {
25- if ( ! JS_TS_LANGUAGES . includes ( lang as ( typeof JS_TS_LANGUAGES ) [ number ] ) ) {
26- return
27- }
28-
13+ function getEmptyResultHint ( pattern : string , lang : CliLanguage ) : string | null {
2914 const src = pattern . trim ( )
3015
31- // Detect incomplete function declarations:
32- // - "function $NAME" (no params/body)
33- // - "export function $NAME" (no params/ body)
34- // - "export async function $NAME" (no params/body)
35- // - "export default function $NAME" (no params/body)
36- // Pattern: ends with $METAVAR (uppercase, underscore, digits) without ( or {
37- const incompleteFunctionDecl =
38- / ^ ( e x p o r t \s + ) ? ( d e f a u l t \s + ) ? ( a s y n c \s + ) ? f u n c t i o n \s + \$ [ A - Z _ ] [ A - Z 0 - 9 _ ] * \s * $ / i . test ( src )
16+ if ( lang === "python" ) {
17+ if ( src . startsWith ( "class " ) && src . endsWith ( ":" ) ) {
18+ return `💡 Hint: Python class patterns need body. Try "class $NAME" or include body with $$$BODY`
19+ }
20+ if ( ( src . startsWith ( "def " ) || src . startsWith ( "async def " ) ) && src . endsWith ( ":" ) ) {
21+ return `💡 Hint: Python function patterns need body. Try "def $FUNC($$$):\\n $$$BODY"`
22+ }
23+ }
3924
40- if ( incompleteFunctionDecl ) {
41- throw new Error (
42- `Incomplete AST pattern for ${ lang } : "${ pattern } "\n\n` +
43- `ast-grep requires complete AST nodes. Function declarations must include parameters and body.\n\n` +
44- `Examples of correct patterns:\n` +
45- ` - "export async function $NAME($$$) { $$$ }" (matches export async functions)\n` +
46- ` - "function $NAME($$$) { $$$ }" (matches all function declarations)\n` +
47- ` - "async function $NAME($$$) { $$$ }" (matches async functions)\n\n` +
48- `Your pattern "${ pattern } " is missing the parameter list and body.`
49- )
25+ if ( [ "javascript" , "typescript" , "tsx" ] . includes ( lang ) ) {
26+ if ( / ^ ( e x p o r t \s + ) ? ( a s y n c \s + ) ? f u n c t i o n \s + \$ [ A - Z _ ] + \s * $ / i. test ( src ) ) {
27+ return `💡 Hint: Function patterns need params and body. Try "function $NAME($$$) { $$$ }"`
28+ }
5029 }
30+
31+ return null
5132}
5233
5334export const ast_grep_search = tool ( {
@@ -66,16 +47,23 @@ export const ast_grep_search = tool({
6647 } ,
6748 execute : async ( args , context ) => {
6849 try {
69- validatePatternForCli ( args . pattern , args . lang as CliLanguage )
70-
7150 const matches = await runSg ( {
7251 pattern : args . pattern ,
7352 lang : args . lang as CliLanguage ,
7453 paths : args . paths ,
7554 globs : args . globs ,
7655 context : args . context ,
7756 } )
78- const output = formatSearchResult ( matches )
57+
58+ let output = formatSearchResult ( matches )
59+
60+ if ( matches . length === 0 ) {
61+ const hint = getEmptyResultHint ( args . pattern , args . lang as CliLanguage )
62+ if ( hint ) {
63+ output += `\n\n${ hint } `
64+ }
65+ }
66+
7967 showOutputToUser ( context , output )
8068 return output
8169 } catch ( e ) {
0 commit comments