1/* 2 * Copyright (c) 2025 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 { OptionValues } from 'commander'; 17import * as fs from 'fs'; 18 19import path from 'path'; 20 21export interface ArkUIConfig { 22 components: Array<string>; 23} 24 25interface NoneUIConfig { 26 files: Array<string>; 27} 28 29export class ArkUIConfigUtil { 30 static instance: ArkUIConfigUtil = new ArkUIConfigUtil(); 31 constructor() { 32 this.config = JSON.parse(fs.readFileSync('./config/arkui_config.json', 'utf-8')); 33 this.config.components.forEach(c => { 34 this.componentSet.add(c); 35 }); 36 this.noneUIconfig = JSON.parse(fs.readFileSync('./config/none_arkui_files.json', 'utf-8')); 37 this.noneUIconfig.files.forEach(f => { 38 this.noneUIFileSet.add(f); 39 }); 40 } 41 // ui components 42 private config: ArkUIConfig; 43 // None ui files 44 private noneUIconfig: NoneUIConfig; 45 private noneUIFileSet: Set<string> = new Set(); 46 // Full set of component, should be manually mantained by config file 47 private componentSet: Set<string> = new Set(); 48 // Component superclass set, generated by traversing the declartion AST 49 private componentSuperclassSet: Set<string> = new Set(); 50 // All class/interface name related to component attribute heritage 51 private componentHeritage: Set<string> = new Set(); 52 // All implement relationship of component heritage 53 private componentHerirageRelation: Map<string, string> = new Map(); 54 // All component filename 55 private componentFiles: Set<string> = new Set(); 56 private file2Attrbiute: Map<string, string> = new Map(); 57 private shouldNotHaveAttributeModifier: Set<string> = new Set(); 58 private _useMemoM3: boolean = false; 59 private _configPath: string = ''; 60 get isHdsComponent(): boolean { 61 return this._configPath.length > 0; 62 } 63 get useMemoM3(): boolean { 64 return this._useMemoM3; 65 } 66 public loadConfig(config: OptionValues): void { 67 if (config.useMemoM3) { 68 this._useMemoM3 = true; 69 } 70 71 if (config.configPath != undefined && config.configPath != '') { 72 this._configPath = config.configPath; 73 // exception process: avoid non-existing given path 74 try { 75 this.config = JSON.parse(fs.readFileSync(this._configPath + '/hds_uicomponents.json', 'utf-8')); 76 this.componentSet.clear(); 77 this.config.components.forEach(c => { 78 this.componentSet.add(c); 79 }); 80 this.noneUIconfig = JSON.parse(fs.readFileSync(this._configPath + '/hds_non_uicomponents.json', 'utf-8')); 81 this.noneUIFileSet.clear(); 82 this.noneUIconfig.files.forEach(f => { 83 this.noneUIFileSet.add(f); 84 }); 85 } catch (error) { 86 this._configPath = ''; 87 console.log('Load given hds_uicomponents file failed!', error); 88 } 89 } 90 } 91 private getPureName(name: string): string { 92 return path 93 .basename(name) 94 .replace(/\.d\.e?ts/g, '') 95 .replace(/_/g, '') 96 .toLowerCase(); 97 } 98 99 public isRelatedToComponent(name: string): boolean { 100 return this.componentSet.has(name) || this.componentSuperclassSet.has(name); 101 } 102 public isComponent(name: string, subfix: string): boolean { 103 const regSubfix = new RegExp(subfix, 'g'); 104 return this.componentSet.has(name.replace(regSubfix, '')); 105 } 106 public addComponentSuperclass(name: string): void { 107 if (!this.isComponent(name, 'Attribute')) { 108 this.componentSuperclassSet.add(name); 109 } 110 } 111 public addComponentAttributeHeritage(name: string[]): void { 112 let prev: string | undefined = undefined; 113 name.forEach(n => { 114 if (prev) { 115 this.componentHerirageRelation.set(prev, n); 116 } 117 prev = n; 118 this.componentHeritage.add(n); 119 }); 120 if (name.length == 1) { 121 this.shouldNotHaveAttributeModifier.add(name[0]); 122 } 123 } 124 public getComponentSuperclass(name: string): string | undefined { 125 return this.componentHerirageRelation.get(name); 126 } 127 public isUIHeritage(name: string): boolean { 128 return this.componentHeritage.has(name); 129 } 130 public notUIFile(name: string): boolean { 131 return this.noneUIFileSet.has(this.getPureName(name)); 132 } 133 public addComponentFile(name: string): void { 134 this.componentFiles.add(this.getPureName(name)); 135 } 136 public isComponentFile(name: string): boolean { 137 return this.componentFiles.has(this.getPureName(name)); 138 } 139 public shouldHaveAttributeModifier(name: string): boolean { 140 if (this.isHdsComponent) { 141 return false; 142 } 143 return !this.shouldNotHaveAttributeModifier.has(name) && this.isComponent(name, 'Attribute'); 144 } 145} 146 147export default ArkUIConfigUtil.instance; 148