idlize

Форк
0
218 строк · 9.7 Кб
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

16
import * as ts from 'ohos-typescript'
17
import * as fs from "fs"
18
import * as path from "path"
19
import { Importer } from './Importer'
20
import { StructTransformer } from './StructTransformer'
21
import { StyleTransformer, EtsFirstArgTransformer } from './StyleTransformer'
22
import { NameCollector } from './NameCollector'
23
import { CallTable, IssueTable, NameTable } from './utils'
24
import { LazyTransformer } from './LazyTransformer'
25
import { EntryTracker } from './EntryTracker'
26
import { filterOutDiagnostics } from './DiagnosticFilter'
27
import { DollarTransformer } from './DollarTransformer'
28
import { ExtensionStylesTransformer } from './ExtensionStylesTransformer'
29
import { NewTransformer } from './NewTransformer'
30
import { CustomBuilderTransformer } from './CustomBuilderTransformer'
31
import { CallTransformer } from './CallTransformer'
32
import { DebugVisitor } from './AbstractVisitor'
33
import { LegacyCallTransformer } from './LegacyCallTransformer'
34
import { AbilityTransformer } from './AbilityTransformer'
35

36
interface ArkToKoOptions {
37
    trace?: boolean
38
    source?: string
39
    destination?: string
40
    arkui?: string
41
    moduleInfo?: (moduleName: string) => any
42
}
43

44
function printSourceFile(sourceFile: ts.Node, source?: string, destination?: string, extension?: string) {
45
    if (!ts.isSourceFile(sourceFile)) throw new Error("Expected SourceFile, got: " + ts.SyntaxKind[sourceFile.kind])
46
    if (!destination) console.log("OUTPUT")
47

48
    const printer = ts.createPrinter({ removeComments: false })
49
    const text = printer.printNode(ts.EmitHint.SourceFile, sourceFile, sourceFile)
50
    if (destination) {
51
        const absoluteDestination = path.resolve(destination)
52
        const absoluteSource = source ? path.resolve(source) : path.resolve()
53
        const fileBaseName = path.basename(sourceFile.fileName, extension ?? ".ets")
54
        const fileDirName = path.dirname(sourceFile.fileName)
55
        const fileRelativeName = path.relative(absoluteSource, fileDirName)
56
        const dir = path.join(absoluteDestination, fileRelativeName)
57
        const file = path.join(dir, fileBaseName + ".ts")
58
        console.log("KOALA: " + path.normalize(file))
59
        fs.mkdirSync(dir, { recursive: true })
60
        fs.writeFileSync(file, text, 'utf8')
61
    } else {
62
        console.log(text)
63
    }
64
}
65

66
function updateRouterDestinationsFile(destination: string|undefined, entryTracker: EntryTracker) {
67
    const entries = Array.from(entryTracker.entries.entries())
68
    const comment = "// This file has been autogenerated. Do not update manually."
69
    const imports: string[] = []
70
    const uses: string[] = []
71
    entries.forEach((entry, i) => {
72
        const [file, component] = entry
73
        const alias = "Entry" + i
74
        imports.push(`import { ${component} as ${alias} } from \"./${file}\"`)
75
        uses.push(`\tconst __force${alias}Use = ${alias}`)
76
    })
77

78
    const registerFunction =`
79
export function registerRoutes() {
80
${uses.join("\n")}
81
}
82
`
83
    const text = comment + "\n" +
84
        imports.join("\n") + "\n" +
85
        registerFunction
86

87
    fs.writeFileSync(path.join(destination ?? ".", "__router_initialization.ts"), text)
88
}
89

90
function fileIsEligible(fileName: string): boolean {
91
    return path.extname(fileName) == ".ets"
92
}
93

94
function prepareDestination(destination: string | undefined) {
95
    if (destination) {
96
        fs.mkdirSync(destination, { recursive: true })
97
    }
98
}
99

