161847f8eSopenharmony_ci/* 261847f8eSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 361847f8eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 461847f8eSopenharmony_ci * you may not use this file except in compliance with the License. 561847f8eSopenharmony_ci * You may obtain a copy of the License at 661847f8eSopenharmony_ci * 761847f8eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 861847f8eSopenharmony_ci * 961847f8eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1061847f8eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1161847f8eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1261847f8eSopenharmony_ci * See the License for the specific language governing permissions and 1361847f8eSopenharmony_ci * limitations under the License. 1461847f8eSopenharmony_ci */ 1561847f8eSopenharmony_ci 1661847f8eSopenharmony_ciconst { FileSystem, Logger } = require('./utils'); 1761847f8eSopenharmony_ciconst path = require('path'); 1861847f8eSopenharmony_ciconst ts = require('typescript'); 1961847f8eSopenharmony_ciconst fs = require('fs'); 2061847f8eSopenharmony_ci 2161847f8eSopenharmony_ciclass SystemApiRecognizer { 2261847f8eSopenharmony_ci constructor(systemRoot) { 2361847f8eSopenharmony_ci this.systemRoot = systemRoot; 2461847f8eSopenharmony_ci this.arkUIDecorator = new Set(['@Builder', '@Styles', '@Extend']); 2561847f8eSopenharmony_ci this.arkUIRender = new Set(['build']); 2661847f8eSopenharmony_ci this.componentAttributeMap = new Map(); 2761847f8eSopenharmony_ci this.componentAttributeTypeSymbolMap = new Map(); 2861847f8eSopenharmony_ci this.forEachComponents = new Set(['LazyForEach', 'ForEach']); 2961847f8eSopenharmony_ci this.apiInfoSet = new Set([]); 3061847f8eSopenharmony_ci } 3161847f8eSopenharmony_ci 3261847f8eSopenharmony_ci /** 3361847f8eSopenharmony_ci * 遍历AST, 识别系统API调用。 3461847f8eSopenharmony_ci * 3561847f8eSopenharmony_ci * @param {ts.Node} node 3661847f8eSopenharmony_ci * @param {string} fileName 3761847f8eSopenharmony_ci */ 3861847f8eSopenharmony_ci visitNode(node, fileName) { 3961847f8eSopenharmony_ci this.recognizeDecorators(node, fileName, undefined); 4061847f8eSopenharmony_ci if (this.isArkUIRenderMethod(node)) { 4161847f8eSopenharmony_ci this.visitUIRenderNode(node.body, fileName); 4261847f8eSopenharmony_ci } else { 4361847f8eSopenharmony_ci this.visitNormalNode(node, fileName); 4461847f8eSopenharmony_ci } 4561847f8eSopenharmony_ci } 4661847f8eSopenharmony_ci 4761847f8eSopenharmony_ci recognizeDecorators(node, fileName, position) { 4861847f8eSopenharmony_ci let decoratorArray = []; 4961847f8eSopenharmony_ci if (node.decorators) { 5061847f8eSopenharmony_ci decoratorArray = node.decorators; 5161847f8eSopenharmony_ci } else if (node.modifiers) { 5261847f8eSopenharmony_ci decoratorArray = node.modifiers; 5361847f8eSopenharmony_ci } 5461847f8eSopenharmony_ci 5561847f8eSopenharmony_ci decoratorArray.forEach(decorator => { 5661847f8eSopenharmony_ci const symbol = this.typeChecker.getSymbolAtLocation(decorator.expression); 5761847f8eSopenharmony_ci if (!symbol) { 5861847f8eSopenharmony_ci return; 5961847f8eSopenharmony_ci } 6061847f8eSopenharmony_ci const apiDecInfo = this.getSdkApiFromValueDeclaration(symbol.valueDeclaration.parent.parent); 6161847f8eSopenharmony_ci if (apiDecInfo) { 6261847f8eSopenharmony_ci apiDecInfo.setPosition(position ? 6361847f8eSopenharmony_ci position : 6461847f8eSopenharmony_ci ts.getLineAndCharacterOfPosition(decorator.getSourceFile(), decorator.getStart())); 6561847f8eSopenharmony_ci apiDecInfo.setSourceFileName(fileName); 6661847f8eSopenharmony_ci apiDecInfo.setQualifiedTypeName('global'); 6761847f8eSopenharmony_ci apiDecInfo.setPropertyName(this.getDecortorName(symbol.valueDeclaration)); 6861847f8eSopenharmony_ci this.addApiInformation(apiDecInfo); 6961847f8eSopenharmony_ci } 7061847f8eSopenharmony_ci }); 7161847f8eSopenharmony_ci } 7261847f8eSopenharmony_ci 7361847f8eSopenharmony_ci getDecortorName(node) { 7461847f8eSopenharmony_ci return node.name ? node.name.getText() : undefined; 7561847f8eSopenharmony_ci } 7661847f8eSopenharmony_ci 7761847f8eSopenharmony_ci /** 7861847f8eSopenharmony_ci * 遍历访问TypeScript 节点 7961847f8eSopenharmony_ci * 8061847f8eSopenharmony_ci * @param {ts.Node} node 8161847f8eSopenharmony_ci * @param {string} fileName 8261847f8eSopenharmony_ci */ 8361847f8eSopenharmony_ci visitNormalNode(node, fileName) { 8461847f8eSopenharmony_ci if (node) { 8561847f8eSopenharmony_ci if (ts.isCallExpression(node)) { 8661847f8eSopenharmony_ci this.recognizeNormalCallExpression(node, fileName); 8761847f8eSopenharmony_ci } else { 8861847f8eSopenharmony_ci this.recognizeNormal(node, fileName); 8961847f8eSopenharmony_ci ts.forEachChild(node, (child) => { 9061847f8eSopenharmony_ci this.visitNode(child, fileName); 9161847f8eSopenharmony_ci }); 9261847f8eSopenharmony_ci } 9361847f8eSopenharmony_ci } 9461847f8eSopenharmony_ci } 9561847f8eSopenharmony_ci 9661847f8eSopenharmony_ci /** 9761847f8eSopenharmony_ci * 遍历访问 UI 渲染节点 9861847f8eSopenharmony_ci * 9961847f8eSopenharmony_ci * @param {ts.Block} node 10061847f8eSopenharmony_ci * @param {string} fileName 10161847f8eSopenharmony_ci */ 10261847f8eSopenharmony_ci visitUIRenderNode(node, fileName) { 10361847f8eSopenharmony_ci if (!node.statements) { 10461847f8eSopenharmony_ci return; 10561847f8eSopenharmony_ci } 10661847f8eSopenharmony_ci node.statements.forEach((statement) => { 10761847f8eSopenharmony_ci this.recognizeUIComponents(statement, fileName); 10861847f8eSopenharmony_ci }); 10961847f8eSopenharmony_ci } 11061847f8eSopenharmony_ci 11161847f8eSopenharmony_ci setTypeChecker(typeChecker) { 11261847f8eSopenharmony_ci this.typeChecker = typeChecker; 11361847f8eSopenharmony_ci } 11461847f8eSopenharmony_ci 11561847f8eSopenharmony_ci /** 11661847f8eSopenharmony_ci * 保存系统API 11761847f8eSopenharmony_ci * 11861847f8eSopenharmony_ci * @param {ApiDeclarationInformation} apiInfo 11961847f8eSopenharmony_ci */ 12061847f8eSopenharmony_ci addApiInformation(apiInfo) { 12161847f8eSopenharmony_ci if (!this.apiInfos) { 12261847f8eSopenharmony_ci this.apiInfos = []; 12361847f8eSopenharmony_ci } 12461847f8eSopenharmony_ci if (this.apiInfoSet.has(this.formatApiInfo(apiInfo))) { 12561847f8eSopenharmony_ci return; 12661847f8eSopenharmony_ci } 12761847f8eSopenharmony_ci this.apiInfos.push(apiInfo); 12861847f8eSopenharmony_ci this.apiInfoSet.add(this.formatApiInfo(apiInfo)); 12961847f8eSopenharmony_ci } 13061847f8eSopenharmony_ci 13161847f8eSopenharmony_ci formatApiInfo(apiInfo) { 13261847f8eSopenharmony_ci return `${apiInfo.dtsName}#${apiInfo.typeName}#${apiInfo.apiRawText}#${apiInfo.sourceFileName}#${apiInfo.pos}`; 13361847f8eSopenharmony_ci } 13461847f8eSopenharmony_ci 13561847f8eSopenharmony_ci getApiInformations() { 13661847f8eSopenharmony_ci const apiDecInfos = this.apiInfos ? this.apiInfos : []; 13761847f8eSopenharmony_ci apiDecInfos.forEach((apiInfo) => { 13861847f8eSopenharmony_ci apiInfo.setApiNode(undefined); 13961847f8eSopenharmony_ci }); 14061847f8eSopenharmony_ci return apiDecInfos; 14161847f8eSopenharmony_ci } 14261847f8eSopenharmony_ci 14361847f8eSopenharmony_ci isSdkApi(apiFilePath) { 14461847f8eSopenharmony_ci return FileSystem.isInDirectory(this.systemRoot, apiFilePath); 14561847f8eSopenharmony_ci } 14661847f8eSopenharmony_ci 14761847f8eSopenharmony_ci /** 14861847f8eSopenharmony_ci * 判断是否为创建ArkUI组件的方法 14961847f8eSopenharmony_ci * 15061847f8eSopenharmony_ci * @param {ts.Node} node 15161847f8eSopenharmony_ci */ 15261847f8eSopenharmony_ci isArkUIRenderMethod(node) { 15361847f8eSopenharmony_ci if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) { 15461847f8eSopenharmony_ci return this.isBuildMethodInStruct(node) || this.hasArkUIDecortor(node); 15561847f8eSopenharmony_ci } 15661847f8eSopenharmony_ci return false; 15761847f8eSopenharmony_ci } 15861847f8eSopenharmony_ci 15961847f8eSopenharmony_ci /** 16061847f8eSopenharmony_ci * 是否为struct 中的 build 方法。 16161847f8eSopenharmony_ci * 16261847f8eSopenharmony_ci * @param {ts.Node} node 16361847f8eSopenharmony_ci * @returns ture or false 16461847f8eSopenharmony_ci */ 16561847f8eSopenharmony_ci isBuildMethodInStruct(node) { 16661847f8eSopenharmony_ci return node.name && this.arkUIRender.has(node.name.getText()) && ts.isStructDeclaration(node.parent); 16761847f8eSopenharmony_ci } 16861847f8eSopenharmony_ci 16961847f8eSopenharmony_ci /** 17061847f8eSopenharmony_ci * 判断是否有ArkUI注解 17161847f8eSopenharmony_ci * 17261847f8eSopenharmony_ci * @param {ts.Node} node 17361847f8eSopenharmony_ci * @returns true or false 17461847f8eSopenharmony_ci */ 17561847f8eSopenharmony_ci hasArkUIDecortor(node) { 17661847f8eSopenharmony_ci if (node.decorators) { 17761847f8eSopenharmony_ci for (const decorator of node.decorators) { 17861847f8eSopenharmony_ci const decoratorName = this.getDecortorIdefiner(decorator); 17961847f8eSopenharmony_ci if (!decoratorName) { 18061847f8eSopenharmony_ci continue; 18161847f8eSopenharmony_ci } 18261847f8eSopenharmony_ci const decoratorStr = `@${decoratorName.getText()}`; 18361847f8eSopenharmony_ci if (!this.arkUIDecorator.has(decoratorStr)) { 18461847f8eSopenharmony_ci continue; 18561847f8eSopenharmony_ci } 18661847f8eSopenharmony_ci const decoratroSymbol = this.typeChecker.getSymbolAtLocation(decoratorName); 18761847f8eSopenharmony_ci if (this.isSdkApi(decoratroSymbol.valueDeclaration.getSourceFile().fileName)) { 18861847f8eSopenharmony_ci return true; 18961847f8eSopenharmony_ci } 19061847f8eSopenharmony_ci } 19161847f8eSopenharmony_ci } 19261847f8eSopenharmony_ci return false; 19361847f8eSopenharmony_ci } 19461847f8eSopenharmony_ci 19561847f8eSopenharmony_ci getDecortorIdefiner(decoratorExp) { 19661847f8eSopenharmony_ci if (ts.isDecorator(decoratorExp) || ts.isCallExpression(decoratorExp)) { 19761847f8eSopenharmony_ci return this.getDecortorIdefiner(decoratorExp.expression); 19861847f8eSopenharmony_ci } 19961847f8eSopenharmony_ci return ts.isIdentifier(decoratorExp) ? decoratorExp : undefined; 20061847f8eSopenharmony_ci } 20161847f8eSopenharmony_ci 20261847f8eSopenharmony_ci /** 20361847f8eSopenharmony_ci * 获取AST节点的API信息。 20461847f8eSopenharmony_ci * 20561847f8eSopenharmony_ci * @param {ts.Node} node 20661847f8eSopenharmony_ci * @param {string} fileName 20761847f8eSopenharmony_ci * @param {Function} positionCallback 20861847f8eSopenharmony_ci * @returns {ApiDeclarationInformation | undefined} apiDecInfo 20961847f8eSopenharmony_ci */ 21061847f8eSopenharmony_ci recognizeApiWithNode(node, fileName, positionCallback, useDeclarations) { 21161847f8eSopenharmony_ci let finallySymbol = undefined; 21261847f8eSopenharmony_ci if (!node) { 21361847f8eSopenharmony_ci return finallySymbol; 21461847f8eSopenharmony_ci } 21561847f8eSopenharmony_ci 21661847f8eSopenharmony_ci try { 21761847f8eSopenharmony_ci let symbol = this.typeChecker.getSymbolAtLocation(node); 21861847f8eSopenharmony_ci if (symbol && symbol.flags === ts.SymbolFlags.Alias) { 21961847f8eSopenharmony_ci symbol = this.typeChecker.getAliasedSymbol(symbol); 22061847f8eSopenharmony_ci } 22161847f8eSopenharmony_ci finallySymbol = this.recognizeApiWithNodeAndSymbol(node, symbol, fileName, positionCallback, useDeclarations); 22261847f8eSopenharmony_ci } catch (error) { 22361847f8eSopenharmony_ci Logger.error('UNKNOW NODE', error); 22461847f8eSopenharmony_ci } 22561847f8eSopenharmony_ci return finallySymbol; 22661847f8eSopenharmony_ci } 22761847f8eSopenharmony_ci 22861847f8eSopenharmony_ci recognizeApiWithNodeAndSymbol(node, symbol, fileName, positionCallback, useDeclarations) { 22961847f8eSopenharmony_ci if (symbol) { 23061847f8eSopenharmony_ci const apiDecInfo = this.getSdkApiDeclarationWithSymbol(symbol, node, useDeclarations); 23161847f8eSopenharmony_ci const position = ts.getLineAndCharacterOfPosition(node.getSourceFile(), positionCallback(node)); 23261847f8eSopenharmony_ci if (symbol.valueDeclaration && this.isSdkApi(symbol.valueDeclaration.getSourceFile().fileName)) { 23361847f8eSopenharmony_ci this.recognizeDecorators(symbol.valueDeclaration, fileName, position); 23461847f8eSopenharmony_ci } 23561847f8eSopenharmony_ci if (apiDecInfo) { 23661847f8eSopenharmony_ci apiDecInfo.setPosition(position); 23761847f8eSopenharmony_ci apiDecInfo.setSourceFileName(fileName); 23861847f8eSopenharmony_ci this.addApiInformation(apiDecInfo); 23961847f8eSopenharmony_ci return apiDecInfo; 24061847f8eSopenharmony_ci } 24161847f8eSopenharmony_ci } 24261847f8eSopenharmony_ci return undefined; 24361847f8eSopenharmony_ci } 24461847f8eSopenharmony_ci 24561847f8eSopenharmony_ci /** 24661847f8eSopenharmony_ci * 识别TS代码节点中的系统API 24761847f8eSopenharmony_ci * 24861847f8eSopenharmony_ci * @param {ts.Node} node 24961847f8eSopenharmony_ci * @param {string} fileName 25061847f8eSopenharmony_ci */ 25161847f8eSopenharmony_ci recognizeNormal(node, fileName) { 25261847f8eSopenharmony_ci if (ts.isPropertyAccessExpression(node)) { 25361847f8eSopenharmony_ci this.recognizePropertyAccessExpression(node, fileName); 25461847f8eSopenharmony_ci } else if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) { 25561847f8eSopenharmony_ci this.recognizeHeritageClauses(node, fileName); 25661847f8eSopenharmony_ci } else if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) { 25761847f8eSopenharmony_ci this.recognizeApiWithNode(node.expression, fileName, (node) => node.getStart()); 25861847f8eSopenharmony_ci } else if (ts.isStructDeclaration(node)) { 25961847f8eSopenharmony_ci this.recognizeHeritageClauses(node, fileName); 26061847f8eSopenharmony_ci } else if (ts.isTypeReferenceNode(node)) { 26161847f8eSopenharmony_ci this.recognizeTypeReferenceNode(node, fileName); 26261847f8eSopenharmony_ci } else if (ts.isObjectLiteralExpression(node)) { 26361847f8eSopenharmony_ci this.recognizeObjectLiteralExpression(node, fileName); 26461847f8eSopenharmony_ci } else if (ts.isCallExpression(node)) { 26561847f8eSopenharmony_ci this.recognizeEtsComponentAndAttributeApi(node.expression, fileName); 26661847f8eSopenharmony_ci } 26761847f8eSopenharmony_ci } 26861847f8eSopenharmony_ci 26961847f8eSopenharmony_ci recognizeTypeReferenceNode(node, fileName) { 27061847f8eSopenharmony_ci if (ts.isTypeReferenceNode(node)) { 27161847f8eSopenharmony_ci this.recognizeTypeReferenceNode(node.typeName, fileName); 27261847f8eSopenharmony_ci } else if (ts.isQualifiedName(node)) { 27361847f8eSopenharmony_ci this.recognizeApiWithNode(node.typeName?.right, fileName, (node) => node.getStart(), true); 27461847f8eSopenharmony_ci } else if (ts.isIdentifier(node)) { 27561847f8eSopenharmony_ci this.recognizeApiWithNode(node, fileName, (node) => node.getStart(), true); 27661847f8eSopenharmony_ci } 27761847f8eSopenharmony_ci } 27861847f8eSopenharmony_ci 27961847f8eSopenharmony_ci recognizeNormalCallExpression(node, fileName) { 28061847f8eSopenharmony_ci if (!node) { 28161847f8eSopenharmony_ci return undefined; 28261847f8eSopenharmony_ci } 28361847f8eSopenharmony_ci if (ts.isCallExpression(node)) { 28461847f8eSopenharmony_ci const apiDecInfo = this.recognizeNormalCallExpression(node.expression, fileName); 28561847f8eSopenharmony_ci this.recognizeNormalCallExpressionArguments(apiDecInfo, node.arguments, fileName); 28661847f8eSopenharmony_ci return apiDecInfo; 28761847f8eSopenharmony_ci } else if (ts.isPropertyAccessExpression(node)) { 28861847f8eSopenharmony_ci this.recognizeNormalCallExpression(node.expression, fileName); 28961847f8eSopenharmony_ci return this.recognizePropertyAccessExpression(node, fileName); 29061847f8eSopenharmony_ci } else if (ts.isIdentifier(node)) { 29161847f8eSopenharmony_ci return this.recognizeApiWithNode(node, fileName, (node) => node.getStart()); 29261847f8eSopenharmony_ci } else { 29361847f8eSopenharmony_ci return undefined; 29461847f8eSopenharmony_ci } 29561847f8eSopenharmony_ci } 29661847f8eSopenharmony_ci 29761847f8eSopenharmony_ci recognizeNormalCallExpressionArguments(apiDecInfo, args, fileName) { 29861847f8eSopenharmony_ci if (args.length === 0) { 29961847f8eSopenharmony_ci return; 30061847f8eSopenharmony_ci } 30161847f8eSopenharmony_ci const parameters = apiDecInfo ? apiDecInfo.apiNode.parameters : undefined; 30261847f8eSopenharmony_ci args.forEach((arg, index) => { 30361847f8eSopenharmony_ci // interface 定义作为函数入参时, 统计为API 30461847f8eSopenharmony_ci this.recognizeArgument(arg, fileName); 30561847f8eSopenharmony_ci if (!(parameters && parameters[index] && parameters[index].type)) { 30661847f8eSopenharmony_ci return; 30761847f8eSopenharmony_ci } 30861847f8eSopenharmony_ci const paramType = parameters[index].type; 30961847f8eSopenharmony_ci if (ts.isTypeReferenceNode(paramType)) { 31061847f8eSopenharmony_ci const paramTypeApiDecInfo = this.recognizeApiWithNode(paramType.typeName, fileName, (node) => node.getStart(), true); 31161847f8eSopenharmony_ci if (paramTypeApiDecInfo) { 31261847f8eSopenharmony_ci this.modifyTypeReferenceSourceFileName(paramType.typeName, paramTypeApiDecInfo); 31361847f8eSopenharmony_ci paramTypeApiDecInfo.setApiType('interface'); 31461847f8eSopenharmony_ci paramTypeApiDecInfo.setPosition(ts.getLineAndCharacterOfPosition(arg.getSourceFile(), arg.getStart())); 31561847f8eSopenharmony_ci } 31661847f8eSopenharmony_ci } 31761847f8eSopenharmony_ci }); 31861847f8eSopenharmony_ci } 31961847f8eSopenharmony_ci 32061847f8eSopenharmony_ci modifyTypeReferenceSourceFileName(typeNameNode, apiDecInfo) { 32161847f8eSopenharmony_ci const symbol = this.typeChecker.getSymbolAtLocation(typeNameNode); 32261847f8eSopenharmony_ci if (symbol) { 32361847f8eSopenharmony_ci const typeDec = symbol.declarations[0]; 32461847f8eSopenharmony_ci let importDec = typeDec; 32561847f8eSopenharmony_ci while (importDec && !ts.isImportDeclaration(importDec)) { 32661847f8eSopenharmony_ci importDec = importDec.parent; 32761847f8eSopenharmony_ci } 32861847f8eSopenharmony_ci if (!importDec) { 32961847f8eSopenharmony_ci return; 33061847f8eSopenharmony_ci } 33161847f8eSopenharmony_ci const moduleSpecifier = importDec.moduleSpecifier; 33261847f8eSopenharmony_ci this.saveApiDecInfo(moduleSpecifier, apiDecInfo, typeNameNode); 33361847f8eSopenharmony_ci } 33461847f8eSopenharmony_ci } 33561847f8eSopenharmony_ci 33661847f8eSopenharmony_ci saveApiDecInfo(moduleSpecifier, apiDecInfo, typeNameNode) { 33761847f8eSopenharmony_ci const specialInterfaceSet = new Set(['Callback', 'AsyncCallback']); 33861847f8eSopenharmony_ci if (ts.isStringLiteral(moduleSpecifier, apiDecInfo)) { 33961847f8eSopenharmony_ci const useTypeFileName = apiDecInfo.apiNode.getSourceFile().fileName; 34061847f8eSopenharmony_ci const moduleRelativePaths = moduleSpecifier.getText().match(/^['"](.*)['"]$/); 34161847f8eSopenharmony_ci const MODULE_PATH_LENGTH = 2; 34261847f8eSopenharmony_ci if (moduleRelativePaths.length < MODULE_PATH_LENGTH) { 34361847f8eSopenharmony_ci return; 34461847f8eSopenharmony_ci } 34561847f8eSopenharmony_ci const modulePath = path.resolve(path.dirname(useTypeFileName), `${moduleRelativePaths[1]}.d.ts`); 34661847f8eSopenharmony_ci if (fs.existsSync(modulePath)) { 34761847f8eSopenharmony_ci if (specialInterfaceSet.has(typeNameNode.getText())) { 34861847f8eSopenharmony_ci apiDecInfo.apiText = this.getSpecialInterfaceText(modulePath, typeNameNode.getText()); 34961847f8eSopenharmony_ci } 35061847f8eSopenharmony_ci const dtsPath = path.relative(this.systemRoot, modulePath).replace(/\\/g, '/'); 35161847f8eSopenharmony_ci apiDecInfo.dtsName = path.basename(modulePath); 35261847f8eSopenharmony_ci apiDecInfo.packageName = path.relative(this.systemRoot, modulePath); 35361847f8eSopenharmony_ci apiDecInfo.dtsPath = this.formatDtsPath(dtsPath); 35461847f8eSopenharmony_ci apiDecInfo.typeName = apiDecInfo.propertyName; 35561847f8eSopenharmony_ci } 35661847f8eSopenharmony_ci } 35761847f8eSopenharmony_ci } 35861847f8eSopenharmony_ci 35961847f8eSopenharmony_ci getSpecialInterfaceText(modulePath, interfaceName) { 36061847f8eSopenharmony_ci const fileContent = fs.readFileSync(modulePath, 'utf-8'); 36161847f8eSopenharmony_ci const apiFileName = path.basename(modulePath).replace('d.ts', '.ts'); 36261847f8eSopenharmony_ci const sourceFile = ts.createSourceFile(apiFileName, fileContent, ts.ScriptTarget.ES2017, true); 36361847f8eSopenharmony_ci let interfaceText = ''; 36461847f8eSopenharmony_ci sourceFile.statements.forEach(stat => { 36561847f8eSopenharmony_ci if (ts.isInterfaceDeclaration(stat) && stat.name.escapedText === interfaceName) { 36661847f8eSopenharmony_ci interfaceText = stat.getText().split('{')[0]; 36761847f8eSopenharmony_ci } 36861847f8eSopenharmony_ci }); 36961847f8eSopenharmony_ci return interfaceText; 37061847f8eSopenharmony_ci } 37161847f8eSopenharmony_ci 37261847f8eSopenharmony_ci formatDtsPath(dtsPath) { 37361847f8eSopenharmony_ci if (dtsPath.indexOf('api/@internal/full/canvaspattern.d.ts') > -1) { 37461847f8eSopenharmony_ci return dtsPath.replace('api/@internal/full/', 'interface/sdk-js/api/common/full/'); 37561847f8eSopenharmony_ci } else if (dtsPath.indexOf('api/@internal/full/featureability.d.ts') > -1) { 37661847f8eSopenharmony_ci return dtsPath.replace('api/@internal/full/', '/interface/sdk-js/api/common/full/'); 37761847f8eSopenharmony_ci } else if (dtsPath.indexOf('api/internal/full') > -1) { 37861847f8eSopenharmony_ci return dtsPath.replace('api/@internal/full/', '/interface/sdk-js/api/@internal/ets/'); 37961847f8eSopenharmony_ci } else if (dtsPath.indexOf('component/') > -1) { 38061847f8eSopenharmony_ci return dtsPath.replace('component/', 'interface/sdk-js/api/@internal/component/ets/'); 38161847f8eSopenharmony_ci } else { 38261847f8eSopenharmony_ci return path.join('/interface/sdk-js', dtsPath).replace(/\\/g, '/'); 38361847f8eSopenharmony_ci } 38461847f8eSopenharmony_ci } 38561847f8eSopenharmony_ci 38661847f8eSopenharmony_ci /** 38761847f8eSopenharmony_ci * 识别UI组件及其属性 38861847f8eSopenharmony_ci * 38961847f8eSopenharmony_ci * @param {ts.Node} node 39061847f8eSopenharmony_ci * @param {string} fileName 39161847f8eSopenharmony_ci */ 39261847f8eSopenharmony_ci recognizeUIComponents(node, fileName, parentName) { 39361847f8eSopenharmony_ci if (ts.isEtsComponentExpression(node)) { 39461847f8eSopenharmony_ci // ETS组件的声明, EtsComponentExpression 表示有子组件的组件. 39561847f8eSopenharmony_ci this.recognizeEtsComponentExpression(node, fileName); 39661847f8eSopenharmony_ci } else if (ts.isCallExpression(node)) { 39761847f8eSopenharmony_ci // 组件链式调用 39861847f8eSopenharmony_ci this.recognizeComponentAttributeChain(node, fileName, []); 39961847f8eSopenharmony_ci } else if (ts.isIfStatement(node)) { 40061847f8eSopenharmony_ci this.recognizeIfStatement(node, fileName); 40161847f8eSopenharmony_ci } else { 40261847f8eSopenharmony_ci ts.forEachChild(node, (child) => { 40361847f8eSopenharmony_ci this.recognizeUIComponents(child, fileName); 40461847f8eSopenharmony_ci }); 40561847f8eSopenharmony_ci } 40661847f8eSopenharmony_ci } 40761847f8eSopenharmony_ci 40861847f8eSopenharmony_ci /** 40961847f8eSopenharmony_ci * 识别在对象内,作为入参的API 41061847f8eSopenharmony_ci * 41161847f8eSopenharmony_ci * @param {ts.Node} node 41261847f8eSopenharmony_ci * @param {string} fileName 41361847f8eSopenharmony_ci * @returns 41461847f8eSopenharmony_ci */ 41561847f8eSopenharmony_ci recognizeObjectLiteralExpression(node, fileName) { 41661847f8eSopenharmony_ci let parentName = ''; 41761847f8eSopenharmony_ci if (node.parent && node.parent.expression && ts.isIdentifier(node.parent.expression)) { 41861847f8eSopenharmony_ci parentName = node.parent.expression.escapedName ? 41961847f8eSopenharmony_ci node.parent.expression.escapedName : node.parent.expression.escapedText; 42061847f8eSopenharmony_ci } 42161847f8eSopenharmony_ci const parentType = this.typeChecker.getContextualType(node); 42261847f8eSopenharmony_ci if (!parentType || !parentType.properties) { 42361847f8eSopenharmony_ci return; 42461847f8eSopenharmony_ci } 42561847f8eSopenharmony_ci if (parentType.properties.length === 0) { 42661847f8eSopenharmony_ci return; 42761847f8eSopenharmony_ci } 42861847f8eSopenharmony_ci if (!parentType.properties[0].valueDeclaration) { 42961847f8eSopenharmony_ci return; 43061847f8eSopenharmony_ci } 43161847f8eSopenharmony_ci const sourceFile = parentType.properties[0].valueDeclaration.getSourceFile(); 43261847f8eSopenharmony_ci 43361847f8eSopenharmony_ci //判断是否为系统API 43461847f8eSopenharmony_ci if (!this.isSdkApi(sourceFile.fileName)) { 43561847f8eSopenharmony_ci return; 43661847f8eSopenharmony_ci } 43761847f8eSopenharmony_ci let parentSymbol = sourceFile.locals.get(parentName); 43861847f8eSopenharmony_ci const apiMapInParent = this.getApiMapInParent(parentSymbol, parentType); 43961847f8eSopenharmony_ci 44061847f8eSopenharmony_ci node.properties.forEach(property => { 44161847f8eSopenharmony_ci const apiNode = apiMapInParent.get(property.name.escapedText); 44261847f8eSopenharmony_ci if (!apiNode) { 44361847f8eSopenharmony_ci return; 44461847f8eSopenharmony_ci } 44561847f8eSopenharmony_ci if (ts.isTypeLiteralNode(apiNode.parent)) { 44661847f8eSopenharmony_ci return; 44761847f8eSopenharmony_ci } 44861847f8eSopenharmony_ci const apiDecInfo = this.getSdkApiFromValueDeclaration(apiNode, property, fileName); 44961847f8eSopenharmony_ci if (apiDecInfo) { 45061847f8eSopenharmony_ci const position = ts.getLineAndCharacterOfPosition(property.getSourceFile(), property.name.getStart()); 45161847f8eSopenharmony_ci this.recognizeDecorators(apiNode, fileName, position); 45261847f8eSopenharmony_ci apiDecInfo.setPosition(position); 45361847f8eSopenharmony_ci apiDecInfo.setSourceFileName(fileName); 45461847f8eSopenharmony_ci this.addApiInformation(apiDecInfo); 45561847f8eSopenharmony_ci } 45661847f8eSopenharmony_ci }); 45761847f8eSopenharmony_ci } 45861847f8eSopenharmony_ci 45961847f8eSopenharmony_ci getApiMapInParent(parentSymbol, parentType) { 46061847f8eSopenharmony_ci const apiMapInParent = new Map(); 46161847f8eSopenharmony_ci if (!parentSymbol) { 46261847f8eSopenharmony_ci parentType.members.forEach((memberValue, member) => { 46361847f8eSopenharmony_ci apiMapInParent.set(member, memberValue.valueDeclaration); 46461847f8eSopenharmony_ci }); 46561847f8eSopenharmony_ci } else { 46661847f8eSopenharmony_ci parentSymbol.declarations[0]?.members?.forEach(member => { 46761847f8eSopenharmony_ci if (!member.name) { 46861847f8eSopenharmony_ci return; 46961847f8eSopenharmony_ci } 47061847f8eSopenharmony_ci apiMapInParent.set(member.name.escapedText, member); 47161847f8eSopenharmony_ci }); 47261847f8eSopenharmony_ci } 47361847f8eSopenharmony_ci return apiMapInParent; 47461847f8eSopenharmony_ci } 47561847f8eSopenharmony_ci 47661847f8eSopenharmony_ci /** 47761847f8eSopenharmony_ci * 识别条件渲染 47861847f8eSopenharmony_ci * @param {ts.Node} node 47961847f8eSopenharmony_ci * @param {string} fileName 48061847f8eSopenharmony_ci */ 48161847f8eSopenharmony_ci recognizeIfStatement(node, fileName) { 48261847f8eSopenharmony_ci this.recognizeArgument(node.expression, fileName); 48361847f8eSopenharmony_ci const thenStatements = ts.isBlock(node) ? node.statements : 48461847f8eSopenharmony_ci (ts.isBlock(node.thenStatement) ? node.thenStatement.statements : undefined); 48561847f8eSopenharmony_ci if (thenStatements) { 48661847f8eSopenharmony_ci thenStatements.forEach((child) => { 48761847f8eSopenharmony_ci this.recognizeUIComponents(child, fileName); 48861847f8eSopenharmony_ci }); 48961847f8eSopenharmony_ci } 49061847f8eSopenharmony_ci if (node.elseStatement) { 49161847f8eSopenharmony_ci this.recognizeIfStatement(node.elseStatement, fileName); 49261847f8eSopenharmony_ci } 49361847f8eSopenharmony_ci } 49461847f8eSopenharmony_ci 49561847f8eSopenharmony_ci /** 49661847f8eSopenharmony_ci * 识别组件链式调用中的API 49761847f8eSopenharmony_ci * @param {ts.Node} node 49861847f8eSopenharmony_ci * @param {string} fileName 49961847f8eSopenharmony_ci */ 50061847f8eSopenharmony_ci recognizeComponentAttributeChain(node, fileName) { 50161847f8eSopenharmony_ci if (ts.isCallExpression(node)) { 50261847f8eSopenharmony_ci const chainResult = this.recognizeComponentAttributeChain(node.expression, fileName); 50361847f8eSopenharmony_ci this.recognizeArguments(node.arguments, fileName); 50461847f8eSopenharmony_ci return new ComponentAttrResult(chainResult.componentInfo, undefined); 50561847f8eSopenharmony_ci } else if (ts.isPropertyAccessExpression(node)) { 50661847f8eSopenharmony_ci const chainResult = this.recognizeComponentAttributeChain(node.expression, fileName); 50761847f8eSopenharmony_ci const attrInfo = this.recognizeEtsComponentAndAttributeApi(node, fileName); 50861847f8eSopenharmony_ci if (chainResult.componentInfo && attrInfo) { 50961847f8eSopenharmony_ci attrInfo.setComponentName(chainResult.componentInfo.propertyName); 51061847f8eSopenharmony_ci } 51161847f8eSopenharmony_ci return new ComponentAttrResult(chainResult.componentInfo, attrInfo); 51261847f8eSopenharmony_ci } else if (ts.isEtsComponentExpression(node)) { 51361847f8eSopenharmony_ci return new ComponentAttrResult(this.recognizeEtsComponentExpression(node, fileName), undefined); 51461847f8eSopenharmony_ci } else if (ts.isIdentifier(node)) { 51561847f8eSopenharmony_ci return new ComponentAttrResult(this.recognizeEtsComponentAndAttributeApi(node, fileName), undefined); 51661847f8eSopenharmony_ci } else { 51761847f8eSopenharmony_ci return new ComponentAttrResult(undefined, undefined); 51861847f8eSopenharmony_ci } 51961847f8eSopenharmony_ci } 52061847f8eSopenharmony_ci 52161847f8eSopenharmony_ci /** 52261847f8eSopenharmony_ci * 识别ArkUI组件表达式 52361847f8eSopenharmony_ci * @param {ts.EtsComponentExpression} node 52461847f8eSopenharmony_ci * @param {string} fileName 52561847f8eSopenharmony_ci * @returns 52661847f8eSopenharmony_ci */ 52761847f8eSopenharmony_ci recognizeEtsComponentExpression(node, fileName) { 52861847f8eSopenharmony_ci // node.expression is component name Identifier 52961847f8eSopenharmony_ci const apiDecInfo = this.recognizeEtsComponentAndAttributeApi(node.expression, fileName); 53061847f8eSopenharmony_ci 53161847f8eSopenharmony_ci if (node.arguments) { 53261847f8eSopenharmony_ci this.recognizeComponentArguments(apiDecInfo, node.arguments, fileName); 53361847f8eSopenharmony_ci } 53461847f8eSopenharmony_ci 53561847f8eSopenharmony_ci if (node.body) { 53661847f8eSopenharmony_ci node.body.statements.forEach((statement) => { 53761847f8eSopenharmony_ci this.recognizeUIComponents(statement, fileName); 53861847f8eSopenharmony_ci }); 53961847f8eSopenharmony_ci } 54061847f8eSopenharmony_ci 54161847f8eSopenharmony_ci return apiDecInfo; 54261847f8eSopenharmony_ci } 54361847f8eSopenharmony_ci 54461847f8eSopenharmony_ci /** 54561847f8eSopenharmony_ci * 识别组件入参 54661847f8eSopenharmony_ci * @param {ApiDeclarationInformation} apiDecInfo 54761847f8eSopenharmony_ci * @param {ts.Node[]} args 54861847f8eSopenharmony_ci * @param {string} fileName 54961847f8eSopenharmony_ci */ 55061847f8eSopenharmony_ci recognizeComponentArguments(apiDecInfo, args, fileName) { 55161847f8eSopenharmony_ci // ForEach, LazyForEach 55261847f8eSopenharmony_ci if (apiDecInfo && this.forEachComponents.has(apiDecInfo.propertyName)) { 55361847f8eSopenharmony_ci args.forEach((arg, index) => { 55461847f8eSopenharmony_ci // itemGenerator 55561847f8eSopenharmony_ci if (index === 1) { 55661847f8eSopenharmony_ci this.visitUIRenderNode(arg.body ? arg.body : arg, fileName); 55761847f8eSopenharmony_ci } else { 55861847f8eSopenharmony_ci this.recognizeArgument(arg, fileName); 55961847f8eSopenharmony_ci } 56061847f8eSopenharmony_ci }); 56161847f8eSopenharmony_ci } else { 56261847f8eSopenharmony_ci this.recognizeArguments(args, fileName); 56361847f8eSopenharmony_ci } 56461847f8eSopenharmony_ci } 56561847f8eSopenharmony_ci 56661847f8eSopenharmony_ci /** 56761847f8eSopenharmony_ci * 识别参数中的API 56861847f8eSopenharmony_ci * @param {ts.Node[]} args 56961847f8eSopenharmony_ci * @param {string} fileName 57061847f8eSopenharmony_ci */ 57161847f8eSopenharmony_ci recognizeArguments(args, fileName) { 57261847f8eSopenharmony_ci args.forEach((arg) => { 57361847f8eSopenharmony_ci this.recognizeArgument(arg, fileName); 57461847f8eSopenharmony_ci }); 57561847f8eSopenharmony_ci } 57661847f8eSopenharmony_ci 57761847f8eSopenharmony_ci recognizeArgument(node, fileName) { 57861847f8eSopenharmony_ci if (!node) { 57961847f8eSopenharmony_ci return; 58061847f8eSopenharmony_ci } 58161847f8eSopenharmony_ci this.recognizeNormal(node, fileName); 58261847f8eSopenharmony_ci ts.forEachChild(node, (child) => { 58361847f8eSopenharmony_ci this.recognizeArgument(child, fileName); 58461847f8eSopenharmony_ci }); 58561847f8eSopenharmony_ci } 58661847f8eSopenharmony_ci 58761847f8eSopenharmony_ci 58861847f8eSopenharmony_ci /** 58961847f8eSopenharmony_ci * 获取组件或属性的API详情 59061847f8eSopenharmony_ci * 59161847f8eSopenharmony_ci * @param {ts.Identifier} node 59261847f8eSopenharmony_ci * @param {string} fileName 59361847f8eSopenharmony_ci * @returns {ApiDeclarationInformation | undefined} apiDecInfo 59461847f8eSopenharmony_ci */ 59561847f8eSopenharmony_ci recognizeEtsComponentAndAttributeApi(node, fileName) { 59661847f8eSopenharmony_ci // recognize component 59761847f8eSopenharmony_ci const apiDecInfo = this.recognizeApiWithNode(node, fileName, 59861847f8eSopenharmony_ci (node) => ts.isPropertyAccessExpression(node) ? node.name.getStart() : node.getStart()); 59961847f8eSopenharmony_ci return apiDecInfo; 60061847f8eSopenharmony_ci } 60161847f8eSopenharmony_ci 60261847f8eSopenharmony_ci /** 60361847f8eSopenharmony_ci * 通过语义分析,识别继承关系中的系统API 60461847f8eSopenharmony_ci * 60561847f8eSopenharmony_ci * @param {ts.ClassDeclaration | ts.InterfaceDeclaration} node 60661847f8eSopenharmony_ci * @param {ts.ClassDeclaration|ts.InterfaceDeclaration} node 60761847f8eSopenharmony_ci */ 60861847f8eSopenharmony_ci recognizeHeritageClauses(node, fileName) { 60961847f8eSopenharmony_ci if (!node.heritageClauses) { 61061847f8eSopenharmony_ci return; 61161847f8eSopenharmony_ci } 61261847f8eSopenharmony_ci const nodeType = this.typeChecker.getTypeAtLocation(node); 61361847f8eSopenharmony_ci const nodeSymbol = nodeType.getSymbol(); 61461847f8eSopenharmony_ci if (!nodeSymbol.members) { 61561847f8eSopenharmony_ci return; 61661847f8eSopenharmony_ci } 61761847f8eSopenharmony_ci const heritagePropertyMap = this.collectAllHeritageMethods(node); 61861847f8eSopenharmony_ci if (!nodeSymbol.valueDeclaration) { 61961847f8eSopenharmony_ci return; 62061847f8eSopenharmony_ci } 62161847f8eSopenharmony_ci if (!nodeSymbol.valueDeclaration.heritageClauses) { 62261847f8eSopenharmony_ci return; 62361847f8eSopenharmony_ci } 62461847f8eSopenharmony_ci if (heritagePropertyMap.size === 0) { 62561847f8eSopenharmony_ci const extendNodes = nodeSymbol.valueDeclaration.heritageClauses[0].types; 62661847f8eSopenharmony_ci this.getExtendClassPropertyMap(extendNodes, heritagePropertyMap); 62761847f8eSopenharmony_ci } 62861847f8eSopenharmony_ci if (heritagePropertyMap === 0) { 62961847f8eSopenharmony_ci return; 63061847f8eSopenharmony_ci } 63161847f8eSopenharmony_ci nodeSymbol.members.forEach((memberSymbol, memberName) => { 63261847f8eSopenharmony_ci if (heritagePropertyMap.has(memberName)) { 63361847f8eSopenharmony_ci const apiDecInfo = this.getSdkApiDeclarationWithSymbol(heritagePropertyMap.get(memberName), undefined); 63461847f8eSopenharmony_ci if (apiDecInfo) { 63561847f8eSopenharmony_ci apiDecInfo.setPosition(ts.getLineAndCharacterOfPosition(node.getSourceFile(), memberSymbol.valueDeclaration.getStart())); 63661847f8eSopenharmony_ci apiDecInfo.setSourceFileName(fileName); 63761847f8eSopenharmony_ci this.addApiInformation(apiDecInfo); 63861847f8eSopenharmony_ci } 63961847f8eSopenharmony_ci } 64061847f8eSopenharmony_ci }); 64161847f8eSopenharmony_ci } 64261847f8eSopenharmony_ci 64361847f8eSopenharmony_ci /** 64461847f8eSopenharmony_ci * 通过向上查找继承的节点,收集多次继承情况下的API 64561847f8eSopenharmony_ci * @param {ts.Node} extendNodes 64661847f8eSopenharmony_ci * @param {Map} extendClassPropertyMap 64761847f8eSopenharmony_ci */ 64861847f8eSopenharmony_ci getExtendClassPropertyMap(extendNodes, extendClassPropertyMap) { 64961847f8eSopenharmony_ci extendNodes.forEach(extendNode => { 65061847f8eSopenharmony_ci const extendNodeType = this.typeChecker.getTypeAtLocation(extendNode); 65161847f8eSopenharmony_ci if (!extendNodeType) { 65261847f8eSopenharmony_ci return; 65361847f8eSopenharmony_ci } 65461847f8eSopenharmony_ci const extendNodeSymbol = extendNodeType.getSymbol(); 65561847f8eSopenharmony_ci if (!extendNodeSymbol) { 65661847f8eSopenharmony_ci return; 65761847f8eSopenharmony_ci } 65861847f8eSopenharmony_ci const valueDeclaration = extendNodeSymbol.declarations[0]; 65961847f8eSopenharmony_ci if (valueDeclaration && !this.isSdkApi(valueDeclaration.getSourceFile().fileName) && extendNodeSymbol.valueDeclaration && 66061847f8eSopenharmony_ci extendNodeSymbol.valueDeclaration.heritageClauses) { 66161847f8eSopenharmony_ci const parentNodes = extendNodeSymbol.valueDeclaration.heritageClauses[0].types; 66261847f8eSopenharmony_ci this.getExtendClassPropertyMap(parentNodes, extendClassPropertyMap); 66361847f8eSopenharmony_ci } else { 66461847f8eSopenharmony_ci extendNodeSymbol.members.forEach((memberSymbol, memberName) => { 66561847f8eSopenharmony_ci extendClassPropertyMap.set(memberName, memberSymbol); 66661847f8eSopenharmony_ci }); 66761847f8eSopenharmony_ci } 66861847f8eSopenharmony_ci }); 66961847f8eSopenharmony_ci } 67061847f8eSopenharmony_ci 67161847f8eSopenharmony_ci /** 67261847f8eSopenharmony_ci * 搜集所有父类(属于SDK中的API)的方法和属性。 67361847f8eSopenharmony_ci * 67461847f8eSopenharmony_ci * @param {ts.Node} node 67561847f8eSopenharmony_ci * @returns Map 67661847f8eSopenharmony_ci */ 67761847f8eSopenharmony_ci collectAllHeritageMethods(node) { 67861847f8eSopenharmony_ci const heritageMembers = new Map(); 67961847f8eSopenharmony_ci if (!node.heritageClauses) { 68061847f8eSopenharmony_ci return heritageMembers; 68161847f8eSopenharmony_ci } 68261847f8eSopenharmony_ci node.heritageClauses.forEach((heritage) => { 68361847f8eSopenharmony_ci heritage.types.forEach((child) => { 68461847f8eSopenharmony_ci const childSymbol = this.typeChecker.getSymbolAtLocation(child.expression); 68561847f8eSopenharmony_ci if (!childSymbol) { 68661847f8eSopenharmony_ci return; 68761847f8eSopenharmony_ci } 68861847f8eSopenharmony_ci const type = this.typeChecker.getTypeOfSymbolAtLocation(childSymbol, child); 68961847f8eSopenharmony_ci const typeSymbol = type.getSymbol(); 69061847f8eSopenharmony_ci if (!typeSymbol) { 69161847f8eSopenharmony_ci return; 69261847f8eSopenharmony_ci } 69361847f8eSopenharmony_ci if (!typeSymbol && childSymbol.members) { 69461847f8eSopenharmony_ci this.setHeritageMembersFroMmembers(heritageMembers, childSymbol.members); 69561847f8eSopenharmony_ci return; 69661847f8eSopenharmony_ci } 69761847f8eSopenharmony_ci const valueDeclaration = typeSymbol.valueDeclaration; 69861847f8eSopenharmony_ci if (!valueDeclaration || !this.isSdkApi(valueDeclaration.getSourceFile().fileName)) { 69961847f8eSopenharmony_ci return; 70061847f8eSopenharmony_ci } 70161847f8eSopenharmony_ci this.setHeritageMembersFroMmembers(heritageMembers, typeSymbol.members); 70261847f8eSopenharmony_ci }); 70361847f8eSopenharmony_ci }); 70461847f8eSopenharmony_ci return heritageMembers; 70561847f8eSopenharmony_ci } 70661847f8eSopenharmony_ci 70761847f8eSopenharmony_ci /** 70861847f8eSopenharmony_ci * 搜集所有父类(属于SDK中的API)的方法和属性。 70961847f8eSopenharmony_ci * 71061847f8eSopenharmony_ci * @param {Map} heritageMembers 71161847f8eSopenharmony_ci * @param {ts.NodeArray} members 71261847f8eSopenharmony_ci */ 71361847f8eSopenharmony_ci setHeritageMembersFroMmembers(heritageMembers, members) { 71461847f8eSopenharmony_ci members.forEach((memberSymbol, memberName) => { 71561847f8eSopenharmony_ci heritageMembers.set(memberName, memberSymbol); 71661847f8eSopenharmony_ci }); 71761847f8eSopenharmony_ci } 71861847f8eSopenharmony_ci 71961847f8eSopenharmony_ci /** 72061847f8eSopenharmony_ci * 解析属性访问 72161847f8eSopenharmony_ci * 72261847f8eSopenharmony_ci * @param {ts.PropertyAccessExpression} node 72361847f8eSopenharmony_ci */ 72461847f8eSopenharmony_ci recognizePropertyAccessExpression(node, fileName) { 72561847f8eSopenharmony_ci return this.recognizeApiWithNode(node, fileName, (node) => node.name.getStart()); 72661847f8eSopenharmony_ci } 72761847f8eSopenharmony_ci 72861847f8eSopenharmony_ci /** 72961847f8eSopenharmony_ci * 获取 export {xx} 中xx的定义 73061847f8eSopenharmony_ci * @param {ts.Symbol} symbol 73161847f8eSopenharmony_ci */ 73261847f8eSopenharmony_ci getAliasExcludesRealValueDeclarations(symbol) { 73361847f8eSopenharmony_ci const symbolName = symbol.escapedName; 73461847f8eSopenharmony_ci const sourceFile = symbol.declarations[0].getSourceFile(); 73561847f8eSopenharmony_ci const realSymbol = sourceFile.locals ? sourceFile.locals.get(symbolName) : undefined; 73661847f8eSopenharmony_ci return realSymbol ? realSymbol.valueDeclaration : undefined; 73761847f8eSopenharmony_ci } 73861847f8eSopenharmony_ci 73961847f8eSopenharmony_ci getApiRawText(node) { 74061847f8eSopenharmony_ci switch (node.kind) { 74161847f8eSopenharmony_ci case ts.SyntaxKind.ClassDeclaration: 74261847f8eSopenharmony_ci return `class ${node.name ? node.name.getText() : ''}`; 74361847f8eSopenharmony_ci case ts.SyntaxKind.InterfaceDeclaration: 74461847f8eSopenharmony_ci return `interface ${node.name ? node.name.getText() : ''}`; 74561847f8eSopenharmony_ci case ts.SyntaxKind.EnumDeclaration: 74661847f8eSopenharmony_ci return `enum ${node.name ? node.name.getText() : ''}`; 74761847f8eSopenharmony_ci case ts.SyntaxKind.ModuleDeclaration: 74861847f8eSopenharmony_ci return `namespace ${node.name ? node.name.getText() : ''}`; 74961847f8eSopenharmony_ci case ts.SyntaxKind.StructDeclaration: 75061847f8eSopenharmony_ci return `struct ${node.name ? node.name.getText() : ''}`; 75161847f8eSopenharmony_ci case node.getText() === 'AsyncCallback' || node.getText() === 'Callback': 75261847f8eSopenharmony_ci return ''; 75361847f8eSopenharmony_ci default: 75461847f8eSopenharmony_ci return node.getText(); 75561847f8eSopenharmony_ci } 75661847f8eSopenharmony_ci } 75761847f8eSopenharmony_ci 75861847f8eSopenharmony_ci getApiTypeName(node) { 75961847f8eSopenharmony_ci if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isEnumDeclaration(node) || 76061847f8eSopenharmony_ci ts.isModuleDeclaration(node)) { 76161847f8eSopenharmony_ci return node.name ? node.name.getText() : ''; 76261847f8eSopenharmony_ci } 76361847f8eSopenharmony_ci return undefined; 76461847f8eSopenharmony_ci } 76561847f8eSopenharmony_ci 76661847f8eSopenharmony_ci /** 76761847f8eSopenharmony_ci * 获取节点定义在哪个文件哪个类型下。 76861847f8eSopenharmony_ci * 76961847f8eSopenharmony_ci * @param {ts.Symbol} type 77061847f8eSopenharmony_ci */ 77161847f8eSopenharmony_ci getSdkApiDeclarationWithSymbol(symbol, node, useDeclarations) { 77261847f8eSopenharmony_ci const sourceSymbol = symbol; 77361847f8eSopenharmony_ci let valudeDec = sourceSymbol && sourceSymbol.valueDeclaration ? sourceSymbol.valueDeclaration : 77461847f8eSopenharmony_ci (sourceSymbol.flags & ts.SymbolFlags.AliasExcludes ? this.getAliasExcludesRealValueDeclarations(symbol) : undefined); 77561847f8eSopenharmony_ci valudeDec = !valudeDec && useDeclarations ? symbol.declarations[0] : valudeDec; 77661847f8eSopenharmony_ci if (!valudeDec) { 77761847f8eSopenharmony_ci return undefined; 77861847f8eSopenharmony_ci } 77961847f8eSopenharmony_ci if (valudeDec.kind === ts.SyntaxKind.TypeParameter) { 78061847f8eSopenharmony_ci return undefined; 78161847f8eSopenharmony_ci } 78261847f8eSopenharmony_ci const sourceFile = valudeDec.getSourceFile(); 78361847f8eSopenharmony_ci if (!this.isSdkApi(sourceFile.fileName)) { 78461847f8eSopenharmony_ci return undefined; 78561847f8eSopenharmony_ci } 78661847f8eSopenharmony_ci let apiDecInfo = undefined; 78761847f8eSopenharmony_ci if (symbol.declarations.length > 1) { 78861847f8eSopenharmony_ci apiDecInfo = this.getSdkApiFromMultiDeclarations(symbol, node); 78961847f8eSopenharmony_ci } 79061847f8eSopenharmony_ci return apiDecInfo ? apiDecInfo : this.getSdkApiFromValueDeclaration(valudeDec); 79161847f8eSopenharmony_ci } 79261847f8eSopenharmony_ci 79361847f8eSopenharmony_ci getSdkApiFromMultiDeclarations(symbol, node) { 79461847f8eSopenharmony_ci if (!node) { 79561847f8eSopenharmony_ci return undefined; 79661847f8eSopenharmony_ci } 79761847f8eSopenharmony_ci let callExpressionNode = node; 79861847f8eSopenharmony_ci while (callExpressionNode && !ts.isCallExpression(callExpressionNode)) { 79961847f8eSopenharmony_ci callExpressionNode = callExpressionNode.parent; 80061847f8eSopenharmony_ci } 80161847f8eSopenharmony_ci if (!callExpressionNode) { 80261847f8eSopenharmony_ci return undefined; 80361847f8eSopenharmony_ci } 80461847f8eSopenharmony_ci const matchedDec = this.findBestMatchedDeclaration(callExpressionNode, symbol); 80561847f8eSopenharmony_ci if (!matchedDec) { 80661847f8eSopenharmony_ci return undefined; 80761847f8eSopenharmony_ci } 80861847f8eSopenharmony_ci return this.getSdkApiFromValueDeclaration(matchedDec); 80961847f8eSopenharmony_ci } 81061847f8eSopenharmony_ci 81161847f8eSopenharmony_ci /** 81261847f8eSopenharmony_ci * 查找参数个数匹配,参数类型匹配的API 81361847f8eSopenharmony_ci * @param {number} argumentLength 81461847f8eSopenharmony_ci * @param {ts.Symbol} symbol 81561847f8eSopenharmony_ci * @returns api declaration node. 81661847f8eSopenharmony_ci */ 81761847f8eSopenharmony_ci findBestMatchedDeclaration(callExpressionNode, symbol) { 81861847f8eSopenharmony_ci const callExpArgLen = callExpressionNode.arguments.length; 81961847f8eSopenharmony_ci if (callExpArgLen === 0) { 82061847f8eSopenharmony_ci return undefined; 82161847f8eSopenharmony_ci } 82261847f8eSopenharmony_ci let matchedDecs = []; 82361847f8eSopenharmony_ci for (let dec of symbol.declarations) { 82461847f8eSopenharmony_ci if (dec.parameters && dec.parameters.length === callExpArgLen) { 82561847f8eSopenharmony_ci matchedDecs.push(dec); 82661847f8eSopenharmony_ci } 82761847f8eSopenharmony_ci } 82861847f8eSopenharmony_ci if (matchedDecs.length === 1) { 82961847f8eSopenharmony_ci return matchedDecs[0]; 83061847f8eSopenharmony_ci } 83161847f8eSopenharmony_ci if ('on' === callExpressionNode.expression.name.getText()) { 83261847f8eSopenharmony_ci return this.findBestMatchedApi(callExpressionNode, matchedDecs); 83361847f8eSopenharmony_ci } 83461847f8eSopenharmony_ci const lastArgument = callExpressionNode.arguments[callExpArgLen - 1]; 83561847f8eSopenharmony_ci if (this.isAsyncCallbackCallExp(lastArgument)) { 83661847f8eSopenharmony_ci matchedDecs = matchedDecs.filter((value) => { 83761847f8eSopenharmony_ci return this.isAsyncCallbackApi(value); 83861847f8eSopenharmony_ci }); 83961847f8eSopenharmony_ci } else { 84061847f8eSopenharmony_ci matchedDecs = matchedDecs.filter((value) => { 84161847f8eSopenharmony_ci return !this.isAsyncCallbackApi(value); 84261847f8eSopenharmony_ci }); 84361847f8eSopenharmony_ci } 84461847f8eSopenharmony_ci return matchedDecs.length > 0 ? matchedDecs[0] : undefined; 84561847f8eSopenharmony_ci } 84661847f8eSopenharmony_ci 84761847f8eSopenharmony_ci /** 84861847f8eSopenharmony_ci * 通过匹配type字符串找到正确的API 84961847f8eSopenharmony_ci * 85061847f8eSopenharmony_ci * @param { ts.Node } callExpressionNode 85161847f8eSopenharmony_ci * @param { Array } matchedDecs 85261847f8eSopenharmony_ci * @returns 85361847f8eSopenharmony_ci */ 85461847f8eSopenharmony_ci findBestMatchedApi(callExpressionNode, matchedDecs) { 85561847f8eSopenharmony_ci let apiNode = undefined; 85661847f8eSopenharmony_ci if (ts.isStringLiteral(callExpressionNode.arguments[0])) { 85761847f8eSopenharmony_ci const useType = callExpressionNode.arguments[0].text; 85861847f8eSopenharmony_ci for (let i = 0; i < matchedDecs.length; i++) { 85961847f8eSopenharmony_ci const matchDec = matchedDecs[i]; 86061847f8eSopenharmony_ci const apiSubscribeTypes = this.getSubscribeApiType(matchDec.parameters[0].type); 86161847f8eSopenharmony_ci if (apiSubscribeTypes.has(useType)) { 86261847f8eSopenharmony_ci apiNode = matchDec; 86361847f8eSopenharmony_ci } 86461847f8eSopenharmony_ci } 86561847f8eSopenharmony_ci } 86661847f8eSopenharmony_ci 86761847f8eSopenharmony_ci if (!apiNode) { 86861847f8eSopenharmony_ci apiNode = matchedDecs[0]; 86961847f8eSopenharmony_ci } 87061847f8eSopenharmony_ci return apiNode; 87161847f8eSopenharmony_ci } 87261847f8eSopenharmony_ci 87361847f8eSopenharmony_ci getSubscribeApiType(typeNode) { 87461847f8eSopenharmony_ci const literalTypeSet = new Set(); 87561847f8eSopenharmony_ci if (ts.isLiteralTypeNode(typeNode)) { 87661847f8eSopenharmony_ci literalTypeSet.add(typeNode.literal.text); 87761847f8eSopenharmony_ci } else if (ts.isUnionTypeNode(typeNode)) { 87861847f8eSopenharmony_ci typeNode.types.forEach(type => { 87961847f8eSopenharmony_ci literalTypeSet.add(type.literal.text); 88061847f8eSopenharmony_ci }); 88161847f8eSopenharmony_ci } 88261847f8eSopenharmony_ci return literalTypeSet; 88361847f8eSopenharmony_ci } 88461847f8eSopenharmony_ci 88561847f8eSopenharmony_ci isAsyncCallbackCallExp(node) { 88661847f8eSopenharmony_ci const type = this.typeChecker.getTypeAtLocation(node); 88761847f8eSopenharmony_ci if (!type || !type.symbol || !type.symbol.valueDeclaration) { 88861847f8eSopenharmony_ci return false; 88961847f8eSopenharmony_ci } 89061847f8eSopenharmony_ci const typeValueDec = type.symbol.valueDeclaration; 89161847f8eSopenharmony_ci return ts.isArrowFunction(typeValueDec) || ts.isMethodDeclaration(typeValueDec) || 89261847f8eSopenharmony_ci ts.isFunctionDeclaration(typeValueDec) || ts.isMethodSignature(typeValueDec) || 89361847f8eSopenharmony_ci ts.isFunctionExpression(typeValueDec); 89461847f8eSopenharmony_ci } 89561847f8eSopenharmony_ci 89661847f8eSopenharmony_ci isAsyncCallbackApi(declaration) { 89761847f8eSopenharmony_ci if (!declaration.parameters) { 89861847f8eSopenharmony_ci return false; 89961847f8eSopenharmony_ci } 90061847f8eSopenharmony_ci const lastArgument = declaration.parameters[declaration.parameters.length - 1]; 90161847f8eSopenharmony_ci const argumentType = this.typeChecker.getTypeAtLocation(lastArgument); 90261847f8eSopenharmony_ci if (argumentType && argumentType.symbol) { 90361847f8eSopenharmony_ci return argumentType.symbol.escapedName === 'AsyncCallback'; 90461847f8eSopenharmony_ci } else { 90561847f8eSopenharmony_ci if (!lastArgument.type || !lastArgument.type.typeName) { 90661847f8eSopenharmony_ci return false; 90761847f8eSopenharmony_ci } 90861847f8eSopenharmony_ci return 'AsyncCallback' === lastArgument.type.typeName.getText(); 90961847f8eSopenharmony_ci } 91061847f8eSopenharmony_ci } 91161847f8eSopenharmony_ci 91261847f8eSopenharmony_ci getSdkApiFromValueDeclaration(valudeDec) { 91361847f8eSopenharmony_ci const sourceFile = valudeDec.getSourceFile(); 91461847f8eSopenharmony_ci const apiInfo = new ApiDeclarationInformation(); 91561847f8eSopenharmony_ci const dtsPath = sourceFile.fileName.replace(this.systemRoot.replace(/\\/g, '/'), ''); 91661847f8eSopenharmony_ci apiInfo.setPropertyName(this.getMethodOrTypeName(valudeDec)); 91761847f8eSopenharmony_ci apiInfo.setApiRawText(this.getApiRawText(valudeDec)); 91861847f8eSopenharmony_ci apiInfo.setPackageName(this.getPackageName(sourceFile.fileName)); 91961847f8eSopenharmony_ci apiInfo.setSdkFileName(path.basename(sourceFile.fileName)); 92061847f8eSopenharmony_ci apiInfo.setTypeName(this.getApiTypeName(valudeDec)); 92161847f8eSopenharmony_ci apiInfo.setApiNode(valudeDec); 92261847f8eSopenharmony_ci apiInfo.setApiType(this.getApiType(valudeDec)); 92361847f8eSopenharmony_ci apiInfo.setDtsPath(this.formatDtsPath(dtsPath)); 92461847f8eSopenharmony_ci apiInfo.setCompletedText(this.getApiText(valudeDec)); 92561847f8eSopenharmony_ci 92661847f8eSopenharmony_ci if (ts.isSourceFile(valudeDec.parent) && ts.isFunctionDeclaration(valudeDec)) { 92761847f8eSopenharmony_ci apiInfo.setQualifiedTypeName('global'); 92861847f8eSopenharmony_ci } 92961847f8eSopenharmony_ci 93061847f8eSopenharmony_ci let curDeclaration = valudeDec.parent; 93161847f8eSopenharmony_ci while (!ts.isSourceFile(curDeclaration)) { 93261847f8eSopenharmony_ci const nodeName = this.getMethodOrTypeName(curDeclaration); 93361847f8eSopenharmony_ci if (nodeName) { 93461847f8eSopenharmony_ci apiInfo.setTypeName(nodeName); 93561847f8eSopenharmony_ci apiInfo.setQualifiedTypeName(nodeName); 93661847f8eSopenharmony_ci } 93761847f8eSopenharmony_ci curDeclaration = curDeclaration.parent; 93861847f8eSopenharmony_ci } 93961847f8eSopenharmony_ci 94061847f8eSopenharmony_ci const qualifiedName = apiInfo.qualifiedTypeName ? 94161847f8eSopenharmony_ci `${apiInfo.qualifiedTypeName}.${apiInfo.propertyName}` : `${apiInfo.propertyName}`; 94261847f8eSopenharmony_ci apiInfo.setQualifiedName(qualifiedName); 94361847f8eSopenharmony_ci return this.fillJSDocInformation(apiInfo, valudeDec); 94461847f8eSopenharmony_ci } 94561847f8eSopenharmony_ci 94661847f8eSopenharmony_ci getApiType(valudeDec) { 94761847f8eSopenharmony_ci let type = apiType.get(valudeDec.kind); 94861847f8eSopenharmony_ci if (ts.isPropertySignature(valudeDec) && valudeDec.type && ts.isFunctionTypeNode(valudeDec.type)) { 94961847f8eSopenharmony_ci type = 'method'; 95061847f8eSopenharmony_ci } 95161847f8eSopenharmony_ci return type; 95261847f8eSopenharmony_ci } 95361847f8eSopenharmony_ci 95461847f8eSopenharmony_ci getApiText(node) { 95561847f8eSopenharmony_ci switch (node.kind) { 95661847f8eSopenharmony_ci case ts.SyntaxKind.ClassDeclaration: 95761847f8eSopenharmony_ci return node.getText().split('{')[0]; 95861847f8eSopenharmony_ci case ts.SyntaxKind.InterfaceDeclaration: 95961847f8eSopenharmony_ci return node.getText().split('{')[0]; 96061847f8eSopenharmony_ci case ts.SyntaxKind.EnumDeclaration: 96161847f8eSopenharmony_ci return node.getText().split('{')[0]; 96261847f8eSopenharmony_ci case ts.SyntaxKind.ModuleDeclaration: 96361847f8eSopenharmony_ci return node.getText().split('{')[0]; 96461847f8eSopenharmony_ci case ts.SyntaxKind.StructDeclaration: 96561847f8eSopenharmony_ci return node.getText().split('{')[0]; 96661847f8eSopenharmony_ci default: 96761847f8eSopenharmony_ci return node.getText(); 96861847f8eSopenharmony_ci } 96961847f8eSopenharmony_ci } 97061847f8eSopenharmony_ci 97161847f8eSopenharmony_ci /** 97261847f8eSopenharmony_ci * 补充JsDoc中的信息。 97361847f8eSopenharmony_ci * 97461847f8eSopenharmony_ci * @param {ApiDeclarationInformation} apiInfo 97561847f8eSopenharmony_ci * @param {ts.Node} node 97661847f8eSopenharmony_ci * @returns 97761847f8eSopenharmony_ci */ 97861847f8eSopenharmony_ci fillJSDocInformation(apiInfo, node) { 97961847f8eSopenharmony_ci this.forEachJsDocTags(node, (tag) => { 98061847f8eSopenharmony_ci (this.fillDeprecatedInfo(tag, apiInfo) || this.fillUseInsteadInfo(tag, apiInfo)); 98161847f8eSopenharmony_ci }); 98261847f8eSopenharmony_ci if (!apiInfo.deprecated) { 98361847f8eSopenharmony_ci const thiz = this; 98461847f8eSopenharmony_ci function reachJsDocTag(tag) { 98561847f8eSopenharmony_ci thiz.fillDeprecatedInfo(tag, apiInfo); 98661847f8eSopenharmony_ci return apiInfo.deprecated; 98761847f8eSopenharmony_ci } 98861847f8eSopenharmony_ci 98961847f8eSopenharmony_ci function reachParent(parent) { 99061847f8eSopenharmony_ci thiz.forEachJsDocTags(parent, reachJsDocTag); 99161847f8eSopenharmony_ci return apiInfo.deprecated; 99261847f8eSopenharmony_ci } 99361847f8eSopenharmony_ci this.forEachNodeParent(node, reachParent); 99461847f8eSopenharmony_ci } 99561847f8eSopenharmony_ci return apiInfo; 99661847f8eSopenharmony_ci } 99761847f8eSopenharmony_ci 99861847f8eSopenharmony_ci fillUseInsteadInfo(tag, apiInfo) { 99961847f8eSopenharmony_ci if (tag.kind === ts.SyntaxKind.JSDocTag && 100061847f8eSopenharmony_ci tag.tagName.getText() === 'useinstead') { 100161847f8eSopenharmony_ci apiInfo.setUseInstead(tag.comment); 100261847f8eSopenharmony_ci return true; 100361847f8eSopenharmony_ci } 100461847f8eSopenharmony_ci return false; 100561847f8eSopenharmony_ci } 100661847f8eSopenharmony_ci 100761847f8eSopenharmony_ci fillDeprecatedInfo(tag, apiInfo) { 100861847f8eSopenharmony_ci if (tag.kind === ts.SyntaxKind.JSDocDeprecatedTag) { 100961847f8eSopenharmony_ci apiInfo.setDeprecated(tag.comment); 101061847f8eSopenharmony_ci return true; 101161847f8eSopenharmony_ci } 101261847f8eSopenharmony_ci return false; 101361847f8eSopenharmony_ci } 101461847f8eSopenharmony_ci 101561847f8eSopenharmony_ci forEachJsDocTags(node, callback) { 101661847f8eSopenharmony_ci if (!node.jsDoc || !callback) { 101761847f8eSopenharmony_ci return; 101861847f8eSopenharmony_ci } 101961847f8eSopenharmony_ci const latestJsDoc = node.jsDoc[node.jsDoc.length - 1]; 102061847f8eSopenharmony_ci if (!latestJsDoc.tags) { 102161847f8eSopenharmony_ci return; 102261847f8eSopenharmony_ci } 102361847f8eSopenharmony_ci for (const tag of latestJsDoc.tags) { 102461847f8eSopenharmony_ci if (callback(tag)) { 102561847f8eSopenharmony_ci break; 102661847f8eSopenharmony_ci }; 102761847f8eSopenharmony_ci }; 102861847f8eSopenharmony_ci } 102961847f8eSopenharmony_ci 103061847f8eSopenharmony_ci forEachNodeParent(node, callback) { 103161847f8eSopenharmony_ci if (!node || !callback) { 103261847f8eSopenharmony_ci return; 103361847f8eSopenharmony_ci } 103461847f8eSopenharmony_ci let curNode = node.parent; 103561847f8eSopenharmony_ci while (curNode) { 103661847f8eSopenharmony_ci if (callback(curNode)) { 103761847f8eSopenharmony_ci break; 103861847f8eSopenharmony_ci } 103961847f8eSopenharmony_ci curNode = curNode.parent; 104061847f8eSopenharmony_ci } 104161847f8eSopenharmony_ci } 104261847f8eSopenharmony_ci 104361847f8eSopenharmony_ci getMethodOrTypeName(node) { 104461847f8eSopenharmony_ci return node.name ? node.name.getText() : undefined; 104561847f8eSopenharmony_ci } 104661847f8eSopenharmony_ci 104761847f8eSopenharmony_ci getPackageName(filePath) { 104861847f8eSopenharmony_ci const isArkUI = FileSystem.isInDirectory(path.resolve(this.systemRoot, 'component'), filePath); 104961847f8eSopenharmony_ci return isArkUI ? 'ArkUI' : path.relative(this.systemRoot, filePath); 105061847f8eSopenharmony_ci } 105161847f8eSopenharmony_ci} 105261847f8eSopenharmony_ci 105361847f8eSopenharmony_ciconst apiType = new Map([ 105461847f8eSopenharmony_ci [ts.SyntaxKind.FunctionDeclaration, 'method'], 105561847f8eSopenharmony_ci [ts.SyntaxKind.MethodSignature, 'method'], 105661847f8eSopenharmony_ci [ts.SyntaxKind.MethodDeclaration, 'method'], 105761847f8eSopenharmony_ci [ts.SyntaxKind.EnumMember, 'enum_instance'], 105861847f8eSopenharmony_ci [ts.SyntaxKind.PropertySignature, 'field'], 105961847f8eSopenharmony_ci [ts.SyntaxKind.VariableStatement, 'constant'], 106061847f8eSopenharmony_ci [ts.SyntaxKind.VariableDeclaration, 'constant'], 106161847f8eSopenharmony_ci [ts.SyntaxKind.VariableDeclarationList, 'constant'], 106261847f8eSopenharmony_ci [ts.SyntaxKind.TypeAliasDeclaration, 'type'], 106361847f8eSopenharmony_ci [ts.SyntaxKind.ClassDeclaration, 'class'], 106461847f8eSopenharmony_ci [ts.SyntaxKind.InterfaceDeclaration, 'interface'], 106561847f8eSopenharmony_ci [ts.SyntaxKind.EnumDeclaration, 'enum_class'], 106661847f8eSopenharmony_ci [ts.SyntaxKind.PropertyDeclaration, 'field'] 106761847f8eSopenharmony_ci]); 106861847f8eSopenharmony_ci 106961847f8eSopenharmony_ciclass ComponentAttrResult { 107061847f8eSopenharmony_ci constructor(componentInfo, attrInfo) { 107161847f8eSopenharmony_ci this.componentInfo = componentInfo; 107261847f8eSopenharmony_ci this.attrInfo = attrInfo; 107361847f8eSopenharmony_ci } 107461847f8eSopenharmony_ci} 107561847f8eSopenharmony_ci 107661847f8eSopenharmony_ciclass ApiDeclarationInformation { 107761847f8eSopenharmony_ci constructor() { 107861847f8eSopenharmony_ci this.dtsName = ''; 107961847f8eSopenharmony_ci this.packageName = ''; 108061847f8eSopenharmony_ci this.propertyName = ''; 108161847f8eSopenharmony_ci this.qualifiedTypeName = ''; 108261847f8eSopenharmony_ci this.pos = ''; 108361847f8eSopenharmony_ci this.sourceFileName = ''; 108461847f8eSopenharmony_ci this.deprecated = ''; 108561847f8eSopenharmony_ci this.apiRawText = ''; 108661847f8eSopenharmony_ci this.qualifiedName = ''; 108761847f8eSopenharmony_ci this.useInstead = ''; 108861847f8eSopenharmony_ci this.typeName = ''; 108961847f8eSopenharmony_ci } 109061847f8eSopenharmony_ci 109161847f8eSopenharmony_ci setSdkFileName(fileName) { 109261847f8eSopenharmony_ci this.dtsName = fileName; 109361847f8eSopenharmony_ci } 109461847f8eSopenharmony_ci 109561847f8eSopenharmony_ci setPackageName(packageName) { 109661847f8eSopenharmony_ci this.packageName = packageName; 109761847f8eSopenharmony_ci } 109861847f8eSopenharmony_ci 109961847f8eSopenharmony_ci setPropertyName(propertyName) { 110061847f8eSopenharmony_ci this.propertyName = propertyName; 110161847f8eSopenharmony_ci } 110261847f8eSopenharmony_ci 110361847f8eSopenharmony_ci setQualifiedTypeName(typeName) { 110461847f8eSopenharmony_ci if (!this.qualifiedTypeName) { 110561847f8eSopenharmony_ci this.qualifiedTypeName = typeName; 110661847f8eSopenharmony_ci } else { 110761847f8eSopenharmony_ci this.qualifiedTypeName = `${typeName}.${this.qualifiedTypeName}`; 110861847f8eSopenharmony_ci } 110961847f8eSopenharmony_ci } 111061847f8eSopenharmony_ci 111161847f8eSopenharmony_ci setTypeName(typeName) { 111261847f8eSopenharmony_ci if (typeName && (!this.typeName || this.typeName === '')) { 111361847f8eSopenharmony_ci this.typeName = typeName; 111461847f8eSopenharmony_ci } 111561847f8eSopenharmony_ci } 111661847f8eSopenharmony_ci 111761847f8eSopenharmony_ci setPosition(pos) { 111861847f8eSopenharmony_ci const { line, character } = pos; 111961847f8eSopenharmony_ci this.pos = `${line + 1},${character + 1}`; 112061847f8eSopenharmony_ci } 112161847f8eSopenharmony_ci 112261847f8eSopenharmony_ci setSourceFileName(sourceFileName) { 112361847f8eSopenharmony_ci this.sourceFileName = sourceFileName; 112461847f8eSopenharmony_ci } 112561847f8eSopenharmony_ci 112661847f8eSopenharmony_ci /** 112761847f8eSopenharmony_ci * 设置废弃版本号 112861847f8eSopenharmony_ci * 112961847f8eSopenharmony_ci * @param {string} deprecated 113061847f8eSopenharmony_ci */ 113161847f8eSopenharmony_ci setDeprecated(deprecated) { 113261847f8eSopenharmony_ci const regExpResult = deprecated.match(/\s*since\s*(\d)+.*/); 113361847f8eSopenharmony_ci const RESULT_LENGTH = 2; 113461847f8eSopenharmony_ci if (regExpResult !== null && regExpResult.length === RESULT_LENGTH) { 113561847f8eSopenharmony_ci this.deprecated = regExpResult[1]; 113661847f8eSopenharmony_ci } 113761847f8eSopenharmony_ci } 113861847f8eSopenharmony_ci 113961847f8eSopenharmony_ci setApiRawText(apiRawText) { 114061847f8eSopenharmony_ci this.apiRawText = apiRawText.replace(/\;/g, ''); 114161847f8eSopenharmony_ci } 114261847f8eSopenharmony_ci 114361847f8eSopenharmony_ci setQualifiedName(qualifiedName) { 114461847f8eSopenharmony_ci this.qualifiedName = qualifiedName; 114561847f8eSopenharmony_ci } 114661847f8eSopenharmony_ci 114761847f8eSopenharmony_ci setUseInstead(useInstead) { 114861847f8eSopenharmony_ci this.useInstead = useInstead; 114961847f8eSopenharmony_ci } 115061847f8eSopenharmony_ci 115161847f8eSopenharmony_ci setComponentName(componentName) { 115261847f8eSopenharmony_ci this.componentName = componentName; 115361847f8eSopenharmony_ci } 115461847f8eSopenharmony_ci 115561847f8eSopenharmony_ci setApiNode(node) { 115661847f8eSopenharmony_ci this.apiNode = node; 115761847f8eSopenharmony_ci } 115861847f8eSopenharmony_ci 115961847f8eSopenharmony_ci setApiType(apiType) { 116061847f8eSopenharmony_ci this.apiType = apiType; 116161847f8eSopenharmony_ci } 116261847f8eSopenharmony_ci 116361847f8eSopenharmony_ci setDtsPath(dtsPath) { 116461847f8eSopenharmony_ci this.dtsPath = dtsPath; 116561847f8eSopenharmony_ci } 116661847f8eSopenharmony_ci 116761847f8eSopenharmony_ci setCompletedText(completedText) { 116861847f8eSopenharmony_ci this.apiText = completedText; 116961847f8eSopenharmony_ci } 117061847f8eSopenharmony_ci} 117161847f8eSopenharmony_ci 117261847f8eSopenharmony_ciexports.SystemApiRecognizer = SystemApiRecognizer;