• 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 { SourceFile } 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
40/**
41 * assembly all sourceFile node info
42 * @param sourceFile
43 * @param fileName
44 * @returns
45 */
46export function getSourceFileAssembly(sourceFile: SourceFile, fileName: string): SourceFileEntity {
47  const importDeclarations: Array<ImportElementEntity> = [];
48  const moduleDeclarations: Array<ModuleBlockEntity> = [];
49  const typeAliasDeclarations: Array<TypeAliasEntity> = [];
50  const classDeclarations: Array<ClassEntity> = [];
51  const interfaceDeclarations: Array<InterfaceEntity> = [];
52  const enumDeclarations: Array<EnumEntity> = [];
53  let exportAssignment: Array<string> = [];
54  const staticMethods: Array<Array<StaticMethodEntity>> = [];
55  const exportDeclarations: Array<string> = [];
56  const functionDeclarations: Array<FunctionEntity> = [];
57
58  sourceFile.forEachChild(node => {
59    if (isImportDeclaration(node)) {
60      importDeclarations.push(getImportDeclaration(node, sourceFile));
61    } else if (isModuleDeclaration(node)) {
62      moduleDeclarations.push(getModuleDeclaration(node, sourceFile, fileName));
63    } else if (isTypeAliasDeclaration(node)) {
64      typeAliasDeclarations.push(getTypeAliasDeclaration(node, sourceFile));
65    } else if (isClassDeclaration(node)) {
66      let isDefaultExportClass = false;
67      if (node.modifiers !== undefined) {
68        node.modifiers.forEach(value => {
69          if (value.kind === SyntaxKind.DefaultKeyword) {
70            isDefaultExportClass = true;
71          }
72        });
73      }
74      if (isDefaultExportClass) {
75        const classDeclarationEntity = getClassDeclaration(node, sourceFile);
76        classDeclarations.push(classDeclarationEntity);
77        if (classDeclarationEntity.staticMethods.length > 0) {
78          staticMethods.push(classDeclarationEntity.staticMethods);
79        }
80      }
81    } else if (isInterfaceDeclaration(node)) {
82      interfaceDeclarations.push(getInterfaceDeclaration(node, sourceFile));
83    } else if (isExportAssignment(node)) {
84      exportAssignment = getExportAssignment(node, sourceFile);
85    } else if (isEnumDeclaration(node)) {
86      enumDeclarations.push(getEnumDeclaration(node, sourceFile));
87    } else if (isExportDeclaration(node)) {
88      exportDeclarations.push(sourceFile.text.substring(node.pos, node.end).trimStart().trimEnd());
89    } else if (isFunctionDeclaration(node)){
90      functionDeclarations.push(getFunctionDeclaration(node, sourceFile));
91    }
92    else {
93      if (node.kind !== SyntaxKind.EndOfFileToken && !isFunctionDeclaration(node) && !isVariableStatement(node)) {
94        console.log('--------------------------- uncaught sourceFile type start -----------------------');
95        console.log('fileName: ' + fileName);
96        console.log(node);
97        console.log('--------------------------- uncaught sourceFile type end -----------------------');
98      }
99    }
100  });
101
102  return {
103    importDeclarations: importDeclarations,
104    moduleDeclarations: moduleDeclarations,
105    typeAliasDeclarations: typeAliasDeclarations,
106    classDeclarations: classDeclarations,
107    interfaceDeclarations: interfaceDeclarations,
108    enumDeclarations: enumDeclarations,
109    exportAssignment: exportAssignment,
110    staticMethods: staticMethods,
111    exportDeclarations: exportDeclarations,
112    functionDeclarations: functionDeclarations,
113  };
114}
115
116/**
117 * get default export class
118 * @param sourceFile
119 * @returns
120 */
121export function getDefaultExportClassDeclaration(sourceFile: SourceFile): Array<ClassEntity> {
122  const defaultExportClass: Array<ClassEntity> = [];
123  sourceFile.forEachChild(node => {
124    if (isClassDeclaration(node)) {
125      defaultExportClass.push(getClassDeclaration(node, sourceFile));
126    }
127  });
128  return defaultExportClass;
129}
130
131/**
132 * get sourceFile const variable statement
133 * @param sourceFile
134 * @returns
135 */
136export function getSourceFileVariableStatements(sourceFile: SourceFile): Array<Array<StatementEntity>> {
137  const variableStatements: Array<Array<StatementEntity>> = [];
138  sourceFile.forEachChild(node => {
139    if (isVariableStatement(node)) {
140      variableStatements.push(getVariableStatementDeclaration(node, sourceFile));
141    }
142  });
143  return variableStatements;
144}
145
146/**
147 * get sourcefile functions
148 * @param sourceFile
149 * @returns
150 */
151export function getSourceFileFunctions(sourceFile: SourceFile): Map<string, Array<FunctionEntity>> {
152  const functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>();
153  sourceFile.forEachChild(node => {
154    if (isFunctionDeclaration(node)) {
155      const functionEntity = getFunctionDeclaration(node, sourceFile);
156      if (functionDeclarations.get(functionEntity.functionName) !== undefined) {
157        functionDeclarations.get(functionEntity.functionName)?.push(functionEntity);
158      } else {
159        const functionArray: Array<FunctionEntity> = [];
160        functionArray.push(functionEntity);
161        functionDeclarations.set(functionEntity.functionName, functionArray);
162      }
163    }
164  });
165  return functionDeclarations;
166}
167
168export interface SourceFileEntity {
169  importDeclarations: Array<ImportElementEntity>,
170  moduleDeclarations: Array<ModuleBlockEntity>,
171  typeAliasDeclarations: Array<TypeAliasEntity>,
172  classDeclarations: Array<ClassEntity>,
173  interfaceDeclarations: Array<InterfaceEntity>,
174  enumDeclarations: Array<EnumEntity>,
175  exportAssignment: Array<string>,
176  staticMethods: Array<Array<StaticMethodEntity>>,
177  exportDeclarations: Array<string>,
178  functionDeclarations: Array<FunctionEntity>
179}
180