• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device 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 */
15
16const { readFile, parseFiles } = require('./collectApi');
17const path = require('path');
18const fs = require('fs');
19const ts = require('typescript');
20
21let exportClass = '';
22
23function collectBaseApi(importFiles, applicationApis) {
24  const SDK_API_FILES = [];
25  const APP_API_FILES = [];
26  getAllApiFiles(SDK_API_FILES);
27
28  importFiles.forEach(importData => {
29    for (let i = 0; i < SDK_API_FILES.length; i++) {
30      const filePath = SDK_API_FILES[i];
31      if (path.basename(filePath).replace(/\.d\.ts/, '') === importData.importFile) {
32        APP_API_FILES.push(filePath);
33        break;
34      }
35    }
36  });
37
38  let noRepeatImportFiles = [...new Set(APP_API_FILES)];
39  const baseApis = parseFiles(noRepeatImportFiles);
40  return compareApis(baseApis, applicationApis, SDK_API_FILES);
41}
42
43function compareApis(baseApis, applicationApis, sdkFiles) {
44  let callApisInApp = [];
45  let componentApiIndexSet = new Set();
46  applicationApis = deleteUndefinedApi(applicationApis);
47
48  applicationApis.forEach(applicationApi => {
49    sdkFiles.forEach(sdkFile => {
50      if (applicationApi.notes !== '实例化对象方式调用' &&
51        path.basename(sdkFile).replace(/\.d\.ts/, '') === applicationApi.packageName) {
52        applicationApi.moduleName = handleImportClass(sdkFile);
53      }
54    });
55  });
56
57  for (let i = 0; i < applicationApis.length; i++) {
58    for (let j = 0; j < baseApis.length; j++) {
59      if (applicationApis[i].type === 'ArkUI' && baseApis[j].packageName === 'ArkUI') {
60        compareComponentApi(applicationApis[i], baseApis[j], callApisInApp, componentApiIndexSet, i);
61      } else if (!applicationApis[i].value && applicationApis[i].type === 'API') {
62        compareApisWithoutValue(applicationApis[i], baseApis[j], callApisInApp);
63      } else if (applicationApis[i].value && applicationApis[i].type === 'API') {
64        compareValuableApis(applicationApis[i], baseApis[j], callApisInApp);
65      }
66    }
67  }
68  return callApisInApp;
69}
70
71exports.collectBaseApi = collectBaseApi;
72
73function deleteUndefinedApi(applicationApis) {
74  for (let i = 0; i < applicationApis.length; i++) {
75    if (applicationApis[i] === undefined) {
76      applicationApis.splice(i, 1);
77    }
78  }
79  return applicationApis;
80}
81
82function compareApisWithoutValue(applicationApi, baseApi, callApisInApp) {
83  if (typeof (applicationApi.moduleName) === 'string' &&
84    baseApi.className.toLowerCase() === applicationApi.moduleName.toLowerCase() &&
85    applicationApi.apiName === baseApi.methodName &&
86    applicationApi.packageName.replace('@', '') === baseApi.packageName) {
87    let applyApi = JSON.parse(JSON.stringify(baseApi));
88    applyApi.pos = applicationApi.callLocation;
89    applyApi.notes = applicationApi.notes ? applicationApi.notes : '';
90    callApisInApp.push(applyApi);
91  }
92}
93
94function compareValuableApis(applicationApi, baseApi, callApisInApp) {
95  if (applicationApi.apiName === baseApi.className && applicationApi.value === baseApi.methodName &&
96    applicationApi.packageName.replace('@', '') === baseApi.packageName) {
97    let applyApi = JSON.parse(JSON.stringify(baseApi));
98    applyApi.pos = applicationApi.callLocation;
99    callApisInApp.push(applyApi);
100  }
101}
102
103function handleImportClass(filePath) {
104  const fileContent = fs.readFileSync(filePath, 'utf-8');
105  ts.transpileModule(fileContent, {
106    compilerOptions: {
107      'target': ts.ScriptTarget.ES2017,
108    },
109    fileName: filePath.replace(/\.d\.ts/, '.ts'),
110    transformers: { before: [isExportClass()] },
111  });
112  return exportClass;
113}
114
115function isExportClass() {
116  return (context) => {
117    return (sourcefile) => {
118      const statements = sourcefile.statements;
119      statements.forEach(statement => {
120        if (ts.isClassDeclaration(statement)) {
121          exportClass = statement.name.escapedText;
122        } else if (ts.isExportAssignment(statement)) {
123          exportClass = statement.expression.escapedText;
124        }
125      });
126      return sourcefile;
127    };
128  };
129}
130
131function compareComponentApi(applicationApi, baseApi, callApisInApp, componentApiIndexSet, index) {
132  let applyApi = JSON.parse(JSON.stringify(baseApi));
133  applyApi.pos = applicationApi.callLocation;
134  if (applicationApi.moduleName.match(new RegExp(baseApi.className.replace(/Attribute|Interface/, ''), 'i')) &&
135    applicationApi.apiName === baseApi.methodName && !componentApiIndexSet.has(index)) {
136    applyApi.className = applicationApi.moduleName;
137    callApisInApp.push(applyApi);
138    componentApiIndexSet.add(index);
139  } else if (applicationApi.apiName === baseApi.methodName && baseApi.className === 'CommonMethod' &&
140    applicationApi.notes !== '比较API' && !componentApiIndexSet.has(index)) {
141    applyApi.className = applicationApi.moduleName;
142    applyApi.notes = 'CommonMethod';
143    callApisInApp.push(applyApi);
144    componentApiIndexSet.add(index);
145  } else if (applicationApi.notes === '比较API' && applicationApi.apiName === baseApi.methodName &&
146    baseApi.className.match(new RegExp(applicationApi.moduleName, 'i')) &&
147    baseApi.className !== 'CommonMethod' && !componentApiIndexSet.has(index)) {
148    callApisInApp.push(applyApi);
149    componentApiIndexSet.add(index);
150  }
151}
152
153function getAllApiFiles(files) {
154  readFile(path.resolve(__dirname, '../sdk'), files);
155}