idlize
102 строки · 4.2 Кб
1/*
2* Copyright (c) 2024 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 'typescript'17import * as path from "path"18import { getOrPut, nameOrNull, renameClassToBuilderClass, renameClassToMaterialized, renameDtsToInterfaces } from "../util";19import { LanguageWriter } from "./LanguageWriters";20import { PeerLibrary } from './PeerLibrary';21import { isMaterialized } from './Materialized';22import { DeclarationNameConvertor } from './dependencies_collector';23import { PeerGeneratorConfig } from './PeerGeneratorConfig';24import { convertDeclaration } from './TypeNodeConvertor';25import { syntheticDeclarationFilename, isSyntheticDeclaration } from './synthetic_declaration';26import { isBuilderClass } from './BuilderClass';27
28export type ImportsCollectorFilter = (feature: string, module: string) => boolean29
30export class ImportsCollector {31private readonly moduleToFeatures: Map<string, Set<string>> = new Map()32private readonly filters: ImportsCollectorFilter[] = []33
34addFeature(feature: string, module: string) {35const dependencies = getOrPut(this.moduleToFeatures, module, () => new Set())36dependencies.add(feature)37}38
39addFeatureByBasename(feature: string, basename: string) {40const basenameNoExt = basename.replaceAll(path.extname(basename), '')41this.addFeature(feature, `./${basenameNoExt}`)42}43
44addFilter(filter: ImportsCollectorFilter) {45this.filters.push(filter)46}47
48addFilterByBasename(basename: string) {49const basenameNoExt = basename.replaceAll(path.extname(basename), '')50const module = `./${basenameNoExt}`51this.addFilter((_, m) => m !== module)52}53
54print(printer: LanguageWriter) {55this.moduleToFeatures.forEach((features, module) => {56const filteredFeatures = Array.from(features).filter(feature => {57return this.filters.every(it => it(feature, module))58}).sort()59if (filteredFeatures.length > 0)60printer.print(`import { ${filteredFeatures.join(', ')} } from "${module}"`)61})62}63}
64
65export type ImportFeature = { feature: string, module: string }66
67export function convertDeclToFeature(library: PeerLibrary, node: ts.Declaration): ImportFeature {68if (isSyntheticDeclaration(node))69return {70feature: convertDeclaration(DeclarationNameConvertor.I, node),71module: `./${syntheticDeclarationFilename(node)}`72}73if (PeerGeneratorConfig.isConflictedDeclaration(node)) {74const parent = node.parent75let feature = ts.isModuleBlock(parent)76? parent.parent.name.text77: convertDeclaration(DeclarationNameConvertor.I, node)78return {79feature: feature,80module: './ConflictedDeclarations'81}82}83
84if (!ts.isSourceFile(node.parent))85throw "Expected parent of declaration to be a SourceFile"86const originalBasename = path.basename(node.parent.fileName)87let fileName = renameDtsToInterfaces(originalBasename, library.declarationTable.language)88if ((ts.isInterfaceDeclaration(node) || ts.isClassDeclaration(node)) && !library.isComponentDeclaration(node)) {89if (isBuilderClass(node)) {90fileName = renameClassToBuilderClass(nameOrNull(node.name)!, library.declarationTable.language)91} else if (isMaterialized(node)) {92fileName = renameClassToMaterialized(nameOrNull(node.name)!, library.declarationTable.language)93}94}95
96const basename = path.basename(fileName)97const basenameNoExt = basename.replaceAll(path.extname(basename), '')98return {99feature: convertDeclaration(DeclarationNameConvertor.I, node),100module: `./${basenameNoExt}`,101}102}