• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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
16import { SourceFile, SyntaxKind } from 'typescript';
17import { firstCharacterToUppercase } from '../common/commonUtils';
18import { ModuleBlockEntity } from '../declaration-node/moduleDeclaration';
19import {
20  getDefaultExportClassDeclaration, getSourceFileFunctions,
21  getSourceFileVariableStatements
22} from '../declaration-node/sourceFileElementsAssemply';
23import { generateClassDeclaration } from './generateClassDeclaration';
24import { generateCommonFunction } from './generateCommonFunction';
25import { generateEnumDeclaration } from './generateEnumDeclaration';
26import { generateImportEqual } from './generateImportEqual';
27import { addToIndexArray } from './generateIndex';
28import { generateInterfaceDeclaration } from './generateInterfaceDeclaration';
29import { generateStaticFunction } from './generateStaticFunction';
30import { addToSystemIndexArray } from './generateSystemIndex';
31import { generateTypeAliasDeclaration } from './generateTypeAlias';
32import { generateVariableStatementDelcatation } from './generateVariableStatementDeclaration';
33
34/**
35 * generate declare
36 * @param rootName
37 * @param moduleEntity
38 * @param sourceFile
39 * @param filename
40 * @returns
41 */
42export function generateModuleDeclaration(rootName: string, moduleEntity: ModuleBlockEntity, sourceFile: SourceFile, filename: string): string {
43  const moduleName = moduleEntity.moduleName;
44  const mockNameArr = filename.split('_');
45  const mockName = mockNameArr[mockNameArr.length - 1];
46  let moduleBody = `export function mock${firstCharacterToUppercase(mockName)}() {\n`;
47  addToIndexArray({ fileName: filename, mockFunctionName: `mock${firstCharacterToUppercase(mockName)}` });
48  let outBody = '';
49  const defaultExportClass = getDefaultExportClassDeclaration(sourceFile);
50
51  if (defaultExportClass.length > 0) {
52    defaultExportClass.forEach(value => {
53      if (value.exportModifiers.includes(SyntaxKind.DefaultKeyword) && value.exportModifiers.includes(SyntaxKind.ExportKeyword)) {
54        if (filename.startsWith('system_')) {
55          const mockNameArr = filename.split('_');
56          const mockName = mockNameArr[mockNameArr.length - 1];
57          addToSystemIndexArray({
58            filename: filename,
59            mockFunctionName: `mock${firstCharacterToUppercase(mockName)}`
60          });
61
62          moduleBody += `global.systemplugin.${mockName} = {`;
63          if (value.staticMethods.length > 0) {
64            let staticMethodBody = '';
65            value.staticMethods.forEach(val => {
66              staticMethodBody += generateStaticFunction(val, true, sourceFile) + '\n';
67            });
68            moduleBody += staticMethodBody;
69          }
70          moduleBody += '}';
71        } else {
72          outBody += generateClassDeclaration('', value, false, '', filename, sourceFile, false);
73        }
74      }
75    });
76  }
77
78  if (moduleEntity.typeAliasDeclarations.length > 0) {
79    moduleEntity.typeAliasDeclarations.forEach(value => {
80      outBody += generateTypeAliasDeclaration(value, true) + '\n';
81    });
82  }
83
84  if (moduleEntity.moduleImportEquaqls.length > 0) {
85    moduleEntity.moduleImportEquaqls.forEach(value => {
86      outBody += generateImportEqual(value) + '\n';
87    });
88  }
89
90  if (moduleEntity.classDeclarations.length > 0) {
91    moduleEntity.classDeclarations.forEach(value => {
92      if (value.exportModifiers.length > 0 && value.exportModifiers.includes(SyntaxKind.ExportKeyword)) {
93        outBody += generateClassDeclaration(moduleName, value, false, '', '', sourceFile, false) + '\n';
94      } else {
95        moduleBody += '\t' + generateClassDeclaration(moduleName, value, false, '', '', sourceFile, true) + '\n';
96      }
97    });
98  }
99
100  if (moduleEntity.interfaceDeclarations.length > 0) {
101    moduleEntity.interfaceDeclarations.forEach(value => {
102      if (value.exportModifiers.length > 0) {
103        outBody += generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + ';\n';
104      } else {
105        moduleBody += '\t' + generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + ';\n';
106      }
107    });
108  }
109
110  if (moduleEntity.enumDeclarations.length > 0) {
111    moduleEntity.enumDeclarations.forEach(value => {
112      if (value.exportModifiers.length > 0) {
113        outBody += generateEnumDeclaration(moduleName, value) + '\n';
114      } else {
115        moduleBody += '\t' + generateEnumDeclaration(moduleName, value) + '\n';
116      }
117    });
118  }
119
120  if (moduleEntity.moduleDeclarations.length > 0) {
121    moduleEntity.moduleDeclarations.forEach(value => {
122      moduleBody += generateInnerModule(value, sourceFile) + '\n';
123    });
124  }
125
126  let functionBody = '';
127  if (moduleEntity.functionDeclarations.size > 0) {
128    moduleEntity.functionDeclarations.forEach(value => {
129      functionBody += '\t' + generateCommonFunction(moduleName, value, sourceFile) + '\n';
130    });
131  }
132
133  moduleBody += '\t' + `const ${moduleName} = {`;
134  if (moduleEntity.variableStatements.length > 0) {
135    moduleEntity.variableStatements.forEach(value => {
136      value.forEach(val => {
137        moduleBody += generateVariableStatementDelcatation(val) + '\n';
138      });
139    });
140  }
141
142  const sourceFileFunctions = getSourceFileFunctions(sourceFile);
143  let sourceFileFunctionBody = '';
144  if (sourceFileFunctions.size > 0) {
145    sourceFileFunctions.forEach(value => {
146      sourceFileFunctionBody += generateCommonFunction(moduleName, value, sourceFile);
147    });
148  }
149
150  const sourceFileVariableStatements = getSourceFileVariableStatements(sourceFile);
151  let sourceFileStatementBody = '';
152  if (sourceFileVariableStatements.length > 0) {
153    sourceFileVariableStatements.forEach(value => {
154      value.forEach(val => {
155        sourceFileStatementBody += generateVariableStatementDelcatation(val);
156      });
157    });
158  }
159
160  moduleBody += sourceFileFunctionBody + '\n';
161  moduleBody += sourceFileStatementBody + '\n';
162  moduleBody += functionBody + '\n';
163
164  const exports = getModuleExportElements(moduleEntity);
165  let exportString = '';
166  exports.forEach(value => {
167    exportString += `${value.name}: ${value.name},\n`;
168  });
169  if (exportString !== '') {
170    moduleBody += '\t' + exportString;
171  }
172
173  moduleBody += '\t};';
174  moduleBody += `\n\treturn ${moduleName};}\n`;
175  moduleBody += outBody;
176  return moduleBody;
177}
178
179/**
180 * generate inner module
181 * @param moduleEntity
182 * @param sourceFile
183 * @returns
184 */
185function generateInnerModule(moduleEntity: ModuleBlockEntity, sourceFile: SourceFile): string {
186  const moduleName = moduleEntity.moduleName;
187  let innerModuleBody = `const ${moduleName} = {`;
188
189  if (moduleEntity.typeAliasDeclarations.length > 0) {
190    moduleEntity.typeAliasDeclarations.forEach(value => {
191      innerModuleBody += generateTypeAliasDeclaration(value, true) + '\n';
192    });
193  }
194
195  if (moduleEntity.moduleImportEquaqls.length > 0) {
196    moduleEntity.moduleImportEquaqls.forEach(value => {
197      innerModuleBody += generateImportEqual(value) + '\n';
198    });
199  }
200
201  if (moduleEntity.interfaceDeclarations.length > 0) {
202    moduleEntity.interfaceDeclarations.forEach(value => {
203      innerModuleBody += generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + '\n';
204    });
205  }
206
207  if (moduleEntity.enumDeclarations.length > 0) {
208    moduleEntity.enumDeclarations.forEach(value => {
209      innerModuleBody += generateEnumDeclaration(moduleName, value) + '\n';
210    });
211  }
212
213  let functionBody = '';
214  if (moduleEntity.functionDeclarations.size > 0) {
215    moduleEntity.functionDeclarations.forEach(value => {
216      functionBody += generateCommonFunction(moduleName, value, sourceFile) + '\n';
217    });
218  }
219
220  if (moduleEntity.variableStatements.length > 0) {
221    moduleEntity.variableStatements.forEach(value => {
222      value.forEach(val => {
223        innerModuleBody += generateVariableStatementDelcatation(val) + '\n';
224      });
225    });
226  }
227  innerModuleBody += functionBody + '\n';
228
229  const exports = getModuleExportElements(moduleEntity);
230  let exportString = '';
231  exports.forEach(value => {
232    exportString += `${value.name}: ${value.name},\n`;
233  });
234  if (exportString !== '') {
235    innerModuleBody += '\t' + exportString;
236  }
237  innerModuleBody += '\t};';
238  return innerModuleBody;
239}
240
241/**
242 * get all export elements
243 * @param moduleEntity
244 * @returns
245 */
246function getModuleExportElements(moduleEntity: ModuleBlockEntity): Array<ModuleExportEntity> {
247  const exportElements: Array<ModuleExportEntity> = [];
248  if (moduleEntity.classDeclarations.length > 0) {
249    moduleEntity.classDeclarations.forEach(value => {
250      exportElements.push({ name: firstCharacterToUppercase(value.className), type: 'class' });
251    });
252  }
253
254  if (moduleEntity.interfaceDeclarations.length > 0) {
255    moduleEntity.interfaceDeclarations.forEach(value => {
256      exportElements.push({ name: value.interfaceName, type: 'interface' });
257    });
258  }
259
260  if (moduleEntity.enumDeclarations.length > 0) {
261    moduleEntity.enumDeclarations.forEach(value => {
262      exportElements.push({ name: value.enumName, type: 'enum' });
263    });
264  }
265
266  if (moduleEntity.moduleDeclarations.length > 0) {
267    moduleEntity.moduleDeclarations.forEach(value => {
268      exportElements.push({ name: value.moduleName, type: 'module' });
269    });
270  }
271
272  if (moduleEntity.typeAliasDeclarations.length > 0) {
273    moduleEntity.typeAliasDeclarations.forEach(value => {
274      exportElements.push({ name: value.typeAliasName, type: 'type' });
275    });
276  }
277  return exportElements;
278}
279
280interface ModuleExportEntity {
281  type: string,
282  name: string
283}
284