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  isCallSignatureDeclaration,
18  isConstructorDeclaration,
19  isHeritageClause,
20  isIndexSignatureDeclaration,
21  isMethodSignature,
22  isPropertySignature,
23  isTypeParameterDeclaration
24} from 'typescript';
25import type { InterfaceDeclaration, SourceFile } from 'typescript';
26import { getExportKeyword } from '../common/commonUtils';
27import { getCallSignatureDeclaration } from './callSignatureDeclaration';
28import type { CallSignatureEntity } from './callSignatureDeclaration';
29import { getConstructorDeclaration } from './constructorDeclaration';
30import type { ConstructorEntity } from './constructorDeclaration';
31import { getHeritageClauseDeclaration } from './heritageClauseDeclaration';
32import type { HeritageClauseEntity } from './heritageClauseDeclaration';
33import { getIndexSignatureDeclaration } from './indexSignatureDeclaration';
34import type { IndexSignatureEntity } from './indexSignatureDeclaration';
35import { getMethodSignatureDeclaration } from './methodSignatureDeclaration';
36import type { MethodSignatureEntity } from './methodSignatureDeclaration';
37import { getPropertySignatureDeclaration } from './propertySignatureDeclaration';
38import type { PropertySignatureEntity } from './propertySignatureDeclaration';
39import { getTypeParameterDeclaration } from './typeParameterDeclaration';
40import type { TypeParameterEntity } from './typeParameterDeclaration';
41
42interface SubstepInterfaceEntity {
43  interfaceName: string;
44  heritageClauses: Array<HeritageClauseEntity>;
45  typeParameters: Array<TypeParameterEntity>;
46  interfaceConstructors: Array<Array<ConstructorEntity>>;
47  interfaceMethodSignature: Map<string, Array<MethodSignatureEntity>>;
48  interfacePropertySignatures: Array<PropertySignatureEntity>;
49  callSignatures: Array<CallSignatureEntity>;
50  indexSignature: Array<IndexSignatureEntity>;
51}
52
53interface SubstepGetClassparam {
54  interfaceNode: InterfaceDeclaration;
55  sourceFile: SourceFile;
56  heritageClauses: Array<HeritageClauseEntity>;
57}
58export interface InterfaceEntity {
59  interfaceName: string;
60  typeParameters: Array<TypeParameterEntity>;
61  heritageClauses: Array<HeritageClauseEntity>;
62  interfaceConstructors: Array<Array<ConstructorEntity>>;
63  interfaceMethodSignature: Map<string, Array<MethodSignatureEntity>>;
64  interfacePropertySignatures: Array<PropertySignatureEntity>;
65  callSignatures: Array<CallSignatureEntity>;
66  exportModifiers: Array<number>;
67  indexSignature: Array<IndexSignatureEntity>;
68}
69
70/**
71 * get interface info
72 * @param interfaceNode
73 * @param sourceFile
74 * @returns
75 */
76export function getInterfaceDeclaration(interfaceNode: InterfaceDeclaration, sourceFile: SourceFile): InterfaceEntity {
77  let exportModifiers: Array<number> = [];
78  if (interfaceNode.modifiers !== undefined) {
79    exportModifiers = getExportKeyword(interfaceNode.modifiers);
80  }
81
82  const heritageClauses: Array<HeritageClauseEntity> = [];
83
84  if (interfaceNode.heritageClauses !== undefined) {
85    interfaceNode.heritageClauses.forEach(value => {
86      heritageClauses.push(getHeritageClauseDeclaration(value, sourceFile));
87    });
88  }
89  const SubstepInterfaceEntitys: SubstepInterfaceEntity = substepGetInterface({
90    interfaceNode,
91    sourceFile,
92    heritageClauses
93  });
94
95  return {
96    ...SubstepInterfaceEntitys,
97    exportModifiers
98  };
99}
100
101/**
102 * get some interface info
103 * @param substepGetClassparam
104 * @returns
105 */
106function substepGetInterface(substepGetClassparam: SubstepGetClassparam): SubstepInterfaceEntity {
107  const { interfaceNode, sourceFile, heritageClauses } = substepGetClassparam;
108  const interfaceName = interfaceNode.name.escapedText.toString();
109  const interfaceConstructors: Array<Array<ConstructorEntity>> = [];
110  const interfaceMethodSignature: Map<string, Array<MethodSignatureEntity>> = new Map<
111    string, Array<MethodSignatureEntity>
112  >();
113  const interfacePropertySignatures: Array<PropertySignatureEntity> = [];
114  const callSignature: Array<CallSignatureEntity> = [];
115  const typeParameters: Array<TypeParameterEntity> = [];
116  const indexSignature: Array<IndexSignatureEntity> = [];
117  interfaceNode.members.forEach(value => {
118    if (isPropertySignature(value)) {
119      interfacePropertySignatures.push(getPropertySignatureDeclaration(value, sourceFile));
120    } else if (isMethodSignature(value)) {
121      const methodSignature = getMethodSignatureDeclaration(value, sourceFile);
122      if (interfaceMethodSignature.get(methodSignature.functionName) !== undefined) {
123        interfaceMethodSignature.get(methodSignature.functionName)?.push(methodSignature);
124      } else {
125        const methodSignatureArray: Array<MethodSignatureEntity> = [];
126        methodSignatureArray.push(methodSignature);
127        interfaceMethodSignature.set(methodSignature.functionName, methodSignatureArray);
128      }
129    } else if (isHeritageClause(value)) {
130      heritageClauses.push(getHeritageClauseDeclaration(value, sourceFile));
131    } else if (isConstructorDeclaration(value)) {
132      interfaceConstructors.push(getConstructorDeclaration(value, sourceFile));
133    } else if (isCallSignatureDeclaration(value)) {
134      callSignature.push(getCallSignatureDeclaration(value, sourceFile));
135    } else if (isTypeParameterDeclaration(value)) {
136      typeParameters.push(getTypeParameterDeclaration(value, sourceFile));
137    } else if (isIndexSignatureDeclaration(value)) {
138      indexSignature.push(getIndexSignatureDeclaration(value, sourceFile));
139    } else {
140      console.log('--------------------------- uncaught interface type start -----------------------');
141      console.log('interfaceName: ' + interfaceName);
142      console.log(value);
143      console.log('--------------------------- uncaught interface type end -----------------------');
144    }
145  });
146  return {
147    interfaceName,
148    typeParameters,
149    heritageClauses,
150    interfaceConstructors,
151    interfaceMethodSignature,
152    interfacePropertySignatures,
153    callSignatures: callSignature,
154    indexSignature
155  };
156}
157