idlize
211 строк · 8.9 Кб
1/*
2* Copyright (c) 2022-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 * as ts from 'ohos-typescript'
17import { AbstractVisitor } from './AbstractVisitor'
18import { Importer } from './Importer'
19import { ExtendDecorator, StylesDecorator, typeParameterExtendsType, adaptorComponentName, AnimatableExtendDecorator, getAnnotationArgument, prependMemoComment, dropStylesLike, asString, ArkCommonMethod, T_TypeParameter, Instance, CommonInstance, extendsLikeFunctionName } from './utils'
20import { Any, getDecorator, hasDecorator, id, parameter } from './ApiUtils'
21
22function rewriteStyles(node: ts.FunctionDeclaration, importer: Importer): ts.FunctionDeclaration {
23const firstParameter = parameter(
24CommonInstance,
25//ts.factory.createTypeReferenceNode(T_TypeParameter),
26Any()
27)
28
29const singleExpressionStatement = node.body?.statements?.[0]
30if (!singleExpressionStatement) return node
31if (!ts.isExpressionStatement(singleExpressionStatement)) return node
32
33const declaration = ts.factory.createFunctionDeclaration(
34// @Styles dropped as "Illegal decorator" because of create instead of update
35// We could not make updateFunctionDecl() remove the illegal decorators
36node.modifiers,
37node.asteriskToken,
38node.name,
39[typeParameterExtendsType(
40T_TypeParameter,
41importer.withArkuiCommonImport(ArkCommonMethod),
42[T_TypeParameter]
43)],
44[firstParameter, ...node.parameters],
45ts.factory.createTypeReferenceNode(T_TypeParameter),
46ts.factory.createBlock([
47ts.factory.createReturnStatement(singleExpressionStatement.expression)
48], true)
49)
50
51return importer.__isArkoalaImplementation ? prependMemoComment(declaration) : declaration
52}
53
54function rewriteStylesMethod(node: ts.MethodDeclaration, importer: Importer): ts.MethodDeclaration {
55const firstParameter = parameter(
56CommonInstance,
57//ts.factory.createTypeReferenceNode(T_TypeParameter),
58Any()
59)
60
61const singleExpressionStatement = node.body?.statements?.[0]
62if (!singleExpressionStatement) return node
63if (!ts.isExpressionStatement(singleExpressionStatement)) return node
64
65const declaration = ts.factory.createMethodDeclaration(
66dropStylesLike(node.modifiers),
67node.asteriskToken,
68node.name,
69node.questionToken,
70[typeParameterExtendsType(
71T_TypeParameter,
72importer.withArkuiCommonImport(ArkCommonMethod),
73[T_TypeParameter]
74)],
75[firstParameter, ...node.parameters],
76ts.factory.createTypeReferenceNode(T_TypeParameter),
77ts.factory.createBlock([
78ts.factory.createReturnStatement(singleExpressionStatement.expression)
79], true)
80)
81
82return importer.__isArkoalaImplementation ? prependMemoComment(declaration) : declaration
83}
84
85function rewriteExtend(node: ts.FunctionDeclaration, extendType: string, importer: Importer): ts.FunctionDeclaration {
86const firstParameter = parameter(
87extendType + Instance,
88//ts.factory.createTypeReferenceNode(T_TypeParameter),
89Any()
90)
91
92const singleExpressionStatement = node.body?.statements?.[0]
93if (!singleExpressionStatement) return node
94if (!ts.isExpressionStatement(singleExpressionStatement)) return node
95
96const declaration = ts.factory.createFunctionDeclaration(
97// @Extend dropped as "Illegal decorator" because of create instead of update
98// We could not make updateFunctionDecl() remove the illegal decorators
99node.modifiers,
100node.asteriskToken,
101id(extendsLikeFunctionName(ts.idText(node.name!), extendType)),
102[typeParameterExtendsType(
103T_TypeParameter,
104adaptorComponentName(extendType),
105[]
106)],
107[firstParameter, ...node.parameters],
108ts.factory.createTypeReferenceNode(adaptorComponentName(extendType)),
109ts.factory.createBlock([
110ts.factory.createReturnStatement(singleExpressionStatement.expression)
111], true)
112)
113return importer.__isArkoalaImplementation ? prependMemoComment(declaration) : declaration
114}
115
116function rewriteExtendMethod(node: ts.MethodDeclaration, extendType: string, importer: Importer): ts.MethodDeclaration {
117const firstParameter = parameter(
118extendType + Instance,
119//ts.factory.createTypeReferenceNode(T_TypeParameter),
120Any()
121)
122
123const singleExpressionStatement = node.body?.statements?.[0]
124if (!singleExpressionStatement) return node
125if (!ts.isExpressionStatement(singleExpressionStatement)) return node
126
127const declaration = ts.factory.updateMethodDeclaration(
128node,
129dropStylesLike(node.modifiers)?.concat(ts.factory.createToken(ts.SyntaxKind.StaticKeyword)),
130node.asteriskToken,
131id(extendsLikeFunctionName(ts.idText(node.name! as ts.Identifier), extendType)),
132node.questionToken,
133[typeParameterExtendsType(T_TypeParameter, adaptorComponentName(extendType), [])],
134[firstParameter, ...node.parameters],
135ts.factory.createTypeReferenceNode(adaptorComponentName(extendType)),
136ts.factory.createBlock([
137ts.factory.createReturnStatement(singleExpressionStatement.expression)
138], true)
139)
140return importer.__isArkoalaImplementation ? prependMemoComment(declaration) : declaration
141}
142
143export class ExtensionStylesTransformer extends AbstractVisitor {
144public stylesFunctions: string[] = []
145public extendFunctions: string[] = []
146public animatableExtendFunctions: string[] = []
147public stylesMethods: ts.Node[] = []
148public extendMethods: ts.Node[] = []
149public animatableExtendMethods: ts.Node[] = []
150
151constructor(
152sourceFile: ts.SourceFile,
153ctx: ts.TransformationContext,
154public typechecker: ts.TypeChecker,
155public importer: Importer
156) {
157super(sourceFile, ctx)
158}
159
160visitor(beforeChildren: ts.Node): ts.Node {
161const node = this.visitEachChild(beforeChildren)
162
163if (ts.isFunctionDeclaration(node)) {
164if (hasDecorator(node, StylesDecorator)) {
165this.stylesFunctions.push(ts.idText(node.name!))
166return rewriteStyles(node, this.importer)
167}
168if (hasDecorator(node, ExtendDecorator)) {
169const decorator = getDecorator(node, ExtendDecorator)!
170const extensibleType = ts.idText(getAnnotationArgument(decorator)!)
171this.extendFunctions.push(extendsLikeFunctionName(ts.idText(node.name!), extensibleType))
172return rewriteExtend(node, extensibleType, this.importer)
173}
174if (hasDecorator(node, AnimatableExtendDecorator)) {
175const decorator = getDecorator(node, AnimatableExtendDecorator)!
176const extensibleType = ts.idText(getAnnotationArgument(decorator)!)
177this.animatableExtendFunctions.push(extendsLikeFunctionName(ts.idText(node.name!), extensibleType))
178return rewriteExtend(node, extensibleType, this.importer)
179}
180}
181if (ts.isMethodDeclaration(node)) {
182if (hasDecorator(node, StylesDecorator)) {
183this.stylesMethods.push(ts.getOriginalNode(node))
184return rewriteStylesMethod(node, this.importer)
185}
186if (hasDecorator(node, ExtendDecorator)) {
187const decorator = getDecorator(node, ExtendDecorator)!
188const extensibleType = ts.idText(getAnnotationArgument(decorator)!)
189this.extendMethods.push(ts.getOriginalNode(node))
190return rewriteExtendMethod(node, extensibleType, this.importer)
191}
192if (hasDecorator(node, AnimatableExtendDecorator)) {
193const decorator = getDecorator(node, AnimatableExtendDecorator)!
194const extensibleType = ts.idText(getAnnotationArgument(decorator)!)
195this.animatableExtendMethods.push(ts.getOriginalNode(node))
196return rewriteExtendMethod(node, extensibleType, this.importer)
197}
198}
199if (ts.isIdentifier(node)) {
200if (ts.idText(node) == CommonInstance) {
201return id(CommonInstance)
202}
203if (ts.idText(node).endsWith(Instance)) {
204const instanceName = ts.idText(node).slice(0, -8)
205return id(instanceName + Instance)
206}
207}
208
209return node
210}
211}
212