• 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
16import {
17  isClassDeclaration, isEnumDeclaration, isExportAssignment, isExportDeclaration, isFunctionDeclaration,
18  isImportDeclaration, isInterfaceDeclaration, isModuleDeclaration, isTypeAliasDeclaration, isVariableStatement,
19  SyntaxKind
20} from 'typescript';
21import type { Node, SourceFile, ClassDeclaration, FunctionDeclaration } from 'typescript';
22import { getClassDeclaration } from './classDeclaration';
23import type { ClassEntity } from './classDeclaration';
24import { getEnumDeclaration } from './enumDeclaration';
25import type { EnumEntity } from './enumDeclaration';
26import { getFunctionDeclaration } from './functionDeclaration';
27import type { FunctionEntity } from './functionDeclaration';
28import { getExportAssignment, getImportDeclaration } from './importAndExportDeclaration';
29import type { ImportElementEntity } from './importAndExportDeclaration';
30import { getInterfaceDeclaration } from './interfaceDeclaration';
31import type { InterfaceEntity } from './interfaceDeclaration';
32import type { StaticMethodEntity } from './methodDeclaration';
33import { getModuleDeclaration } from './moduleDeclaration';
34import type { ModuleBlockEntity } from './moduleDeclaration';
35import { getTypeAliasDeclaration } from './typeAliasDeclaration';
36import type { TypeAliasEntity } from './typeAliasDeclaration';
37import { getVariableStatementDeclaration } from './variableStatementResolve';
38import type { StatementEntity } from './variableStatementResolve';
39
40interface SubstepClassParams {
41  node: ClassDeclaration,
42  sourceFile: SourceFile,
43  classDeclarations: Array<ClassEntity>,
44  staticMethods: Array<Array<StaticMethodEntity>>,
45}
46
47interface SubstepFuntionParams {
48  node: FunctionDeclaration,
49  sourceFile: SourceFile,
50  functionDeclarations: Map<string, Array<FunctionEntity>>
51}
52
53export interface SourceFileEntity {
54  importDeclarations: Array<ImportElementEntity>,
55  moduleDeclarations: Array<ModuleBlockEntity>,
56  typeAliasDeclarations: Array<TypeAliasEntity>,
57  classDeclarations: Array<ClassEntity>,
58  interfaceDeclarations: Array<InterfaceEntity>,
59  enumDeclarations: Array<EnumEntity>,
60  exportAssignment: Array<string>,
61  staticMethods: Array<Array<StaticMethodEntity>>,
62  exportDeclarations: Array<string>,
63  functionDeclarations: Map<string, Array<FunctionEntity>>
64}
65
66/**
67 * assembly all sourceFile node info
68 * @param sourceFile
69 * @param fileName
70 * @returns
71 */
72export function getSourceFileAssembly(sourceFile: SourceFile, fileName: string): SourceFileEntity {
73  const importDeclarations: Array<ImportElementEntity> = [];
74  const moduleDeclarations: Array<ModuleBlockEntity> = [];
75  const typeAliasDeclarations: Array<TypeAliasEntity> = [];
76  let classDeclarations: Array<ClassEntity> = [];
77  const interfaceDeclarations: Array<InterfaceEntity> = [];
78  const enumDeclarations: Array<EnumEntity> = [];
79  let exportAssignment: Array<string> = [];
80  let staticMethods: Array<Array<StaticMethodEntity>> = [];
81  const exportDeclarations: Array<string> = [];
82  let functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>();
83  sourceFile.forEachChild(node => {
84    if (isImportDeclaration(node)) {
85      importDeclarations.push(getImportDeclaration(node, sourceFile));
86    } else if (isModuleDeclaration(node)) {
87      moduleDeclarations.push(getModuleDeclaration(node, sourceFile, fileName));
88    } else if (isTypeAliasDeclaration(node)) {
89      typeAliasDeclarations.push(getTypeAliasDeclaration(node, sourceFile));
90    } else if (isClassDeclaration(node)) {
91      const substepClassBack = substepClass({ node, sourceFile, classDeclarations, staticMethods });
92      classDeclarations = substepClassBack.classDeclarations;
93      staticMethods = substepClassBack.staticMethods;
94    } else if (isInterfaceDeclaration(node)) {
95      interfaceDeclarations.push(getInterfaceDeclaration(node, sourceFile));
96    } else if (isExportAssignment(node)) {
97      exportAssignment = getExportAssignment(node, sourceFile);
98    } else if (isEnumDeclaration(node)) {
99      enumDeclarations.push(getEnumDeclaration(node, sourceFile));
100    } else if (isExportDeclaration(node)) {
101      exportDeclarations.push(sourceFile.text.substring(node.pos, node.end).trimStart().trimEnd());
102    } else if (isFunctionDeclaration(node)) {
103      const classParams = substepFunction({ node, sourceFile, functionDeclarations });
104      functionDeclarations = classParams.functionDeclarations;
105    } else {
106      substepConsole(node, fileName);
107    }
108  });
109  return {
110    importDeclarations,
111    moduleDeclarations,
112    typeAliasDeclarations,
113    classDeclarations,
114    interfaceDeclarations,
115    enumDeclarations,
116    exportAssignment,
117    staticMethods,
118    exportDeclarations,
119    functionDeclarations
120  };
121}
122
123/**
124 * get default export class
125 * @param sourceFile
126 * @returns
127 */
128export function getDefaultExportClassDeclaration(sourceFile: SourceFile): Array<ClassEntity> {
129  const defaultExportClass: Array<ClassEntity> = [];
130  sourceFile.forEachChild(node => {
131    if (isClassDeclaration(node)) {
132      defaultExportClass.push(getClassDeclaration(node, sourceFile));
133    }
134  });
135  return defaultExportClass;
136}
137
138/**
139 * get sourceFile const variable statement
140 * @param sourceFile
141 * @returns
142 */
143export function getSourceFileVariableStatements(sourceFile: SourceFile): Array<Array<StatementEntity>> {
144  const variableStatements: Array<Array<StatementEntity>> = [];
145  sourceFile.forEachChild(node => {
146    if (isVariableStatement(node)) {
147      variableStatements.push(getVariableStatementDeclaration(node, sourceFile));
148    }
149  });
150  return variableStatements;
151}
152
153/**
154 * get sourcefile functions
155 * @param sourceFile
156 * @returns
157 */
158export function getSourceFileFunctions(sourceFile: SourceFile): Map<string, Array<FunctionEntity>> {
159  const functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>();
160  sourceFile.forEachChild(node => {
161    if (isFunctionDeclaration(node)) {
162      const functionEntity = getFunctionDeclaration(node, sourceFile);
163      if (functionDeclarations.get(functionEntity.functionName) !== undefined) {
164        functionDeclarations.get(functionEntity.functionName)?.push(functionEntity);
165      } else {
166        const functionArray: Array<FunctionEntity> = [];
167        functionArray.push(functionEntity);
168        functionDeclarations.set(functionEntity.functionName, functionArray);
169      }
170    }
171  });
172  return functionDeclarations;
173}
174
175/**
176 * assembly some sourceFile node info
177 * @param substepClassParams
178 * @returns
179 */
180function substepClass(substepClassParams: SubstepClassParams): SubstepClassParams {
181  let isDefaultExportClass = false;
182  if (substepClassParams.node.modifiers !== undefined) {
183    substepClassParams.node.modifiers.forEach(value => {
184      if (value.kind === SyntaxKind.DefaultKeyword) {
185        isDefaultExportClass = true;
186      }
187    });
188  }
189  if (isDefaultExportClass) {
190    const classDeclarationEntity = getClassDeclaration(substepClassParams.node, substepClassParams.sourceFile);
191    substepClassParams.classDeclarations.push(classDeclarationEntity);
192    if (classDeclarationEntity.staticMethods.length > 0) {
193      substepClassParams.staticMethods.push(classDeclarationEntity.staticMethods);
194    }
195  }
196  return substepClassParams;
197}
198
199/**
200 * assembly some sourceFile node info
201 * @param substepClassParams
202 * @returns
203 */
204function substepFunction(substepClassParams: SubstepFuntionParams): SubstepFuntionParams {
205  const functionEntity = getFunctionDeclaration(substepClassParams.node, substepClassParams.sourceFile);
206  if (substepClassParams.functionDeclarations.get(functionEntity.functionName) !== undefined) {
207    substepClassParams.functionDeclarations.get(functionEntity.functionName)?.push(functionEntity);
208  } else {
209    const functionArray: Array<FunctionEntity> = [];
210    functionArray.push(functionEntity);
211    substepClassParams.functionDeclarations.set(functionEntity.functionName, functionArray);
212  }
213  return substepClassParams;
214}
215
216/**
217 * assembly some sourceFile node info
218 * @param substepClassParams
219 * @returns
220 */
221function substepConsole(node: Node, fileName: string):void {
222  if (node.kind !== SyntaxKind.EndOfFileToken && !isFunctionDeclaration(node) && !isVariableStatement(node)) {
223    console.log('--------------------------- uncaught sourceFile type start -----------------------');
224    console.log('fileName: ' + fileName);
225    console.log(node);
226    console.log('--------------------------- uncaught sourceFile type end -----------------------');
227  }
228  return;
229}
230