@@ -4,24 +4,47 @@ const REGEX_ESCAPE_PATTERN = /[.*+?^${}()|[\]\\]/g;
44
55/**
66 * Get the shebang line from the root.
7+ * According to ECMAScript spec, shebangs (InputElementHashbangOrRegExp) are only
8+ * valid at the start of a Script or Module. We find hash_bang_lines that appear
9+ * at the beginning before any actual code. When multiple consecutive shebangs exist at the top,
10+ * we return the last one as it would be the effective shebang used.
711 * @param root The root node to search.
812 * @returns The shebang line if found, otherwise null.
913 */
10- export const getShebang = ( root : SgRoot ) =>
11- root . root ( ) . find ( {
14+ export const getShebang = ( root : SgRoot ) => {
15+ const allShebangs = root . root ( ) . findAll ( {
1216 rule : {
1317 kind : 'hash_bang_line' ,
1418 regex : '\\bnode(\\.exe)?\\b' ,
15- not : {
16- // tree-sitter wraps hash-bang in Error node
17- // when it's not in the top of program node
18- inside : {
19- kind : 'ERROR' ,
20- } ,
21- } ,
2219 } ,
2320 } ) ;
2421
22+ if ( ! allShebangs . length ) return null ;
23+
24+ // Check if first shebang is at line 0 (start of file)
25+ const firstShebang = allShebangs [ 0 ] ;
26+ if ( firstShebang . range ( ) . start . line !== 0 ) {
27+ return null ; // Shebang not at start of file
28+ }
29+
30+ // Collect all consecutive shebangs from the start
31+ const validShebangs = [ firstShebang ] ;
32+ for ( let i = 1 ; i < allShebangs . length ; i ++ ) {
33+ const prevLine = allShebangs [ i - 1 ] . range ( ) . end . line ;
34+ const currentLine = allShebangs [ i ] . range ( ) . start . line ;
35+
36+ // Check if this shebang is on the next consecutive line
37+ if ( currentLine === prevLine || currentLine === prevLine + 1 ) {
38+ validShebangs . push ( allShebangs [ i ] ) ;
39+ } else {
40+ break ; // Stop at first non-consecutive shebang
41+ }
42+ }
43+
44+ // Return the last consecutive shebang from the start
45+ return validShebangs [ validShebangs . length - 1 ] ;
46+ } ;
47+
2548/**
2649 * Replace Node.js arguments in the shebang line.
2750 * @param root The root node to search.
0 commit comments