100
export function arkExpandFile(
101
    sourceFile: ts.SourceFile,
102
    arkuiPackage: string,
103
    typeChecker: ts.TypeChecker,
104
    ctx: ts.TransformationContext,
105
    extras: ts.TransformerExtras | undefined,
106
    entryTracker: EntryTracker,
107
    moduleInfo?: (moduleName: string) => any
108
): ts.SourceFile {
109
        const importer = new Importer(arkuiPackage, moduleInfo)
110
        const nameTable = new NameTable()
111
        const issueTable = new IssueTable()
112
        const callTable = new CallTable()
113

114
        /* Uncomment to dump AST on entry */
115

116
        // const debug = new DebugVisitor(sourceFile, ctx)
117
        // debug.visitor(sourceFile)
118

119
        const callTransformer = new CallTransformer(sourceFile, ctx, typeChecker, callTable, importer)
120
        const lazyTransformer = new LazyTransformer(sourceFile, ctx, importer, callTable)
121
        const newTransformer = new NewTransformer(sourceFile, ctx, importer, issueTable)
122
        const customBuilderTransformer = new CustomBuilderTransformer(sourceFile, ctx, typeChecker, callTable)
123
        const legacyCallTransformer = new LegacyCallTransformer(sourceFile, ctx, importer, callTable)
124
        const extensionStylesTransformer = new ExtensionStylesTransformer(sourceFile, ctx, typeChecker, importer)
125
        const preprocessorTransformer = new EtsFirstArgTransformer(sourceFile, ctx, importer, callTable)
126
        const styleTransformer = new StyleTransformer(sourceFile, ctx, typeChecker, importer, extensionStylesTransformer, callTable)
127
        const structTransformer = new StructTransformer(sourceFile, ctx, typeChecker, importer, nameTable, entryTracker, callTable)
128
        const nameCollector = new NameCollector(sourceFile, ctx, nameTable, issueTable)
129
        const dollarTransformer = new DollarTransformer(sourceFile, ctx, nameTable)
130
        const abilityTransformer = new AbilityTransformer(sourceFile, ctx, importer)
131

132
        nameCollector.visitor(sourceFile)
133

134
        const translatedCalls = callTransformer.visitor(sourceFile) as ts.SourceFile
135
        const translatedDollar = dollarTransformer.visitor(translatedCalls) as ts.SourceFile
136
        const translatedLazy = lazyTransformer.visitor(translatedDollar) as ts.SourceFile
137
        const translatedNew = newTransformer.visitor(translatedLazy) as ts.SourceFile
138
        const translatedCustomBuilders = customBuilderTransformer.visitor(translatedNew) as ts.SourceFile
139
        const translatedLegacyCalls = legacyCallTransformer.visitor(translatedCustomBuilders) as ts.SourceFile
140
        const translatedStyleFunctions = extensionStylesTransformer.visitor(translatedLegacyCalls) as ts.SourceFile
141
        const preprocessedEts = preprocessorTransformer.visitor(translatedStyleFunctions) as ts.SourceFile
142
        const translatedStyle = styleTransformer.visitor(preprocessedEts) as ts.SourceFile
143
        const translatedStruct = structTransformer.visitor(translatedStyle) as ts.SourceFile
144
        const translatedAbility = abilityTransformer.visitor(translatedStruct) as ts.SourceFile
145

146
        const finalStage = translatedAbility
147

148
        filterOutDiagnostics(sourceFile, nameTable, issueTable, extras)
149

150
        return ts.factory.updateSourceFile(
151
            finalStage,
152
            [
153
                ...importer.generate(),
154
                ...finalStage.statements,
155
                // TODO: do we need a better way to obtain it?
156
                // ...structTranslator.entryCode
157
            ],
158
            finalStage.isDeclarationFile,
159
            finalStage.referencedFiles,
160
            finalStage.typeReferenceDirectives,
161
            finalStage.hasNoDefaultLib,
162
            finalStage.libReferenceDirectives
163
        )
164
}
165

166
export default function arkExpander(program: ts.Program, userPluginOptions: ArkToKoOptions, extras: ts.TransformerExtras) {
167
    const pluginOptions = {
168
        trace: userPluginOptions.trace ?? true,
169
        source: userPluginOptions.source ?? ".",
170
        destination: userPluginOptions.destination ?? "../generated",
171
        arkui: userPluginOptions.arkui ?? "@koalaui/arkui",
172
        moduleInfo: userPluginOptions.moduleInfo
173
    }
174
    const typeChecker = program.getTypeChecker()
175
    prepareDestination(pluginOptions.destination)
176
    const entryTracker = new EntryTracker(pluginOptions.source)
177

178
    return (ctx: ts.TransformationContext) => {
179
        return (sourceFile: ts.SourceFile) => {
180

181
            if (!fileIsEligible(sourceFile.fileName)) {
182
                console.log("Verbatim TS: ", sourceFile.fileName)
183
                printSourceFile(sourceFile, pluginOptions.source, pluginOptions.destination, ".ts")
184
                return sourceFile
185
            } else {
186
                console.log("ETS->TS: " + path.normalize(sourceFile.fileName))
187
            }
188

189
            let final = arkExpandFile(sourceFile, pluginOptions.arkui, typeChecker, ctx, extras, entryTracker, pluginOptions.moduleInfo)
190

191
            printSourceFile(final, pluginOptions.source, pluginOptions.destination)
192
            updateRouterDestinationsFile(pluginOptions.destination, entryTracker)
193

194
            // if (structTranslator.entryFile) {
195
            //     emitStartupFile(structTranslator.entryFile, pluginOptions.source!, pluginOptions.destination!)
196
            // }
197

198
            return final
199
        }
200
    }
201
}
202

203
export function makeEtsExpander(typeChecker: ts.TypeChecker, userPluginOptions: ArkToKoOptions, extras: ts.TransformerExtras) {
204
    const pluginOptions = {
205
        trace: userPluginOptions.trace ?? true,
206
        source: userPluginOptions.source ?? ".",
207
        destination: userPluginOptions.destination ?? "../generated",
208
        arkui: userPluginOptions.arkui ?? "@koalaui/arkui",
209
        moduleInfo: userPluginOptions.moduleInfo
210
    }
211
    const entryTracker = new EntryTracker(pluginOptions.source)
212

213
    return (ctx: ts.TransformationContext) => {
214
        return (sourceFile: ts.SourceFile) => {
215
            return arkExpandFile(sourceFile, pluginOptions.arkui, typeChecker, ctx, extras, entryTracker)
216
        }
217
    }
218
}
219

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.