• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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 ts from 'typescript';
17
18import {
19  COMPONENT_CONSTRUCTOR_ID,
20  COMPONENT_CONSTRUCTOR_PARENT,
21  COMPONENT_CONSTRUCTOR_PARAMS,
22  COMPONENT_CONSTRUCTOR_UPDATE_PARAMS,
23  COMPONENT_WATCH_FUNCTION,
24  BASE_COMPONENT_NAME,
25  INTERFACE_NAME_SUFFIX,
26  COMPONENT_CONSTRUCTOR_LOCALSTORAGE
27} from './pre_define';
28
29import {
30  localStorageLinkCollection,
31  localStoragePropCollection
32} from './validate_ui_syntax';
33
34export function getInitConstructor(members: ts.NodeArray<ts.Node>, parentComponentName: ts.Identifier
35  ): ts.ConstructorDeclaration {
36  let ctorNode: any = members.find(item => {
37    return ts.isConstructorDeclaration(item);
38  });
39  if (ctorNode) {
40    ctorNode = updateConstructor(ctorNode, [], [], true);
41  }
42  return initConstructorParams(ctorNode, parentComponentName);
43}
44
45export function updateConstructor(ctorNode: ts.ConstructorDeclaration,para: ts.ParameterDeclaration[],
46  addStatements: ts.Statement[], isSuper: boolean = false, isAdd: boolean = false,
47  parentComponentName?: ts.Identifier): ts.ConstructorDeclaration {
48  let modifyPara: ts.ParameterDeclaration[];
49  if (para && para.length) {
50    modifyPara = Array.from(ctorNode.parameters);
51    if (modifyPara) {
52      modifyPara.push(...para);
53    }
54  }
55  let modifyBody: ts.Statement[];
56  if (addStatements && addStatements.length && ctorNode) {
57    modifyBody = Array.from(ctorNode.body.statements);
58    if (modifyBody) {
59      if (isSuper) {
60        modifyBody.unshift(...addStatements);
61      } else {
62        modifyBody.push(...addStatements);
63      }
64    }
65  }
66  if (ctorNode) {
67    let ctorPara: ts.ParameterDeclaration[] | ts.NodeArray<ts.ParameterDeclaration> =
68      modifyPara || ctorNode.parameters;
69    if (isAdd) {
70      ctorPara = addParamsType(ctorNode, modifyPara, parentComponentName);
71    }
72    ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, ctorNode.decorators,
73      ctorNode.modifiers, modifyPara || ctorNode.parameters,
74      ts.factory.createBlock(modifyBody || ctorNode.body.statements, true));
75  }
76  return ctorNode;
77}
78
79function initConstructorParams(node: ts.ConstructorDeclaration, parentComponentName: ts.Identifier):
80  ts.ConstructorDeclaration {
81  if (!ts.isIdentifier(parentComponentName)) {
82    return;
83  }
84  const localStorageNum: number = localStorageLinkCollection.get(parentComponentName.getText()).size +
85    localStoragePropCollection.get(parentComponentName.getText()).size;
86  const paramNames: Set<string> = new Set([COMPONENT_CONSTRUCTOR_ID, COMPONENT_CONSTRUCTOR_PARENT,
87    COMPONENT_CONSTRUCTOR_PARAMS, localStorageNum ? COMPONENT_CONSTRUCTOR_LOCALSTORAGE :
88      COMPONENT_CONSTRUCTOR_PARAMS]);
89  const newParameters: ts.ParameterDeclaration[] = Array.from(node.parameters);
90  if (newParameters.length !== 0) {
91    // @ts-ignore
92    newParameters.splice(0, newParameters.length);
93  }
94  paramNames.forEach((paramName: string) => {
95    // @ts-ignore
96    newParameters.push(ts.factory.createParameterDeclaration(undefined, undefined, undefined,
97      ts.factory.createIdentifier(paramName), undefined, undefined, undefined));
98  });
99
100  return ts.factory.updateConstructorDeclaration(node, undefined, node.modifiers, newParameters,
101    node.body);
102}
103
104function addParamsType(ctorNode: ts.ConstructorDeclaration, modifyPara: ts.ParameterDeclaration[],
105  parentComponentName: ts.Identifier): ts.ParameterDeclaration[] {
106  const tsPara: ts.ParameterDeclaration[] | ts.NodeArray<ts.ParameterDeclaration> =
107    modifyPara || ctorNode.parameters;
108  const newTSPara: ts.ParameterDeclaration[] = [];
109  tsPara.forEach((item) => {
110    let parameter: ts.ParameterDeclaration = item;
111    switch (item.name.escapedText) {
112      case COMPONENT_CONSTRUCTOR_ID:
113        parameter = ts.factory.updateParameterDeclaration(item, item.decorators, item.modifiers,
114          item.dotDotDotToken, item.name, item.questionToken,
115          ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), item.initializer);
116        break;
117      case COMPONENT_CONSTRUCTOR_PARENT:
118        parameter = ts.factory.createParameterDeclaration(item.decorators, item.modifiers,
119          item.dotDotDotToken, item.name, item.questionToken,
120          ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(BASE_COMPONENT_NAME), undefined),
121          item.initializer);
122        break;
123      case COMPONENT_CONSTRUCTOR_PARAMS:
124        parameter = ts.factory.updateParameterDeclaration(item, item.decorators, item.modifiers,
125          item.dotDotDotToken, item.name, item.questionToken,
126          ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
127            parentComponentName.getText() + INTERFACE_NAME_SUFFIX), undefined), item.initializer);
128        break;
129    }
130    newTSPara.push(parameter);
131  })
132  return newTSPara;
133}
134
135export function addConstructor(ctorNode: any, watchMap: Map<string, ts.Node>,
136  parentComponentName: ts.Identifier): ts.ConstructorDeclaration {
137  const watchStatements: ts.ExpressionStatement[] = [];
138  const localStorageNum: number = localStorageLinkCollection.get(parentComponentName.getText()).size +
139    localStoragePropCollection.get(parentComponentName.getText()).size;
140  watchMap.forEach((value, key) => {
141    const watchNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
142      ts.factory.createCallExpression(
143        ts.factory.createPropertyAccessExpression(
144          ts.factory.createThis(),
145          ts.factory.createIdentifier(COMPONENT_WATCH_FUNCTION)
146        ),
147        undefined,
148        [
149          ts.factory.createStringLiteral(key),
150          ts.isStringLiteral(value) ?
151            ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
152              ts.factory.createIdentifier(value.text)) : value as ts.PropertyAccessExpression
153        ]
154      ));
155    watchStatements.push(watchNode);
156  });
157  const callSuperStatement: ts.Statement = ts.factory.createExpressionStatement(
158    ts.factory.createCallExpression(ts.factory.createSuper(), undefined,
159      localStorageNum ?
160      [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID),
161        ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT),
162        ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE)] :
163        [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID),
164        ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)]
165    ));
166  const updateWithValueParamsStatement: ts.Statement = ts.factory.createExpressionStatement(
167    ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
168      ts.factory.createThis(), ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS)),
169    undefined, [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)]));
170  return updateConstructor(updateConstructor(ctorNode, [], [callSuperStatement], true), [],
171    [updateWithValueParamsStatement, ...watchStatements], false, true, parentComponentName);
172}
173