UNPKG

unity-find-fault

Version:

A tool to find fault in unity project.

165 lines 7.14 kB
import fg from "fast-glob"; import np from "normalize-path"; import path from "path"; import { toolchain } from "../toolchain.js"; import { Project, SyntaxKind } from "ts-morph"; export class UIRelations { static project; static clsss = []; static async build() { const tsRoot = path.join(toolchain.opts.projectRoot, 'TsScripts'); const tsFiles = await fg('**/*.ts', { cwd: tsRoot, ignore: ['**/*.d.ts'] }); UIRelations.project = new Project({ tsConfigFilePath: path.join(tsRoot, 'tsconfig.json') }); // const uiPathDataTs = path.join(tsRoot, 'System/data/UIPathData.ts'); // const tabFormTs = path.join() for (const f of tsFiles) { const tsf = path.join(tsRoot, f); const src = UIRelations.project.getSourceFile(tsf); if (!src) { console.error('SourceFile not exists:', tsf); continue; } const classes = src.getClasses(); for (const cls of classes) { // const exts = cls.getExtends(); // if (exts) { // console.log(f, cls.getName(), exts.getKindName(), exts.getText(), exts.getType().getText()); // } const className = cls.getName(); if (!className) continue; const clsInfo = UIRelations.getClassInfo(np(tsf), className); const btypes = cls.getBaseTypes(); if (btypes.length > 0) { clsInfo.extends = []; btypes.forEach(v => { const t = v.getText(); if (!t.startsWith('import(')) { clsInfo.extends.push(UIRelations.getClassInfo(clsInfo.sourceFile, t)); } else { const mch = t.match(/^import\("(.+)"\)\.(\w+)(<.+>)?$/); if (mch) { const [, sourceFile, className] = mch; clsInfo.extends.push(UIRelations.getClassInfo(sourceFile + '.ts', className)); } else { console.error('base type parse failed: ', t); } } }); } } } } static isExtends(cls, parent) { if (cls.extends != null) { for (const e of cls.extends) { if (e.className == parent || UIRelations.isExtends(e, parent)) { return true; } } } return false; } static getClassInfo(sourceFile, className) { if (className.includes('<')) { className = className.substring(0, className.indexOf('<')); } let clsInfo = UIRelations.clsss.find(v => v.sourceFile == sourceFile && v.className == className); if (clsInfo == null) { clsInfo = { sourceFile, className }; UIRelations.clsss.push(clsInfo); } return clsInfo; } static getAllForms() { const ui2Prefab = {}; const updSrc = UIRelations.project.getSourceFileOrThrow(path.join(toolchain.opts.projectRoot, 'TsScripts/System/data/UIPathData.ts')); const updCls = updSrc.getClassOrThrow('UIPathData'); const sps = updCls.getStaticProperties(); sps.forEach(v => { const pd = v.asKindOrThrow(SyntaxKind.PropertyDeclaration); ui2Prefab[pd.getName()] = pd.getInitializerIfKindOrThrow(SyntaxKind.StringLiteral).getText(); }); const out = []; for (const cls of UIRelations.clsss) { if (UIRelations.isExtends(cls, 'CommonForm')) { const info = UIRelations.getUIInfo(cls, out); info.prefab = UIRelations.getPrefabPath(cls, ui2Prefab); if (UIRelations.isExtends(cls, 'TabForm')) { const subForms = UIRelations.getSubForms(cls); // console.assert(subForms.length > 0, cls.className); subForms.forEach(v => { info.children.push(UIRelations.getUIInfo(v, out)); }); } } } return out; } static getUIInfo(cls, collection) { let info = collection.find(v => v.tsClass == cls); if (info == null) { info = { prefab: '', tsClass: cls, children: [] }; collection.push(info); } return info; } static getPrefabPath(cls, ui2Prefab) { // if (cls.className == 'CommonForm' || cls.className == 'TabForm') return ''; const src = UIRelations.project.getSourceFileOrThrow(cls.sourceFile); const clsDef = src.getClassOrThrow(cls.className); const mthd = clsDef.getMethod('resPath'); if (mthd != null && !mthd.isAbstract()) { const rsChilds = mthd.getBodyOrThrow().getChildrenOfKind(SyntaxKind.ReturnStatement); if (rsChilds.length > 0) { for (const rs of rsChilds) { const rsText = rs.getText(); const mch = rsText.match(/return UIPathData\.(\w+)/); if (mch != null) { return ui2Prefab[mch[1]]; } } } } if (cls.extends != null) { for (const e of cls.extends) { if (UIRelations.isExtends(e, 'CommonForm')) { return UIRelations.getPrefabPath(e, ui2Prefab); } } } return ''; } static getSubForms(cls) { const out = []; const src = UIRelations.project.getSourceFileOrThrow(cls.sourceFile); const clsDef = src.getClassOrThrow(cls.className); const ctors = clsDef.getConstructors(); for (const ctor of ctors) { const lines = ctor.getBody()?.getChildrenOfKind(SyntaxKind.SyntaxList); if (lines) { const exps = lines[0].getChildrenOfKind(SyntaxKind.ExpressionStatement); for (const exp of exps) { const e = exp.getExpressionIfKind(SyntaxKind.CallExpression); if (e && e.getExpressionIfKind(SyntaxKind.SuperKeyword)) { const args = e.getArguments(); args.filter(v => v.isKind(SyntaxKind.Identifier)).forEach(v => { const tt = v.getType().getText(); const mch = tt.match(/^typeof import\("(.+)"\)\.(\w+)(<.+>)?$/); if (mch) { const [, sourceFile, className] = mch; out.push(UIRelations.getClassInfo(sourceFile + '.ts', className)); } }); } } } } return out; } } //# sourceMappingURL=UIRelations.js.map