@@ -8,54 +8,119 @@ import * as path from "node:path";
88 */
99import { parseArgs } from "node:util" ;
1010import { Glob } from "bun" ;
11- import { buildCFG } from "./cfg-helper.ts" ;
1211import {
1312 fileTypes ,
1413 getLanguage ,
1514 iterFunctions ,
1615} from "../src/file-parsing/bun.ts" ;
17- import { getFuncDef } from "./render-function.ts" ;
16+ import { buildCFG } from "./cfg-helper.ts" ;
17+ import { getFuncDef } from "./render-function.ts" ;
1818
1919export function iterSourceFiles ( root : string ) : IterableIterator < string > {
2020 const sourceGlob = new Glob (
2121 `**/*.{${ fileTypes . map ( ( { ext } ) => ext ) . join ( "," ) } }` ,
2222 ) ;
2323 return sourceGlob . scanSync ( root ) ;
2424}
25+ function * iterFilenames (
26+ root : string ,
27+ dirsToInclude : string [ ] ,
28+ ) : IterableIterator < string > {
29+ if ( dirsToInclude . length === 1 && dirsToInclude [ 0 ] === "*" ) {
30+ yield * iterSourceFiles ( root ) ;
31+ } else {
32+ for ( const dir of dirsToInclude ) {
33+ for ( const filename of iterSourceFiles ( path . join ( root , dir ) ) ) {
34+ // We want the path relative to the root
35+ yield path . join ( dir , filename ) ;
36+ }
37+ }
38+ }
39+ }
2540
26- async function * iterInfo ( root : string ) {
27- for ( const filename of iterSourceFiles ( root ) ) {
28- const filepath = path . join ( root , filename ) ;
29- const code = await Bun . file ( filepath ) . text ( ) ;
41+ async function * iterFunctionInfo (
42+ root : string ,
43+ filenames : IterableIterator < string > ,
44+ ) : AsyncIterableIterator < {
45+ node_count : number ;
46+ start_position : { row :number , column :number } ;
47+ funcdef : string ;
48+ filename : string ;
49+ } > {
50+ for ( const filename of filenames ) {
51+ const code = await Bun . file ( path . join ( root , filename ) ) . text ( ) ;
3052 const language = getLanguage ( filename ) ;
3153 for ( const func of iterFunctions ( code , language ) ) {
3254 const cfg = buildCFG ( func , language ) ;
3355 yield {
34- file : filename ,
35- startIndex : func . startIndex ,
36- nodeCount : cfg . graph . order ,
37- funcDef : getFuncDef ( code , func ) ,
38- startPosition : func . startPosition ,
56+ node_count : cfg . graph . order ,
57+ start_position : func . startPosition ,
58+ funcdef : getFuncDef ( code , func ) ,
59+ filename : filename . replaceAll ( "\\" , "/" ) ,
3960 } ;
4061 }
4162 }
4263}
4364
65+ async function generateIndex (
66+ /** Project name on GitHub */
67+ project : string ,
68+ /** Git ref */
69+ ref : string ,
70+ /** Root on local filesystem */
71+ root : string ,
72+ /** Directories to index, relative to the root */
73+ dirsToInclude : string [ ] ,
74+ ) {
75+ const filenames = iterFilenames ( root , dirsToInclude ) ;
76+ const functions = await Array . fromAsync ( iterFunctionInfo ( root , filenames ) ) ;
77+ return {
78+ version : 1 ,
79+ content : {
80+ index_type : "github" ,
81+ project,
82+ ref,
83+ functions,
84+ } ,
85+ } ;
86+ }
87+
4488async function main ( ) {
45- const { values } = parseArgs ( {
89+ const {
90+ values,
91+ positionals : [ _runtime , _this , ...dirsToInclude ] ,
92+ } = parseArgs ( {
4693 args : Bun . argv ,
4794 options : {
95+ project : {
96+ type : "string" ,
97+ } ,
98+ ref : {
99+ type : "string" ,
100+ } ,
48101 root : {
49102 type : "string" ,
50103 } ,
104+ out : {
105+ type : "string" ,
106+ } ,
51107 } ,
52108 strict : true ,
53109 allowPositionals : true ,
54110 } ) ;
55111
56- const root = values . root ?? "." ;
112+ if ( ! values . project || ! values . ref || ! values . root ) {
113+ throw new Error ( "Missing arguments" ) ;
114+ }
57115
58- process . stdout . write ( JSON . stringify ( await Array . fromAsync ( iterInfo ( root ) ) ) ) ;
116+ const output = JSON . stringify (
117+ await generateIndex ( values . project , values . ref , values . root , dirsToInclude ) ,
118+ ) ;
119+ if ( values . out ) {
120+ await Bun . write ( values . out , output ) ;
121+ } else {
122+ await Bun . write ( Bun . stdout , output ) ;
123+ }
59124}
60125
61126if ( require . main === module ) {
0 commit comments