@@ -4,35 +4,69 @@ const fs = require('fs');
4
4
const argv = require ( 'yargs-parser' ) ( process . argv . slice ( 2 ) ) ;
5
5
const inquirer = require ( 'inquirer' ) ;
6
6
const chalk = require ( 'chalk' ) ;
7
+ const crypto = require ( 'crypto' ) ;
7
8
const { cleanComment } = require ( './cleanComment' ) ;
8
9
9
10
const grammarsPath = path . resolve ( __dirname , '../src/grammar' ) ;
10
11
const outputPath = path . resolve ( __dirname , '../src/lib' ) ;
11
12
12
- const languageEntries = fs . readdirSync ( grammarsPath ) ;
13
+ const languageEntries = fs . readdirSync ( grammarsPath ) . filter ( ( language ) => {
14
+ return fs . statSync ( path . join ( grammarsPath , language ) ) . isDirectory ( ) ;
15
+ } ) ;
13
16
14
17
const baseCmd = 'antlr4ng -Dlanguage=TypeScript -visitor -listener -Xexact-output-dir -o' ;
15
18
16
- function compile ( language ) {
17
- const cmd = ` ${ baseCmd } ${ outputPath } / ${ language } ${ grammarsPath } / ${ language } /*.g4` ;
19
+ function getFileHash ( filePath ) {
20
+ if ( ! fs . existsSync ( filePath ) ) return null ;
18
21
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 ) ;
23
25
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 } ) ;
35
43
}
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
+ } ) ;
36
70
} ) ;
37
71
}
38
72
@@ -59,22 +93,32 @@ function prompt() {
59
93
} ) ;
60
94
}
61
95
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
+
62
111
function main ( ) {
63
112
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' ) {
69
115
// compile single: yarn antlr4 --lang=mysql
70
116
const supportedLanguage = languageEntries . find ( ( language ) =>
71
117
language . startsWith ( argv . lang )
72
118
) ;
73
119
74
120
if ( argv . lang === 'all' ) {
75
- languageEntries . forEach ( ( language ) => {
76
- compile ( language ) ;
77
- } ) ;
121
+ antlr4AllSql ( ) ;
78
122
} else if ( supportedLanguage ) {
79
123
compile ( supportedLanguage ) ;
80
124
} else {
0 commit comments