@@ -4,35 +4,69 @@ const fs = require('fs');
44const argv = require ( 'yargs-parser' ) ( process . argv . slice ( 2 ) ) ;
55const inquirer = require ( 'inquirer' ) ;
66const chalk = require ( 'chalk' ) ;
7+ const crypto = require ( 'crypto' ) ;
78const { cleanComment } = require ( './cleanComment' ) ;
89
910const grammarsPath = path . resolve ( __dirname , '../src/grammar' ) ;
1011const outputPath = path . resolve ( __dirname , '../src/lib' ) ;
1112
12- const languageEntries = fs . readdirSync ( grammarsPath ) ;
13+ const languageEntries = fs . readdirSync ( grammarsPath ) . filter ( ( language ) => {
14+ return fs . statSync ( path . join ( grammarsPath , language ) ) . isDirectory ( ) ;
15+ } ) ;
1316
1417const baseCmd = 'antlr4ng -Dlanguage=TypeScript -visitor -listener -Xexact-output-dir -o' ;
1518
16- function compile ( language ) {
17- const cmd = ` ${ baseCmd } ${ outputPath } / ${ language } ${ grammarsPath } / ${ language } /*.g4` ;
19+ function getFileHash ( filePath ) {
20+ if ( ! fs . existsSync ( filePath ) ) return null ;
1821
19- if ( language !== 'plsql' && fs . existsSync ( `${ outputPath } /${ language } ` ) ) {
20- console . info ( chalk . green ( `\nRemoving:` , chalk . gray ( `${ outputPath } /${ language } /*` ) ) ) ;
21- fs . rmSync ( `${ outputPath } /${ language } ` , { recursive : true } ) ;
22- }
22+ const fileBuffer = fs . readFileSync ( filePath ) ;
23+ const hashSum = crypto . createHash ( 'sha256' ) ;
24+ hashSum . update ( fileBuffer ) ;
2325
24- console . info ( chalk . green ( 'Executing:' ) , chalk . gray ( cmd ) ) ;
25- exec ( cmd , ( err ) => {
26- if ( err ) {
27- console . error (
28- chalk . redBright ( `\n[Antlr4 compile error]:` ) ,
29- chalk . cyan ( language ) ,
30- chalk . gray ( err )
31- ) ;
32- } else {
33- cleanComment ( language ) ;
34- console . info ( chalk . greenBright ( `Compile ${ language } succeeded!` ) ) ;
26+ return hashSum . digest ( 'hex' ) ;
27+ }
28+
29+ function compile ( language ) {
30+ return new Promise ( ( resolve , reject ) => {
31+ const outputDir = `${ outputPath } /${ language } ` ;
32+ const grammarFiles = fs
33+ . readdirSync ( `${ grammarsPath } /${ language } ` )
34+ . filter ( ( file ) => file . endsWith ( '.g4' ) ) ;
35+ const previousHashes = grammarFiles . map ( ( file ) => ( {
36+ file,
37+ hash : getFileHash ( path . join ( outputDir , file . replace ( '.g4' , '.ts' ) ) ) ,
38+ } ) ) ;
39+
40+ if ( language !== 'plsql' && fs . existsSync ( `${ outputPath } /${ language } ` ) ) {
41+ console . info ( chalk . green ( `\nRemoving:` , chalk . gray ( `${ outputPath } /${ language } /*` ) ) ) ;
42+ fs . rmSync ( `${ outputPath } /${ language } ` , { recursive : true } ) ;
3543 }
44+
45+ const cmd = `${ baseCmd } ${ outputDir } ${ grammarsPath } /${ language } /*.g4` ;
46+ console . info ( chalk . green ( 'Executing:' ) , chalk . gray ( cmd ) ) ;
47+ exec ( cmd , ( err ) => {
48+ if ( err ) {
49+ console . error (
50+ chalk . redBright ( `\n[Antlr4 compile error]:` ) ,
51+ chalk . cyan ( language ) ,
52+ chalk . gray ( err )
53+ ) ;
54+ } else {
55+ cleanComment ( language ) ;
56+ console . info ( chalk . greenBright ( `Compile ${ language } succeeded!` ) ) ;
57+
58+ const changedFiles = grammarFiles . filter ( ( file ) => {
59+ const newHash = getFileHash ( path . join ( outputDir , file . replace ( '.g4' , '.ts' ) ) ) ;
60+ const prevHash = previousHashes . find ( ( h ) => h . file === file ) ?. hash ;
61+ return newHash !== prevHash ;
62+ } ) ;
63+
64+ if ( changedFiles . length > 0 ) {
65+ return reject ( `${ language } not run antlr4` ) ;
66+ }
67+ resolve ( ) ;
68+ }
69+ } ) ;
3670 } ) ;
3771}
3872
@@ -59,22 +93,32 @@ function prompt() {
5993 } ) ;
6094}
6195
96+ async function antlr4AllSql ( ) {
97+ const errors = [ ] ;
98+
99+ const tasks = languageEntries . map ( ( language ) =>
100+ compile ( language ) . catch ( ( err ) => errors . push ( err ) )
101+ ) ;
102+
103+ await Promise . all ( tasks ) ;
104+
105+ if ( errors . length > 0 && argv . check ) {
106+ errors . forEach ( ( error ) => console . error ( chalk . red ( `- ${ error } ` ) ) ) ;
107+ process . exit ( 1 ) ; // 非零退出表示错误
108+ }
109+ }
110+
62111function main ( ) {
63112 if ( argv . all ) {
64- // compile all: yarn antlr4 --all
65- languageEntries . forEach ( ( language ) => {
66- compile ( language ) ;
67- } ) ;
68- } else if ( argv . lang ) {
113+ antlr4AllSql ( ) ;
114+ } else if ( argv . lang && typeof argv . lang === 'string' ) {
69115 // compile single: yarn antlr4 --lang=mysql
70116 const supportedLanguage = languageEntries . find ( ( language ) =>
71117 language . startsWith ( argv . lang )
72118 ) ;
73119
74120 if ( argv . lang === 'all' ) {
75- languageEntries . forEach ( ( language ) => {
76- compile ( language ) ;
77- } ) ;
121+ antlr4AllSql ( ) ;
78122 } else if ( supportedLanguage ) {
79123 compile ( supportedLanguage ) ;
80124 } else {
0 commit comments