• 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");
20const { NapiLog } = require("./tools/NapiLog");
21
22// 读取和解析.d.ts文件
23const filePath = '@ohos.test.d.ts';
24
25// 打印语法树
26function stringifyWithoutCircular(obj) {
27    const cache = new Set();
28    return JSON.stringify(obj, (key, value) => {
29        if (typeof value === 'object' && value !== null) {
30        if (cache.has(value)) {
31            return; // Skip circular references
32        }
33        cache.add(value);
34        }
35        return value;
36    });
37    }
38
39
40function analyzeFileRaw(fn) {
41    const sourceCode = fs.readFileSync(filePath, 'utf-8');
42    const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true);
43    let statements = sourceFile.statements
44
45    let result = {
46        exportDefault: [],
47        exports: [],
48        imports:[],
49        declareType: [],
50        declareFunction: [],
51        declareNamespace: [],
52        declareInterface: [],
53        declareLicense: [],
54    }
55
56    if (statements.length === 0 ) {
57        return null;
58    }
59
60    let imports = statements[0].getText();
61    if (imports !== null && imports !== undefined) {
62        result.imports.push(imports);
63    }
64
65    let data = statements[0].getFullText();
66    let licenseData = getLicense(data);
67    if ('' !== licenseData) {
68        result.declareLicense.push(licenseData)
69    }
70
71    return analyzeRaw(statements, result)
72}
73
74function analyzeRaw(statements, result) {
75    while (true) {
76        let exportsInfo = statements[2].getText();
77        let matchs = re.match("export default ([a-zA-Z0-9_]+);", exportsInfo);
78        if (matchs !== null && matchs !== undefined) {
79            let exportName = re.getReg(exportsInfo, matchs.regs[1])
80            result.exportDefault.push(exportName)
81        }
82
83        let data = statements[1].getText();
84        let namespace = analyzeMatchNamespace(matchs, data, result)
85        if (namespace !== null && namespace !== undefined) {
86            data = namespace[0]
87            result = namespace[1]
88        }
89        let interface = analyzeMatchInterface(matchs, data, result)
90        if (interface !== null && interface !== undefined) {
91            data = interface[0]
92            result = interface[1]
93        }
94
95        let functionMatch = analyzeMatchFunction(matchs, data, result)
96        if (functionMatch !== null && functionMatch !== undefined) {
97            data = functionMatch[0]
98            result = functionMatch[1]
99        }
100
101        return result;
102
103    }
104   return result
105}
106
107function analyzeMatchNamespace(matchs, data, result) {
108    matchs = re.match("declare namespace ([a-zA-Z_0-9]+) *({)", data);
109    // 解析declare
110    if (matchs !== null && matchs !== undefined) {
111        let namespaceName = re.getReg(data, matchs.regs[1])
112        let namespaceData = checkOutBody(data, matchs.regs[2][0], null, true)
113        data = data.substring(matchs.regs[2][1] + namespaceData.length + 1, data.length)
114        result.declareNamespace.push({
115            name: namespaceName,
116            body: analyzeNamespace(namespaceData)
117        })
118    }
119    return [data, result]
120}
121
122function analyzeMatchInterface(matchs, data, result) {
123    matchs = re.match("(export )*(declare )*interface ([A-Za-z_0-9<>= ]+) (extends [a-zA-Z]+ )*({)", data)
124    if (matchs) {
125        let interfaceName = re.getReg(data, matchs.regs[3])
126        let interfaceData = checkOutBody(data, matchs.regs[5][0], null, true)
127        data = data.substring(matchs.regs[5][1] + interfaceData.length + 1, data.length)
128        result.declareInterface.push({
129            name: interfaceName,
130            body: {}
131        })
132    }
133    return [data, result]
134}
135
136function analyzeMatchFunction(matchs, data, result) {
137    matchs = re.match("declare function ([A-Za-z0-9_]+)\\(([\n a-zA-Z:;=,_0-9?<>{}|]*)\\) *:"
138        + "*([A-Za-z0-9_<>{}:, .]+);*", data)
139    if (matchs) {
140        let functionName = re.getReg(data, matchs.regs[1])
141        let functionBody = re.getReg(data, matchs.regs[2])
142        data = re.removeReg(data, matchs.regs[0])
143        result.declareFunction.push({
144            name: functionName,
145            body: functionBody
146        })
147    }
148    return [data, result]
149}
150
151function analyzeMatchType(matchs, data, result) {
152    matchs = re.match("(export )*type ([a-zA-Z]+) *= *([()a-zA-Z :=>,\"| ]+);", data)
153    if (matchs) {
154        let exportName = re.getReg(data, matchs.regs[2])
155        let exportBody = re.getReg(data, matchs.regs[3])
156        data = re.removeReg(data, matchs.regs[0]);
157        result.declareType.push({
158            name: exportName,
159            body: exportBody
160        })
161        if (matchs.regs[1][0] !== -1) {
162            result.exports.push(exportName)
163        }
164    }
165
166    matchs = re.match("(export )*type ([a-zA-Z]+) *= *(\n{)", data)
167    if (matchs) {
168        let exportName = re.getReg(data, matchs.regs[2])
169        let exportBody = checkOutBody(data, matchs.regs[3][0], null, true)
170        data = data.substring(matchs.regs[3][1] + exportBody.length + 2, data.length)
171        result.declareType.push({
172            name: exportName,
173            body: exportBody
174        })
175        if (matchs.regs[1][0] !== -1) {
176            result.exports.push(exportName)
177        }
178    }
179    return [data, result]
180}
181
182module.exports = {
183    analyzeFileRaw
184}