• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15const ts = require('typescript');
16const fs = require('fs');
17const re = require("./tools/re");
18const { getLicense, checkOutBody } = require("./tools/tool");
19const { analyzeNamespace } = require("./analyze/namespace");
20
21// 读取和解析.d.ts文件
22const filePath = '@ohos.test.d.ts';
23// const sourceCode = fs.readFileSync(filePath, 'utf-8');
24// const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true);
25// let statements = sourceFile.statements
26
27// 打印语法树
28function stringifyWithoutCircular(obj) {
29    const cache = new Set();
30    return JSON.stringify(obj, (key, value) => {
31        if (typeof value === 'object' && value !== null) {
32        if (cache.has(value)) {
33            return; // Skip circular references
34        }
35        cache.add(value);
36        }
37        return value;
38    });
39    }
40
41
42function analyzeFileRaw(fn) {
43    const sourceCode = fs.readFileSync(filePath, 'utf-8');
44    const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true);
45    let statements = sourceFile.statements
46
47   // console.log(stringifyWithoutCircular(sourceFile));
48
49    let result = {
50        exportDefault: [],
51        exports: [],
52        imports:[],
53        declareType: [],
54        declareFunction: [],
55        declareNamespace: [],
56        declareInterface: [],
57        declareLicense: [],
58    }
59
60    if (statements.length === 0 ) {
61        return null;
62    }
63
64    let imports = statements[0].getText();
65    if (imports != null) {
66        result.imports.push(imports);
67    }
68
69    let data = statements[0].getFullText();
70    let licenseData = getLicense(data);
71    if (null != licenseData) {
72        result.declareLicense.push(licenseData)
73    }
74
75    let impordts = statements[1].getText();
76
77    let ff = statements[1].getChildren();
78    let ffa = statements[1].getChildAt(1);
79    let ffb = statements[1].getChildCount();
80    let ffc = statements[1].getLastToken();
81    let xx = statements[1].getEnd();
82
83    // let exportsInfo = statements[2].getText();
84
85    // let ff = statements[2].end
86    // let gg = statements[2].
87    // let exportName = statements[2].expression.escapedText
88
89    // result.exportDefault.push(exportName);
90
91    return analyzeRaw(statements, result)
92}
93
94function analyzeRaw(statements, result) {
95    while (true) {
96        let exportsInfo = statements[2].getText();
97        let matchs = re.match("export default ([a-zA-Z0-9_]+);", exportsInfo);
98        if (matchs != null) {
99            let exportName = re.getReg(exportsInfo, matchs.regs[1])
100            // data = re.removeReg(data, matchs.regs[0]);
101            result.exportDefault.push(exportName)
102        }
103
104        // data = re.replaceAll(data, "\n{", "{");
105        // let matchType = analyzeMatchType(matchs, data, result)
106        // if (matchType != null) {
107        //     data = matchType[0]
108        //     if (matchType[1] != null) {
109        //         result = matchType[1]
110        //     }
111        // }
112        let data = statements[1].getText();
113        let namespace = analyzeMatchNamespace(matchs, data, result)
114        if (namespace != null) {
115            data = namespace[0]
116            result = namespace[1]
117        }
118        let interface = analyzeMatchInterface(matchs, data, result)
119        if (interface != null) {
120            data = interface[0]
121            result = interface[1]
122        }
123        return result;
124        // let functionMatch = analyzeMatchFunction(matchs, data, result)
125        // if (functionMatch != null) {
126        //     data = functionMatch[0]
127        //     result = functionMatch[1]
128        // }
129        // if (oldData == data) {
130        //     NapiLog.logError("\nvvv 解析文件失败 vvv");
131        //     NapiLog.logError("[", data.substring(0, data.length > 64 ? 64 : data.length), "]");
132        //     break;
133        // }
134    }
135   return result
136}
137
138function analyzeMatchNamespace(matchs, data, result) {
139    matchs = re.match("declare namespace ([a-zA-Z_0-9]+) *({)", data);
140    // 解析declare
141    if (matchs != null) {
142        let namespaceName = re.getReg(data, matchs.regs[1])
143        let namespaceData = checkOutBody(data, matchs.regs[2][0], null, true)
144        data = data.substring(matchs.regs[2][1] + namespaceData.length + 1, data.length)
145        result.declareNamespace.push({
146            name: namespaceName,
147            body: analyzeNamespace(namespaceData)
148        })
149    }
150    return [data, result]
151}
152
153function analyzeMatchInterface(matchs, data, result) {
154    matchs = re.match("(export )*(declare )*interface ([A-Za-z_0-9<>= ]+) (extends [a-zA-Z]+ )*({)", data)
155    if (matchs) {
156        let interfaceName = re.getReg(data, matchs.regs[3])
157        let interfaceData = checkOutBody(data, matchs.regs[5][0], null, true)
158        data = data.substring(matchs.regs[5][1] + interfaceData.length + 1, data.length)
159        result.declareInterface.push({
160            name: interfaceName,
161            body: {}
162        })
163    }
164    return [data, result]
165}
166
167function analyzeMatchFunction(matchs, data, result) {
168    matchs = re.match("declare function ([A-Za-z0-9_]+)\\(([\n a-zA-Z:;=,_0-9?<>{}|]*)\\) *:"
169        + "*([A-Za-z0-9_<>{}:, .]+);*", data)
170    if (matchs) {
171        let functionName = re.getReg(data, matchs.regs[1])
172        let functionBody = re.getReg(data, matchs.regs[2])
173        data = re.removeReg(data, matchs.regs[0])
174        result.declareFunction.push({
175            name: functionName,
176            body: functionBody
177        })
178    }
179    return [data, result]
180}
181
182function analyzeMatchType(matchs, data, result) {
183    matchs = re.match("(export )*type ([a-zA-Z]+) *= *([()a-zA-Z :=>,\"| ]+);", data)
184    if (matchs) {
185        let exportName = re.getReg(data, matchs.regs[2])
186        let exportBody = re.getReg(data, matchs.regs[3])
187        data = re.removeReg(data, matchs.regs[0]);
188        result.declareType.push({
189            name: exportName,
190            body: exportBody
191        })
192        if (matchs.regs[1][0] != -1) {
193            result.exports.push(exportName)
194        }
195    }
196
197    matchs = re.match("(export )*type ([a-zA-Z]+) *= *(\n{)", data)
198    if (matchs) {
199        let exportName = re.getReg(data, matchs.regs[2])
200        let exportBody = checkOutBody(data, matchs.regs[3][0], null, true)
201        data = data.substring(matchs.regs[3][1] + exportBody.length + 2, data.length)
202        result.declareType.push({
203            name: exportName,
204            body: exportBody
205        })
206        if (matchs.regs[1][0] != -1) {
207            result.exports.push(exportName)
208        }
209    }
210    return [data, result]
211}
212
213module.exports = {
214    analyzeFileRaw
215}