1 | const {Expr, Token, Setter, Expression, SetterExpression, SpliceSetterExpression, TokenTypeData} = require('./lang');
|
2 | const SimpleCompiler = require('./simple-compiler');
|
3 | const fs = require('fs');
|
4 | const os = require('os');
|
5 | const path = require('path');
|
6 | const {spawn, spawnSync} = require('child_process');
|
7 | const {extractTypes} = require('./flow-types');
|
8 |
|
9 | function spawnAsync(proc, args, options) {
|
10 | return new Promise((resolve, reject) => {
|
11 | const child = spawn(proc, args, options);
|
12 | let results = '';
|
13 | let err = '';
|
14 | child.stdout.on('data', msg => {
|
15 | results += msg;
|
16 | });
|
17 | child.stderr.on('data', msg => {
|
18 | err += msg;
|
19 | });
|
20 | child.on('close', code => {
|
21 | if (code === 0) {
|
22 | resolve(results);
|
23 | } else {
|
24 | console.error(err);
|
25 | reject(code);
|
26 | }
|
27 | });
|
28 | });
|
29 | }
|
30 |
|
31 | const {splitSettersGetters, normalizeAndTagAllGetters} = require('./expr-tagging');
|
32 |
|
33 | class FlowCompiler extends SimpleCompiler {
|
34 | constructor(model, options) {
|
35 | const {getters, setters} = splitSettersGetters(model);
|
36 | super({...model, ...normalizeAndTagAllGetters(getters, setters)}, options);
|
37 | }
|
38 |
|
39 | get template() {
|
40 | return require('./templates/flow.js');
|
41 | }
|
42 |
|
43 | generateExpr(expr) {
|
44 | const currentToken = expr instanceof Expression ? expr[0] : expr;
|
45 | if (currentToken.hasOwnProperty('$id')) {
|
46 | return `annotate_${expr[0].$id}(${super.generateExpr(expr)})`;
|
47 | }
|
48 | return super.generateExpr(expr);
|
49 | }
|
50 |
|
51 | buildExprFunctionsByTokenType(acc, expr) {
|
52 | acc.push(`function annotate_${expr[0].$id} (src){return src}`);
|
53 | super.buildExprFunctionsByTokenType(acc, expr);
|
54 | }
|
55 |
|
56 | compile() {
|
57 | const src = super.compile();
|
58 | console.log(src);
|
59 | const tempDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'flow-'));
|
60 | const tempFilename = path.join(tempDirectory, `${this.options.name}.js`);
|
61 | const flowConfigFile = path.join(tempDirectory, '.flowconfig');
|
62 | const srcBeforeFlowSuggest = `// @flow
|
63 | ${this.options.flow};
|
64 | ${src.replace(/\/\*::(.*?)\*\//g, '$1').replace(/\/\*:(.*?)\*\//g, ':$1')}
|
65 | `;
|
66 | fs.writeFileSync(tempFilename, srcBeforeFlowSuggest);
|
67 | const flowCliOptions = {cwd: tempDirectory + path.sep};
|
68 | spawnSync(require.resolve('flow-bin/cli'), ['init'], flowCliOptions);
|
69 | const postFlowSrc = spawnSync(require.resolve('flow-bin/cli'), ['suggest', tempFilename], flowCliOptions);
|
70 | this.annotations = extractTypes(postFlowSrc);
|
71 | console.log(JSON.stringify(this.annotations));
|
72 | console.log(postFlowSrc);
|
73 | fs.unlinkSync(flowConfigFile);
|
74 | fs.unlinkSync(tempFilename);
|
75 | fs.rmdirSync(tempDirectory);
|
76 | return postFlowSrc;
|
77 | }
|
78 |
|
79 | get lang() {
|
80 | return 'flow';
|
81 | }
|
82 | }
|
83 |
|
84 | module.exports = FlowCompiler;
|