1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { 17 factory, 18 isBlock, 19 isCallExpression, 20 isElementAccessExpression, 21 isExpressionStatement, 22 isIdentifier, 23 isPropertyAccessExpression, 24 isSourceFile, 25 setParentRecursive, 26 visitEachChild 27} from 'typescript'; 28 29import type { 30 Block, 31 LeftHandSideExpression, 32 Node, 33 NodeArray, 34 SourceFile, 35 Statement, 36 TransformationContext, 37 Transformer, 38 TransformerFactory 39} from 'typescript'; 40 41import type {IOptions} from '../../configs/IOptions'; 42import type {TransformPlugin} from '../TransformPlugin'; 43import {OhPackType, isCommentedNode} from '../../utils/TransformUtil'; 44import {findOhImportStatement} from '../../utils/OhsUtil'; 45 46namespace secharmony { 47 const TRANSFORMER_ORDER: number = 2; 48 export let transformerPlugin: TransformPlugin = { 49 'name': 'disableHilogPlugin', 50 'order': (1 << TRANSFORMER_ORDER), 51 'createTransformerFactory': createDisableHilogFactory 52 }; 53 54 export function createDisableHilogFactory(option: IOptions): TransformerFactory<Node> { 55 if (!option.mDisableHilog) { 56 return null; 57 } 58 59 return disableHilogFactory; 60 61 function disableHilogFactory(context: TransformationContext): Transformer<Node> { 62 let sourceFile: SourceFile; 63 return transformer; 64 65 function transformer(node: Node): Node { 66 if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) { 67 return node; 68 } 69 70 sourceFile = node; 71 let resultAst: Node = visitAst(node); 72 return setParentRecursive(resultAst, true); 73 } 74 75 function visitAst(node: Node): Node { 76 if (isSourceFile(node)) { 77 const visitedAst: SourceFile = visitEachChild(node, visitAst, context); 78 const deletedStatements: Statement[] = deleteHilogStatement(visitedAst.statements); 79 80 return factory.updateSourceFile(node, deletedStatements); 81 } 82 83 if (!isBlock(node)) { 84 return visitEachChild(node, visitAst, context); 85 } 86 87 const visitedBlock: Block = visitEachChild(node, visitAst, context); 88 const newStatements: Statement[] = deleteHilogStatement(visitedBlock.statements); 89 90 return factory.createBlock(newStatements, true); 91 } 92 93 function deleteHilogStatement(statements: NodeArray<Statement>): Statement[] { 94 const reservedStatements: Statement[] = []; 95 statements.forEach((child) => { 96 if (isSimpleHilogStatement(child)) { 97 return; 98 } 99 100 if (isHilogImportStatement(child)) { 101 if (isCommentedNode(child, sourceFile)) { 102 reservedStatements.push(child); 103 } 104 105 return; 106 } 107 108 reservedStatements.push(child); 109 }); 110 111 return reservedStatements; 112 } 113 114 function isHilogImportStatement(node: Statement): boolean { 115 const ohPackType: OhPackType = findOhImportStatement(node, '@ohos.hilog'); 116 return ohPackType !== OhPackType.NONE; 117 } 118 119 function isSimpleHilogStatement(node: Statement): boolean { 120 if (!isExpressionStatement(node)) { 121 return false; 122 } 123 124 if (!node.expression || !isCallExpression(node.expression)) { 125 return false; 126 } 127 128 const expressionCalled: LeftHandSideExpression = node.expression.expression; 129 if (!expressionCalled) { 130 return false; 131 } 132 133 if (isPropertyAccessExpression(expressionCalled) && expressionCalled.expression) { 134 if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'hilog') { 135 return true; 136 } 137 } 138 139 if (isElementAccessExpression(expressionCalled) && expressionCalled.expression) { 140 if (isIdentifier(expressionCalled.expression) && expressionCalled.expression.text === 'hilog') { 141 return true; 142 } 143 } 144 145 return false; 146 } 147 } 148 } 149} 150 151export = secharmony; 152