diff --git a/build-tools/delete_systemapi_plugin.js b/build-tools/delete_systemapi_plugin.js index a482757f44f6b9884477fd4e061b4ed287db7684..21b28b0f54590f42d4de8edb05307389174120ed 100644 --- a/build-tools/delete_systemapi_plugin.js +++ b/build-tools/delete_systemapi_plugin.js @@ -22,10 +22,15 @@ let lastNoteStr = ''; let lastNodeName = ''; let etsType = 'ets'; let componentEtsFiles = []; -let componentEtsDeleteFiles = ['plugincomponent', 'uiextensioncomponent']; +let componentEtsDeleteFiles = ['plugincomponent', 'uiextensioncomponent', 'effectcomponent', 'inspector']; const referencesMap = new Map(); const referencesModuleMap = new Map(); const kitFileNeedDeleteMap = new Map(); +const ARKTS_FLAG = 'use static'; +const COMPILER_OPTIONS = { + target: ts.ScriptTarget.ES2017, + etsAnnotationsEnable: true +}; /** * @enum {string} references地址的切换类型 */ @@ -48,39 +53,6 @@ const METHOD_KIND = [ ts.SyntaxKind.Constructor ]; -const regJSDOCStr = `\\s*\\/\\*\\*(?:(?!\\/\\*\\*)[\\s\\S])*?`; - -const STATIC_API_DELETE_RULES = new Map([[ - 'arkui/component/common.static.d.ets', [ - `${regJSDOCStr}declare enum TransitionHierarchyStrategy.*ADAPTIVE = 1.*?\\n\\}.*?\\n`, - `${regJSDOCStr}declare interface PixelMapMock.*release\\(\\): void.*?\\n\\}.*?\\n`, - `${regJSDOCStr}declare interface PointLightStyle.*bloom\\?: number.*?\\n\\}.*?\\n`, - `${regJSDOCStr}declare interface LightSource.*color\\?: ResourceColor.*?\\n\\}.*?\\n` - ]], [ - 'arkui/component/embeddedComponent.static.d.ets', [ - `${regJSDOCStr}@memo.*\\): EmbeddedComponentAttribute` - ]], [ - 'arkui/component/list.static.d.ets', [ - `${regJSDOCStr}export declare enum ChainEdgeEffect.*STRETCH.*?\\n\\}.*?\\n`, - `${regJSDOCStr}export declare interface ChainAnimationOptions.*damping\\?: number.*?\\n\\}.*?\\n` - ]], [ - 'arkui/component/pluginComponent.static.d.ets', []], [ - 'arkui/component/richEditor.static.d.ets', []], [ - 'arkui/component/textInput.static.d.ets', []], [ - 'arkui/component/uiExtensionComponent.static.d.ets', []], [ - 'arkui/component/xcomponent.static.d.ets', []]]); - -const STATIC_IMPORT_DELETE_RULES = new Map([[ - 'arkui/component/common.static.d.ets', [{ - reg: /(import\s*\{.*)IlluminatedType(,\s)?(.*from.*enums)/g, replaceValue: '$1$3' - }]], [ - 'arkui/component/pluginComponent.static.d.ets', [{ - reg: /.*/sg, replaceValue: '' - }]], [ - 'arkui/component/uiExtensionComponent.static.d.ets', [{ - reg: /.*/sg, replaceValue: '' - }]]]); - function start() { const program = new commander.Command(); program @@ -346,9 +318,6 @@ function processFileNameWithoutExt(filePath) { .replace(/\.ets$/g, ''); } -function isArkTsSpecialSyntax(content) { - return /\@memo|(? { - let content = fs.readFileSync(url, 'utf-8'); // 文件内容 - if (etsType === 'ets2') { - writeFile(url, content); - return; - } - const relativePath = path.relative(inputDir, url); - if (STATIC_API_DELETE_RULES.has(relativePath.replace(/\\/g, '/'))) { - const content = processStaticFile(url); - writeFile(url, content); - return; - } const apiBaseName = path.basename(url); - if (isArkTsSpecialSyntax(content)) { - writeFile(url, content); - return; - } + let content = fs.readFileSync(url, 'utf-8'); // 文件内容 let isTransformer = /\.d\.ts/.test(apiBaseName) || /\.d\.ets/.test(apiBaseName); if (/\.json/.test(url) || apiBaseName === 'index-full.d.ts') { isTransformer = false; @@ -397,40 +352,13 @@ function tsTransform(utFiles, callback) { } } ts.transpileModule(content, { - compilerOptions: { - target: ts.ScriptTarget.ES2017, - }, + compilerOptions: COMPILER_OPTIONS, fileName: fileName, transformers: { before: [callback(url)] }, }); }); } -/** - * - * @param {string} url - * @returns - */ -function processStaticFile(url) { - const relativePath = path.relative(inputDir, url).replace(/\\/g, '/'); - let content = fs.readFileSync(url, 'utf-8'); // 文件内容 - const regNodeList = STATIC_API_DELETE_RULES.get(relativePath); - regNodeList.forEach(regRule => { - const regSystemApi = new RegExp(regRule, 'sg'); - content = content.replace(regSystemApi, '\n'); - }); - const replaceSignNode = new RegExp( - '\\s*\\/\\*\\*(?:(?!\\/\\*\\*)[\\s\\S])*?@systemapi[\\s\\S]*?\\*\\/.*?\\r?\\n.*?\\r?\\n', - 'g' - ); - content = content.replace(replaceSignNode, '\n'); - const regImportList = STATIC_IMPORT_DELETE_RULES.get(relativePath) || []; - regImportList.forEach(regNode => { - content = content.replace(regNode.reg, regNode.replaceValue); - }); - return content; -} - /** * 切换references或者references中path的格式 * @param {string} references references或者references中的path @@ -597,102 +525,143 @@ function visitEachChild(context, node) { /** * 每个文件处理前回调函数第二个 * @param {string} url 文件路径 + * @param {string} copyrightMessage 版权头注释 + * @param {string} fileAndKitComment 文件kit注释 + * @param {boolean} firstNodeIsStatic 第一个节点是否为use static * @returns {Function} */ -function formatImportDeclaration(url, copyrightMessage = '', isCopyrightDeleted = false) { +function formatImportDeclaration(url, copyrightMessage = '', fileAndKitComment = '', firstNodeIsStatic = false) { + const allIdentifierSet = new Set([]); return (context) => { - const allIdentifierSet = new Set([]); return (node) => { sourceFile = node; - collectAllIdentifier(node); // 获取所有标识符 + collectAllIdentifier(context, node, allIdentifierSet); // 获取所有标识符 formatValue = formatAllNodes(url, node, allIdentifierSet); // 获取所有节点 node = visitEachChild(context, formatValue.node); const referencesMessage = formatValue.referencesMessage; - if (formatValue.isCopyrightDeleted) { - copyrightMessage = formatValue.copyrightMessage; - isCopyrightDeleted = formatValue.isCopyrightDeleted; + if (isEmptyFile(node)) { + return ts.factory.createSourceFile([], ts.SyntaxKind.EndOfFileToken, ts.NodeFlags.None); } - if (!isEmptyFile(node)) { - const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); - let result = printer.printNode(ts.EmitHint.Unspecified, node, sourceFile); - if (isCopyrightDeleted) { - // 当第一个节点被删除时会同步删除整个文件jsdoc - result = copyrightMessage + '\n' + result; - } - copyrightMessage = node.getFullText().replace(node.getText(), ''); - if (referencesMessage) { - // 将references写入文件 - result = - result.substring(0, copyrightMessage.length) + - '\n' + - referencesMessage + - result.substring(copyrightMessage.length); - } - result = removeSystemapiDoc(result); - writeFile(url, result); + const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); + let result = printer.printNode(ts.EmitHint.Unspecified, node, sourceFile); + result = collectCopyrightMessage(result, copyrightMessage, fileAndKitComment, firstNodeIsStatic); + copyrightMessage = node.getFullText().replace(node.getText(), ''); + if (referencesMessage) { // 将references写入文件 + result = result.substring(0, copyrightMessage.length) + '\n' + referencesMessage + + result.substring(copyrightMessage.length); } + result = removeSystemapiDoc(result); + writeFile(url, result); return ts.factory.createSourceFile([], ts.SyntaxKind.EndOfFileToken, ts.NodeFlags.None); }; - function collectAllIdentifier(node) { - if (ts.isSourceFile(node) && node.statements) { - node.statements.forEach((stat) => { - if (!ts.isImportDeclaration(stat)) { - ts.visitEachChild(stat, collectAllNodes, context); - } - }); - } + }; +} + +function collectAllIdentifier(context, node, allIdentifierSet) { + if (!ts.isSourceFile(node) || !node.statements) { + return; + } + node.statements.forEach((stat) => { + if (stat.illegalDecorators) { + collectillegalNodes(ts.getAllDecorators(stat), allIdentifierSet); } - function collectAllNodes(node) { - if (ts.isIdentifier(node)) { - allIdentifierSet.add(node.escapedText.toString()); - } - return ts.visitEachChild(node, collectAllNodes, context); + if (!ts.isImportDeclaration(stat)) { + ts.visitEachChild(stat, collectAllNodes(context, allIdentifierSet), context); + } + }); +} + +function collectAllNodes(context, allIdentifierSet) { + return (node) => { + if (ts.isIdentifier(node)) { + allIdentifierSet.add(node.escapedText.toString()); } + return ts.visitEachChild(node, collectAllNodes(context, allIdentifierSet), context); }; } -function formatAllNodes(url, node, allIdentifierSet, copyrightMessage = '', isCopyrightDeleted = false) { +function collectillegalNodes(decorator, allIdentifierSet) { + decorator.forEach(decorator => { + allIdentifierSet.add(decorator.expression.escapedText.toString()); + }); +} + +/** + * 给result添加被systemapi裁剪掉的版权头信息和kit标签 + * @param {string} result 文件内容 + * @param {string} copyrightMessage 版权头注释 + * @param {string} fileAndKitComment 文件kit注释 + * @param {boolean} firstNodeIsStatic 第一个节点是否为use static + * @returns + */ +function collectCopyrightMessage(result, copyrightMessage, fileAndKitComment, firstNodeIsStatic) { + const newFileAndKitComment = getFileAndKitComment(result); + const newCopyrightMessage = getCopyrightComment(result); + let commentIndex = 0; + if (firstNodeIsStatic) { + const indexStatic = result.match(/use static.*\n/); + if (indexStatic) { + commentIndex = indexStatic.index + indexStatic[0].length; + } + } + if (newFileAndKitComment === '') { + result = + result.substring(0, commentIndex) + + fileAndKitComment + + '\n\n' + + result.substring(commentIndex); + } + if (newCopyrightMessage === '') { + // 多段注释中间需要换行 + result = + result.substring(0, commentIndex) + + copyrightMessage + + '\n\n' + + result.substring(commentIndex); + } + return result; +} + +function formatAllNodes(url, node, allIdentifierSet) { let referencesMessage = ''; let currReferencesModule = formatAllNodesReferences(url); - if (ts.isSourceFile(node) && node.statements) { - const newStatements = []; - node.statements.forEach((statement) => { - if (ts.isImportDeclaration(statement)) { - const importInfo = formatAllNodesImportDeclaration( - node, - statement, - url, - currReferencesModule, - allIdentifierSet - ); - if (importInfo.statement) { - newStatements.push(statement); - } else if (importInfo.isCopyrightDeleted) { - copyrightMessage = importInfo.copyrightMessage; - isCopyrightDeleted = importInfo.isCopyrightDeleted; - } - } else if (ts.isStructDeclaration(statement)) { - statement = ts.factory.updateStructDeclaration( - statement, - statement.modifiers, - statement.name, - statement.typeParameters, - statement.heritageClauses, - statement.members.slice(1) - ); - newStatements.push(statement); - } else { + if (!ts.isSourceFile(node) || !node.statements) { + return { node, referencesMessage }; + } + const newStatements = []; + node.statements.forEach((statement) => { + if (ts.isImportDeclaration(statement)) { + const importInfo = formatAllNodesImportDeclaration( + node, + statement, + url, + currReferencesModule, + allIdentifierSet + ); + if (importInfo) { newStatements.push(statement); } - }); - currReferencesModule.forEach((item) => { - if (item.isUsed) { - referencesMessage += item.reference + '\n'; - } - }); - node = ts.factory.updateSourceFile(node, newStatements); - } - return { node, referencesMessage, copyrightMessage, isCopyrightDeleted }; + } else if (ts.isStructDeclaration(statement)) { + statement = ts.factory.updateStructDeclaration( + statement, + statement.modifiers, + statement.name, + statement.typeParameters, + statement.heritageClauses, + statement.members.slice(1) + ); + newStatements.push(statement); + } else { + newStatements.push(statement); + } + }); + currReferencesModule.forEach((item) => { + if (item.isUsed) { + referencesMessage += item.reference + '\n'; + } + }); + node = ts.factory.updateSourceFile(node, newStatements); + return { node, referencesMessage }; } function hasCopyright(node) { @@ -733,96 +702,130 @@ function formatAllNodesReferences(url) { * @param {ts.node} node 当前节点 * @param {ts.ImportDeclaration} statement 导入节点 * @param {string} url 文件路径 - * @param {string} url 文件路径 - * @param {Set} allIdentifierSet 该文件的所有Identifier关键字 - * @returns {{statement:ts.ImportDeclaration,copyrightMessage:string,isCopyrightDeleted:boolean}} statement 处理完成的导入节点、copyrightMessage + * @param {Array} currReferencesModule 该文件的所有Identifier关键字 + * @param {Set} allIdentifierSet 该文件的所有Identifier关键字 + * @returns {ts.ImportDeclaration|undefined} statement 处理完成的导入节点、copyrightMessage */ function formatAllNodesImportDeclaration(node, statement, url, currReferencesModule, allIdentifierSet) { - // 是import节点 import { AsyncCallback } from './@ohos.base'; - const clauseSet = new Set([]); - if (statement.importClause && ts.isImportClause(statement.importClause)) { - // 标识符 - const clauseNode = statement.importClause; - if (!clauseNode.namedBindings && clauseNode.name && ts.isIdentifier(clauseNode.name)) { - // 没有大括号的标识符 - clauseSet.add(clauseNode.name.escapedText.toString()); - } else if ( - clauseNode.namedBindings && - clauseNode.namedBindings.name && - ts.isIdentifier(clauseNode.namedBindings.name) - ) { - // 没有标识符 *号 - clauseSet.add(clauseNode.namedBindings.name.escapedText.toString()); - } else if (clauseNode.namedBindings && clauseNode.namedBindings.elements) { - // 有花括号的标识符 - clauseNode.namedBindings.elements.forEach((ele) => { - if (ele.name && ts.isIdentifier(ele.name)) { - clauseSet.add(ele.name.escapedText.toString()); - } - }); - } - } + const clauseSet = collectClauseSet(statement); const importSpecifier = statement.moduleSpecifier.getText().replace(/[\'\"]/g, ''); const fileDir = path.dirname(url); let hasImportSpecifierFile = hasFileByImportPath(fileDir, importSpecifier); let hasImportSpecifierInModules = globalModules.has(importSpecifier); - if ((hasImportSpecifierFile || hasImportSpecifierInModules) && clauseSet.size > 0) { - let currModule = []; + if (!hasImportSpecifierFile && !hasImportSpecifierInModules) { + //路径不存在 或者 无reference使用 + return undefined; + } + let currModule = []; + if (hasImportSpecifierInModules) { + let index = globalModules.get(importSpecifier); + currModule = currReferencesModule[index].modules[importSpecifier]; + } + let { exsitClauseSet, hasExsitStatus, hasNonExsitStatus } = + collectNeedDeleteFlag(clauseSet, allIdentifierSet, hasImportSpecifierInModules, currModule); + if (!hasExsitStatus) { + // 不存在需要使用的标识符 + return undefined; + } + if (hasImportSpecifierInModules) { + let index = globalModules.get(importSpecifier); + currReferencesModule[index].isUsed = true; + } + if (!hasNonExsitStatus) { + // 不存在需要删除的标识符 + return statement; + } + // 有需要删除的标识符 + return updataImportNode(statement, exsitClauseSet); +} + +/** + * 保留import节点中exsitClauseSet使用到的模块 + * + * @param {ts.ImportDeclaration} statement + * @param {Set} exsitClauseSet + * @returns + */ +function updataImportNode(statement, exsitClauseSet) { + const newSpecifiers = []; + statement.importClause.namedBindings.elements.forEach((element) => { + if (exsitClauseSet.has(element.name.escapedText.toString())) { + newSpecifiers.push(element); + } + }); + statement.importClause.namedBindings = ts.factory.updateNamedImports( + statement.importClause.namedBindings, + newSpecifiers + ); + return statement; +} + +/** + * 判断当前import的模块是否需要删除 + * + * @param {Set} clauseSet 当前模块集合 + * @param {Set} allIdentifierSet 当前文件使用到的Identifer名称 + * @param {boolean} hasImportSpecifierInModules reference特殊路径是否存在 + * @param {Array} currModule reference模块信息 + * @returns + */ +function collectNeedDeleteFlag(clauseSet, allIdentifierSet, hasImportSpecifierInModules, currModule) { + let exsitClauseSet = new Set([]); // 当前import使用到的模块 + let hasExsitStatus = false; // 存在需要使用的模块 + let hasNonExsitStatus = false; //存在不需要使用的模块 + for (const clause of clauseSet) { + let flag = allIdentifierSet.has(clause); if (hasImportSpecifierInModules) { - let index = globalModules.get(importSpecifier); - currModule = currReferencesModule[index].modules[importSpecifier]; + flag = allIdentifierSet.has(clause) && currModule.includes(clause); } - const clasueCheckList = []; - let exsitClauseSet = new Set([]); - for (const clause of clauseSet) { - let flag = allIdentifierSet.has(clause); - if (hasImportSpecifierInModules) { - flag = allIdentifierSet.has(clause) && currModule.includes(clause); - } - if (flag) { - // 标识符使用到了当前import中的引用 - exsitClauseSet.add(clause); - clasueCheckList.push('exist'); - } else { - clasueCheckList.push('non-exist'); - } + if (flag) { + // 标识符使用到了当前import中的引用 + exsitClauseSet.add(clause); + hasExsitStatus = true; + } else { + hasNonExsitStatus = true; } - let hasExsitStatus = false; - let hasNonExsitStatus = false; - clasueCheckList.forEach((ele) => { - if (ele === 'exist') { - hasExsitStatus = true; - } else { - hasNonExsitStatus = true; + } + return { + exsitClauseSet, + hasExsitStatus, + hasNonExsitStatus + }; +} + +/** + * 收集import节点的导入模块 + * + * @param {ts.ImportDeclaration} statement 导入节点 + * @returns {Set} clauseSet + */ +function collectClauseSet(statement) { + // 是import节点 import {AsyncCallback} from './@ohos.base'; + const clauseSet = new Set([]); + if (!statement.importClause || !ts.isImportClause(statement.importClause)) { + return clauseSet; + } + // 标识符 + const clauseNode = statement.importClause; + if (!clauseNode.namedBindings && clauseNode.name && ts.isIdentifier(clauseNode.name)) { + // 没有大括号的标识符 + clauseSet.add(clauseNode.name.escapedText.toString()); + } else if ( + clauseNode.namedBindings && + clauseNode.namedBindings.name && + ts.isIdentifier(clauseNode.namedBindings.name) + ) { + // 没有标识符 *号 + clauseSet.add(clauseNode.namedBindings.name.escapedText.toString()); + } else if (clauseNode.namedBindings && clauseNode.namedBindings.elements) { + // 有花括号的标识符 + clauseNode.namedBindings.elements.forEach((ele) => { + if (ele.name && ts.isIdentifier(ele.name)) { + clauseSet.add(ele.name.escapedText.toString()); } }); - if (hasExsitStatus) { - // 有使用到的标识符 - if (hasNonExsitStatus) { - // 有没有使用到的标识符 - const newSpecifiers = []; - statement.importClause.namedBindings.elements.forEach((element) => { - if (exsitClauseSet.has(element.name.escapedText.toString())) { - newSpecifiers.push(element); - } - }); - statement.importClause.namedBindings = ts.factory.updateNamedImports( - statement.importClause.namedBindings, - newSpecifiers - ); - } - if (hasImportSpecifierInModules) { - let index = globalModules.get(importSpecifier); - currReferencesModule[index].isUsed = true; - } - return { statement }; - } else if (hasCopyright(statement)) { - return { copyrightMessage: node.getFullText().replace(node.getText(), ''), isCopyrightDeleted: true }; - } - } else if (hasCopyright(statement)) { - return { copyrightMessage: node.getFullText().replace(node.getText(), ''), isCopyrightDeleted: true }; } - return { statement: undefined, copyrightMessage: '', isCopyrightDeleted: false }; + return clauseSet; } /** @@ -842,6 +845,23 @@ function getFileAndKitComment(fileFullText) { return fileAndKitComment; } +/** + * + * 防止版权头段注释丢失 + * @param {string} fileFullText + * @returns {string} + * + */ +function getCopyrightComment(fileFullText) { + let copyrightComment = ''; + let pattern = /\/\*\s*\r?\n\s*\*\s*Copyright[\s\S]*?\*\//g; + let comment = fileFullText.match(pattern); + if (comment) { + copyrightComment = comment[0]; + } + return copyrightComment; +} + /** * 处理最终结果中的systemapi * @param {string} result @@ -864,8 +884,8 @@ function deleteSystemApi(url) { return (node) => { const fullText = String(node.getFullText()); //获取文件头部的注释信息--这里可能会涉及到@file和@kit段注释丢失 - let fileAndKitComment = getFileAndKitComment(fullText); - const copyrightMessage = fullText.replace(node.getText(), '').split(/\/\*\*/)[0] + fileAndKitComment + '\n'; + const fileAndKitComment = getFileAndKitComment(fullText); + const copyrightMessage = getCopyrightComment(fullText); let kitName = ''; if (fullText.match(/\@kit (.*)\r?\n/g)) { kitName = RegExp.$1.replace(/\s/g, ''); @@ -881,11 +901,9 @@ function deleteSystemApi(url) { } const fileName = processFileName(url); ts.transpileModule(result, { - compilerOptions: { - target: ts.ScriptTarget.ES2017, - }, + compilerOptions: COMPILER_OPTIONS, fileName: fileName, - transformers: { before: [formatImportDeclaration(url, copyrightMessage, deleteNode.isCopyrightDeleted)] }, + transformers: { before: [formatImportDeclaration(url, copyrightMessage, fileAndKitComment, deleteNode.firstNodeIsStatic)] }, }); } return ts.factory.createSourceFile([], ts.SyntaxKind.EndOfFileToken, ts.NodeFlags.None); @@ -903,12 +921,12 @@ exports.deleteSystemApi = deleteSystemApi; /** * 处理最外层的节点看是否删除 - * @param node 解析过后的节点 - * @param kitName 当前文件kitName + * @param {ts.Node} node 解析过后的节点 + * @param {string} url 当前文件kitName * @returns */ -function processSourceFile(node, kitName, url) { - let isCopyrightDeleted = false; +function processSourceFile(node, url) { + let firstNodeIsStatic = false; const newStatements = []; const newStatementsWithoutExport = []; const deleteSystemApiSet = new Set(); @@ -917,7 +935,7 @@ function processSourceFile(node, kitName, url) { default: '', exportName: new Set(), }; - isCopyrightDeleted = addNewStatements(node, newStatements, deleteSystemApiSet, needDeleteExport); + firstNodeIsStatic = addNewStatements(node, newStatements, deleteSystemApiSet, needDeleteExport); newStatements.forEach((statement) => { const names = getExportIdentifierName(statement); if (ts.isExportDeclaration(statement) && statement.moduleSpecifier && statement.moduleSpecifier.text.startsWith('./arkui/component/')) { @@ -947,7 +965,7 @@ function processSourceFile(node, kitName, url) { } return { node: ts.factory.updateSourceFile(node, newStatementsWithoutExport, node.isDeclarationFile, node.referencedFiles), - isCopyrightDeleted, + firstNodeIsStatic, }; } @@ -981,15 +999,15 @@ function processExportNode(statement, node, needDeleteExport, names, deleteSyste } function addNewStatements(node, newStatements, deleteSystemApiSet, needDeleteExport) { - let isCopyrightDeleted = false; + let firstNodeIsStatic = false; node.statements.forEach((statement, index) => { + if (index === 0 && isStaticFlag(statement)) { + firstNodeIsStatic = true; + } if (!isSystemapi(statement)) { newStatements.push(statement); return; } - if (index === 0) { - isCopyrightDeleted = true; - } if (ts.isVariableStatement(statement)) { deleteSystemApiSet.add(variableStatementGetEscapedText(statement)); } else if ( @@ -998,7 +1016,8 @@ function addNewStatements(node, newStatements, deleteSystemApiSet, needDeleteExp ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement) || ts.isStructDeclaration(statement) || - ts.isTypeAliasDeclaration(statement) + ts.isTypeAliasDeclaration(statement) || + ts.isAnnotationDeclaration(statement) ) { if (statement && statement.name && statement.name.escapedText) { deleteSystemApiSet.add(statement.name.escapedText.toString()); @@ -1009,7 +1028,7 @@ function addNewStatements(node, newStatements, deleteSystemApiSet, needDeleteExp } }); - return isCopyrightDeleted; + return firstNodeIsStatic; } function setDeleteExport(statement, node, needDeleteExport, deleteSystemApiSet) { @@ -1105,11 +1124,32 @@ function processVisitEachChild(context, node) { node = processEnumDeclaration(node); } else if (ts.isStructDeclaration(node)) { node = processStructDeclaration(node); + } else if (ts.isAnnotationDeclaration(node)) { + node = processAnnotationDeclaration(node); } return ts.visitEachChild(node, processAllNodes, context); } } +/** + * 处理@interface子节点 + */ +function processAnnotationDeclaration(node) { + const newMembers = []; + node.members.forEach((member) => { + if (!isSystemapi(member)) { + newMembers.push(member); + } + }); + node = ts.factory.updateAnnotationDeclaration( + node, + node.modifiers, + node.name, + newMembers + ); + return node; +} + /** * 处理interface子节点 */ @@ -1212,9 +1252,7 @@ function resolveReferences(url) { const content = fs.readFileSync(fullReferencePath, 'utf-8'); //文件内容 const fileName = processFileName(fullReferencePath); ts.transpileModule(content, { - compilerOptions: { - target: ts.ScriptTarget.ES2017, - }, + compilerOptions: COMPILER_OPTIONS, fileName: fileName, transformers: { before: [resolveCallback(fullReferencePath)] }, }); @@ -1236,7 +1274,7 @@ function resolveCallback(url) { ts.isModuleBlock(statement.body) && !isSystemapi(statement) ) { - ts.visitEachChild(statement, collectAllIdentifier, context); + ts.visitEachChild(statement, collectAllReferencesIdentifier, context); dealExternalStatements(referenceSourceFile); allModule[statement.name.text.toString()] = [...allReferencesIdentifierSet]; allReferencesIdentifierSet.clear(); @@ -1265,14 +1303,14 @@ function resolveCallback(url) { } }); } - function collectAllIdentifier(node) { + function collectAllReferencesIdentifier(node) { if (isSystemapi(node)) { return node; } if (ts.isIdentifier(node)) { allReferencesIdentifierSet.add(node.escapedText.toString()); } - return ts.visitEachChild(node, collectAllIdentifier, context); + return ts.visitEachChild(node, collectAllReferencesIdentifier, context); } }; } @@ -1302,12 +1340,25 @@ function isSystemapi(node) { return false; } +/** + * 判断是否为use static标记 + * @param { ts.Node } node + * @returns { boolean } + */ +function isStaticFlag(node) { + return ts.isExpressionStatement(node) && + node.expression && + ts.isStringLiteral(node.expression) && + node.expression.text && + node.expression.text === ARKTS_FLAG; +} + function isEmptyFile(node) { let isEmpty = true; if (ts.isSourceFile(node) && node.statements) { for (let i = 0; i < node.statements.length; i++) { const statement = node.statements[i]; - if (ts.isImportDeclaration(statement)) { + if (ts.isImportDeclaration(statement) || isStaticFlag(statement)) { continue; } isEmpty = false; diff --git a/build-tools/handleApiFiles.js b/build-tools/handleApiFiles.js index c5b47681cd99d0f19d541e231b8e7ba1ad7732ee..33225dc30b07f88c1cb61b31ad511176597d2f70 100755 --- a/build-tools/handleApiFiles.js +++ b/build-tools/handleApiFiles.js @@ -166,10 +166,10 @@ function handleApiFileByType(apiRelativePath, rootPath, type, output, isPublic) if (isEndWithStatic) { if (type === 'ets2') { if (isPublic === 'true') { - writeFile(outputPath, fileContent); + writeFile(outputPath, deleteArktsTag(fileContent)); return; } else { - writeFile(outputPath.replace(/\.static\.d\.ets$/, '.d.ets'), fileContent); + writeFile(outputPath.replace(/\.static\.d\.ets$/, '.d.ets'), deleteArktsTag(fileContent)); return; } } else { @@ -538,25 +538,22 @@ function handleNoTagFileInSecondType(sourceFile, outputPath, fullPath) { /** * 获取删除overload节点后的文件内容 - * @param {*} sourceFile + * @param {*} newContent 文件内容 + * @param {*} filePath 文件路径 * @returns */ function getFileContent(newContent, filePath) { const regex = /^overload\s+.+$/; - if (isArkTsSpecialSyntax(newContent) || !regex.test(newContent)) { + if (!regex.test(newContent)) { return newContent; } const sourceFile = ts.createSourceFile(path.basename(filePath), newContent, ts.ScriptTarget.ES2017, true); const printer = ts.createPrinter(); - const result = ts.transform(sourceFile, [deleteOverLoadJsDoc]); + const result = ts.transform(sourceFile, [deleteOverLoadJsDoc], { etsAnnotationsEnable: true }); const output = printer.printFile(result.transformed[0]); return output; } -function isArkTsSpecialSyntax(content) { - return /\@memo|(?