• 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_CONSTRUCTOR_INITIAL_PARAMS,
24  COMPONENT_WATCH_FUNCTION,
25  BASE_COMPONENT_NAME,
26  INTERFACE_NAME_SUFFIX,
27  COMPONENT_CONSTRUCTOR_LOCALSTORAGE,
28  BASE_COMPONENT_NAME_PU,
29  COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU,
30  COMPONENT_CONSTRUCTOR_LOCALSTORAGE_TYPE_PU,
31  ELMTID
32} from './pre_define';
33
34import {
35  localStorageLinkCollection,
36  localStoragePropCollection
37} from './validate_ui_syntax';
38
39import { partialUpdateConfig } from '../main';
40
41export function getInitConstructor(members: ts.NodeArray<ts.Node>, parentComponentName: ts.Identifier
42): ts.ConstructorDeclaration {
43  let ctorNode: any = members.find(item => {
44    return ts.isConstructorDeclaration(item);
45  });
46  if (ctorNode) {
47    ctorNode = updateConstructor(ctorNode, [], [], true);
48  }
49  return initConstructorParams(ctorNode, parentComponentName);
50}
51
52export function updateConstructor(ctorNode: ts.ConstructorDeclaration, para: ts.ParameterDeclaration[],
53  addStatements: ts.Statement[], isSuper: boolean = false, isAdd: boolean = false,
54  parentComponentName?: ts.Identifier): ts.ConstructorDeclaration {
55  let modifyPara: ts.ParameterDeclaration[];
56  if (para && para.length) {
57    modifyPara = Array.from(ctorNode.parameters);
58    if (modifyPara) {
59      modifyPara.push(...para);
60    }
61  }
62  let modifyBody: ts.Statement[];
63  if (addStatements && addStatements.length && ctorNode) {
64    modifyBody = Array.from(ctorNode.body.statements);
65    if (modifyBody) {
66      if (isSuper) {
67        modifyBody.unshift(...addStatements);
68      } else {
69        modifyBody.push(...addStatements);
70      }
71    }
72  }
73  if (ctorNode) {
74    let ctorPara: ts.ParameterDeclaration[] | ts.NodeArray<ts.ParameterDeclaration> =
75      modifyPara || ctorNode.parameters;
76    if (isAdd) {
77      ctorPara = addParamsType(ctorNode, modifyPara, parentComponentName);
78    }
79    ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, ctorNode.decorators,
80      ctorNode.modifiers, modifyPara || ctorNode.parameters,
81      ts.factory.createBlock(modifyBody || ctorNode.body.statements, true));
82  }
83  return ctorNode;
84}
85
86function initConstructorParams(node: ts.ConstructorDeclaration, parentComponentName: ts.Identifier):
87  ts.ConstructorDeclaration {
88  if (!ts.isIdentifier(parentComponentName)) {
89    return;
90  }
91  const paramNames: Set<string> = !partialUpdateConfig.partialUpdateMode ? new Set([
92    COMPONENT_CONSTRUCTOR_ID,
93    COMPONENT_CONSTRUCTOR_PARENT,
94    COMPONENT_CONSTRUCTOR_PARAMS,
95    COMPONENT_CONSTRUCTOR_LOCALSTORAGE
96  ]) : new Set([
97    COMPONENT_CONSTRUCTOR_PARENT,
98    COMPONENT_CONSTRUCTOR_PARAMS,
99    COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU,
100    ELMTID
101  ]);
102  const newParameters: ts.ParameterDeclaration[] = Array.from(node.parameters);
103  if (newParameters.length !== 0) {
104    // @ts-ignore
105    newParameters.splice(0, newParameters.length);
106  }
107  paramNames.forEach((paramName: string) => {
108    newParameters.push(ts.factory.createParameterDeclaration(undefined, undefined, undefined,
109      ts.factory.createIdentifier(paramName), undefined, undefined,
110      paramName === ELMTID ? ts.factory.createPrefixUnaryExpression(
111        ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral('1')) : undefined));
112  });
113
114  return ts.factory.updateConstructorDeclaration(node, undefined, node.modifiers, newParameters,
115    node.body);
116}
117
118function addParamsType(ctorNode: ts.ConstructorDeclaration, modifyPara: ts.ParameterDeclaration[],
119  parentComponentName: ts.Identifier): ts.ParameterDeclaration[] {
120  const tsPara: ts.ParameterDeclaration[] | ts.NodeArray<ts.ParameterDeclaration> =
121    modifyPara || ctorNode.parameters;
122  const newTSPara: ts.ParameterDeclaration[] = [];
123  tsPara.forEach((item) => {
124    let parameter: ts.ParameterDeclaration = item;
125    switch (item.name.escapedText) {
126      case COMPONENT_CONSTRUCTOR_ID:
127        parameter = ts.factory.updateParameterDeclaration(item, item.decorators, item.modifiers,
128          item.dotDotDotToken, item.name, item.questionToken,
129          ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), item.initializer);
130        break;
131      case COMPONENT_CONSTRUCTOR_PARENT:
132        parameter = ts.factory.createParameterDeclaration(item.decorators, item.modifiers,
133          item.dotDotDotToken, item.name, item.questionToken,
134          ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
135            !partialUpdateConfig.partialUpdateMode ? BASE_COMPONENT_NAME : BASE_COMPONENT_NAME_PU), undefined),
136          item.initializer);
137        break;
138      case COMPONENT_CONSTRUCTOR_PARAMS:
139        parameter = ts.factory.updateParameterDeclaration(item, item.decorators, item.modifiers,
140          item.dotDotDotToken, item.name, item.questionToken,
141          ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
142            parentComponentName.getText() + INTERFACE_NAME_SUFFIX), undefined), item.initializer);
143        break;
144      case COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU:
145        parameter = ts.factory.createParameterDeclaration(item.decorators, item.modifiers, item.dotDotDotToken,
146          item.name, ts.factory.createToken(ts.SyntaxKind.QuestionToken), ts.factory.createTypeReferenceNode(
147            ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE_TYPE_PU), undefined), item.initializer);
148        break;
149    }
150    newTSPara.push(parameter);
151  });
152  return newTSPara;
153}
154
155export function addConstructor(ctorNode: any, watchMap: Map<string, ts.Node>,
156  parentComponentName: ts.Identifier): ts.ConstructorDeclaration {
157  const watchStatements: ts.ExpressionStatement[] = [];
158  watchMap.forEach((value, key) => {
159    const watchNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
160      ts.factory.createCallExpression(
161        ts.factory.createPropertyAccessExpression(
162          ts.factory.createThis(),
163          ts.factory.createIdentifier(COMPONENT_WATCH_FUNCTION)
164        ),
165        undefined,
166        [
167          ts.factory.createStringLiteral(key),
168          ts.isStringLiteral(value) ?
169            ts.factory.createPropertyAccessExpression(ts.factory.createThis(),
170              ts.factory.createIdentifier(value.text)) : value as ts.PropertyAccessExpression
171        ]
172      ));
173    watchStatements.push(watchNode);
174  });
175  const callSuperStatement: ts.Statement = createCallSuperStatement();
176  const updateWithValueParamsStatement: ts.Statement = createUPdWithValStatement();
177  return updateConstructor(updateConstructor(ctorNode, [], [callSuperStatement], true), [],
178    [updateWithValueParamsStatement, ...watchStatements], false, true, parentComponentName);
179}
180
181function createCallSuperStatement(): ts.Statement {
182  if (!partialUpdateConfig.partialUpdateMode) {
183    return ts.factory.createExpressionStatement(ts.factory.createCallExpression(
184      ts.factory.createSuper(), undefined,
185      [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID),
186        ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT),
187        ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE)]));
188  } else {
189    return ts.factory.createExpressionStatement(
190      ts.factory.createCallExpression(ts.factory.createSuper(), undefined,
191        [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT),
192          ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE_PU),
193          ts.factory.createIdentifier(ELMTID)]));
194  }
195}
196
197function createUPdWithValStatement(): ts.Statement {
198  return ts.factory.createExpressionStatement(
199    ts.factory.createCallExpression(
200      ts.factory.createPropertyAccessExpression(
201        ts.factory.createThis(),
202        ts.factory.createIdentifier(
203          !partialUpdateConfig.partialUpdateMode ?
204            COMPONENT_CONSTRUCTOR_UPDATE_PARAMS : COMPONENT_CONSTRUCTOR_INITIAL_PARAMS
205        )
206      ),
207      undefined,
208      [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARAMS)]
209    )
210  );
211}