diff --git a/compiler/src/fast_build/system_api/api_check_define.ts b/compiler/src/fast_build/system_api/api_check_define.ts deleted file mode 100644 index d4a8a9794246f264812b6f997bc0ddcbb4e709dc..0000000000000000000000000000000000000000 --- a/compiler/src/fast_build/system_api/api_check_define.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const PERMISSION_TAG_CHECK_NAME: string = 'permission'; -export const PERMISSION_TAG_CHECK_ERROR: string = "To use this API, you need to apply for the permissions: $DT"; -export const SYSTEM_API_TAG_CHECK_NAME: string = 'systemapi'; -export const SYSTEM_API_TAG_CHECK_WARNING: string = "'{0}' is system api"; -export const TEST_TAG_CHECK_NAME: string = 'test'; -export const TEST_TAG_CHECK_ERROR: string = "'{0}' can only be used for testing directories "; -export const SYSCAP_TAG_CHECK_NAME: string = 'syscap'; -export const SYSCAP_TAG_CHECK_WARNING: string = "The system capacity of this api '{0}' is not supported on all devices"; -export const SYSCAP_TAG_CONDITION_CHECK_WARNING: string = 'The API is not supported on all devices. Use the canIUse condition to determine whether the API is supported.'; -export const CANIUSE_FUNCTION_NAME: string = 'canIUse'; -export const VERSION_CHECK_FUNCTION_NAME: string = 'isApiVersionGreaterOrEqual'; -export const RUNTIME_OS_OH: string = 'OpenHarmony'; -export const FORM_TAG_CHECK_NAME: string = 'form'; -export const FORM_TAG_CHECK_ERROR: string = "'{0}' can't support form application."; -export const CROSSPLATFORM_TAG_CHECK_NAME: string = 'crossplatform'; -export const CROSSPLATFORM_TAG_CHECK_ERROER: string = "'{0}' can't support crossplatform application."; -export const DEPRECATED_TAG_CHECK_NAME: string = 'deprecated'; -export const DEPRECATED_TAG_CHECK_WARNING: string = "'{0}' has been deprecated."; -export const FA_TAG_CHECK_NAME: string = 'famodelonly'; -export const FA_TAG_HUMP_CHECK_NAME: string = 'FAModelOnly'; -export const FA_TAG_CHECK_ERROR: string = 'This API is used only in FA Mode, but the current Mode is Stage.'; -export const STAGE_TAG_CHECK_NAME: string = 'stagemodelonly'; -export const STAGE_TAG_HUMP_CHECK_NAME: string = 'StageModelOnly'; -export const STAGE_TAG_CHECK_ERROR: string = 'This API is used only in Stage Mode, but the current Mode is FA.'; -export const STAGE_COMPILE_MODE: string = 'moduleJson'; -export const ATOMICSERVICE_BUNDLE_TYPE: string = 'atomicService'; -export const ATOMICSERVICE_TAG_CHECK_NAME: string = 'atomicservice'; -export const ATOMICSERVICE_TAG_CHECK_ERROER: string = "'{0}' can't support atomicservice application."; -export const SINCE_TAG_NAME: string = 'since'; -export const SINCE_TAG_CHECK_ERROER: string = "The '{0}' API is supported since SDK version $SINCE1. However, the current compatible SDK version is $SINCE2."; -export const ATOMICSERVICE_TAG_CHECK_VERSION: number = 11; -export const FIND_MODULE_WARNING: string = "Cannot find name '{0}'."; - -export const CONSTANT_STEP_0: number = 0; -export const CONSTANT_STEP_1: number = 1; -export const CONSTANT_STEP_2: number = 2; -export const CONSTANT_STEP_3: number = 3; - -export const GLOBAL_DECLARE_WHITE_LIST: Set = new Set(['Context', 'PointerStyle', 'PixelMap', 'UnifiedData', - 'Summary', 'UniformDataType', 'IntentionCode', 'NavDestinationInfo', 'UIContext', 'Resource', 'WebviewController']); diff --git a/compiler/src/fast_build/system_api/api_check_permission.ts b/compiler/src/fast_build/system_api/api_check_permission.ts deleted file mode 100644 index ec5344fa00a5afcfa79c000bd704e922d36beadf..0000000000000000000000000000000000000000 --- a/compiler/src/fast_build/system_api/api_check_permission.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import ts from 'typescript'; - -enum PermissionVaildTokenState { - Init, - LeftParenthesis, - RightParenthesis, - PermissionChar, - And, - Or, -} - -interface PermissionVaildCalcInfo { - valid: boolean; - currentToken: PermissionVaildTokenState; - finish: boolean; - currentPermissionMatch: boolean; -} - -interface PermissionVaildCalcGroup { - subQueue: string[]; - includeParenthesis: boolean; -} - -export interface PermissionModule { - modulePath: string; - testPermissions: string[]; - permissions: string[]; -} - -export class JsDocCheckService { - /** - * STER1. Parse the permission information configured on the API - * STEP2. Recursive queue to obtain whether the current permission configuration supports it - */ - static validPermission(comment: string, permissionsArray: string[]): boolean { - const permissionsItem: string[] = JsDocCheckService.getSplitsArrayWithDesignatedCharAndStr(comment ?? '', ' ') - .filter((item) => { - return item !== ''; - }); - const permissionsQueue: string[] = []; - permissionsItem.forEach((item: string) => { - //STEP1.1 Parse'(' - const leftParenthesisItem: string[] = JsDocCheckService.getSplitsArrayWithDesignatedCharAndArrayStr([item], '('); - //STEP1.2 Parse')' - const rightParenthesisItem: string[] = JsDocCheckService.getSplitsArrayWithDesignatedCharAndArrayStr(leftParenthesisItem, ')'); - permissionsQueue.push(...rightParenthesisItem); - }); - //STEP2 - const calcValidResult: PermissionVaildCalcInfo = { - valid: false, - currentToken: PermissionVaildTokenState.Init, - finish: false, - currentPermissionMatch: true, - }; - JsDocCheckService.validPermissionRecursion(permissionsQueue, permissionsArray, calcValidResult); - return calcValidResult.valid; - } - - private static validPermissionRecursion(permissionsQueue: string[], permissions: string[], calcValidResult: PermissionVaildCalcInfo): void { - if (permissionsQueue.some(item => ['(', ')'].includes(item))) { - const groups: PermissionVaildCalcGroup[] = JsDocCheckService.groupWithParenthesis(permissionsQueue); - const groupJoin: string[] = JsDocCheckService.getGroupItemPermission(groups, calcValidResult, permissions); - JsDocCheckService.getPermissionVaildAtoms(groupJoin, calcValidResult, permissions ?? []); - } else { - JsDocCheckService.getPermissionVaildAtoms(permissionsQueue, calcValidResult, permissions ?? []); - } - } - - private static getSplitsArrayWithDesignatedCharAndStr(permission: string, designatedChar: string): string[] { - return permission.split(designatedChar).map(item => item.trim()); - } - - private static getGroupItemPermission( - groups: PermissionVaildCalcGroup[], - calcValidResult: PermissionVaildCalcInfo, - permissions: string[]): string[] { - const groupJoin: string[] = []; - groups.forEach((groupItem: PermissionVaildCalcGroup) => { - if (groupItem.includeParenthesis) { - const calcValidResultItem: PermissionVaildCalcInfo = { - ...calcValidResult, - }; - const subStack: string[] = groupItem.subQueue.slice(1, groupItem.subQueue.length - 1); - JsDocCheckService.validPermissionRecursion(subStack, permissions, calcValidResultItem); - if (calcValidResultItem.valid) { - groupJoin.push(''); - } else { - groupJoin.push('NA'); - } - } else { - groupJoin.push(...groupItem.subQueue); - } - }); - return groupJoin; - } - - private static groupWithParenthesis(stack: string[]): PermissionVaildCalcGroup[] { - let currentLeftParenthesisCount: number = 0; - const groups: PermissionVaildCalcGroup[] = []; - let currentGroupItem: PermissionVaildCalcGroup = { - subQueue: [], - includeParenthesis: false, - }; - stack.forEach((item: string, index: number) => { - if (item === '(') { - if (currentLeftParenthesisCount === 0) { - groups.push(currentGroupItem); - currentGroupItem = { - subQueue: [item], - includeParenthesis: true - }; - } else { - currentGroupItem.subQueue.push(item); - } - currentLeftParenthesisCount++; - } else if (item === ')') { - currentLeftParenthesisCount--; - currentGroupItem.subQueue.push(item); - if (currentLeftParenthesisCount === 0) { - groups.push(currentGroupItem); - currentGroupItem = { - subQueue: [], - includeParenthesis: false, - }; - } - } else { - currentGroupItem.subQueue.push(item); - if (index === stack.length - 1) { - groups.push(currentGroupItem); - } - } - }); - return groups; - } - - private static getPermissionVaildAtoms(atomStacks: string[], calcValidResult: PermissionVaildCalcInfo, configPermissions: string[]): void { - if (calcValidResult.finish) { - return; - } - if (atomStacks[0] === 'and') { - calcValidResult.currentToken = PermissionVaildTokenState.And; - } else if (atomStacks[0] === 'or') { - calcValidResult.currentToken = PermissionVaildTokenState.Or; - } else { - if (calcValidResult.currentToken === PermissionVaildTokenState.Or) { - if (JsDocCheckService.inValidOrExpression( - atomStacks, - calcValidResult, - configPermissions - )) { - calcValidResult.currentPermissionMatch = false; - } - } else if (calcValidResult.currentToken === PermissionVaildTokenState.And) { - if (JsDocCheckService.inValidAndExpression( - atomStacks, - calcValidResult, - configPermissions - )) { - calcValidResult.currentPermissionMatch = false; - } - } else { - calcValidResult.currentPermissionMatch = - JsDocCheckService.validPermissionItem(atomStacks[0], configPermissions); - } - } - if (atomStacks.length > 1) { - JsDocCheckService.getPermissionVaildAtoms( - atomStacks.slice(1), - calcValidResult, - configPermissions - ); - } else { - calcValidResult.valid = calcValidResult.currentPermissionMatch; - calcValidResult.finish = true; - } - } - - private static inValidOrExpression( - atomStacks: string[], - calcValidResult: PermissionVaildCalcInfo, - configPermissions: string[]): boolean { - if ( - !calcValidResult.currentPermissionMatch && - !JsDocCheckService.validPermissionItem(atomStacks[0], configPermissions) - ) { - calcValidResult.valid = false; - return true; - } - calcValidResult.currentPermissionMatch = true; - return false; - } - private static inValidAndExpression( - atomStacks: string[], - calcValidResult: PermissionVaildCalcInfo, - configPermissions: string[]): boolean { - if ( - !calcValidResult.currentPermissionMatch || - !JsDocCheckService.validPermissionItem(atomStacks[0], configPermissions) - ) { - calcValidResult.valid = false; - return true; - } - calcValidResult.currentPermissionMatch = - JsDocCheckService.validPermissionItem(atomStacks[0], configPermissions); - return false; - } - private static validPermissionItem(atomStackItem: string, configPermissions: string[]): boolean { - return atomStackItem === '' || configPermissions.includes(atomStackItem); - } - - private static getSplitsArrayWithDesignatedCharAndArrayStr( - leftParenthesisItems: string[], - designatedChar: string - ): string[] { - const rightParenthesisItems: string[] = []; - leftParenthesisItems.forEach((leftParenthesisItem: string) => { - if (leftParenthesisItem.includes(designatedChar)) { - const rightParenthesis: string[] = - JsDocCheckService.getSplitsArrayWithDesignatedCharAndStr( - leftParenthesisItem, - designatedChar - ); - rightParenthesis.forEach((item: string) => { - if (item === '') { - rightParenthesisItems.push(designatedChar); - } else { - rightParenthesisItems.push(item); - } - }); - } else { - rightParenthesisItems.push(leftParenthesisItem); - } - }); - return rightParenthesisItems; - } -} diff --git a/compiler/src/fast_build/system_api/api_check_utils.ts b/compiler/src/fast_build/system_api/api_check_utils.ts deleted file mode 100644 index 71be695cd3d84c08684a8ec0b880aead0e20a94a..0000000000000000000000000000000000000000 --- a/compiler/src/fast_build/system_api/api_check_utils.ts +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import ts from 'typescript'; -import path from 'path'; -import fs from 'fs'; - -import { - projectConfig, - extendSdkConfigs, - globalProgram, - ohosSystemModulePaths, - systemModules, - allModulesPaths, - ohosSystemModuleSubDirPaths -} from '../../../main'; -import { - LogType, - LogInfo, - IFileLog, - CurrentProcessFile -} from '../../utils'; -import { type ResolveModuleInfo } from '../../ets_checker'; -import { - PERMISSION_TAG_CHECK_NAME, - PERMISSION_TAG_CHECK_ERROR, - SYSTEM_API_TAG_CHECK_NAME, - SYSTEM_API_TAG_CHECK_WARNING, - TEST_TAG_CHECK_NAME, - TEST_TAG_CHECK_ERROR, - SYSCAP_TAG_CHECK_NAME, - SYSCAP_TAG_CONDITION_CHECK_WARNING, - SYSCAP_TAG_CHECK_WARNING, - CANIUSE_FUNCTION_NAME, - FORM_TAG_CHECK_NAME, - FORM_TAG_CHECK_ERROR, - FIND_MODULE_WARNING, - CROSSPLATFORM_TAG_CHECK_NAME, - CROSSPLATFORM_TAG_CHECK_ERROER, - DEPRECATED_TAG_CHECK_NAME, - DEPRECATED_TAG_CHECK_WARNING, - FA_TAG_CHECK_NAME, - FA_TAG_HUMP_CHECK_NAME, - FA_TAG_CHECK_ERROR, - STAGE_TAG_CHECK_NAME, - STAGE_TAG_HUMP_CHECK_NAME, - STAGE_TAG_CHECK_ERROR, - STAGE_COMPILE_MODE, - ATOMICSERVICE_BUNDLE_TYPE, - ATOMICSERVICE_TAG_CHECK_NAME, - ATOMICSERVICE_TAG_CHECK_ERROER, - ATOMICSERVICE_TAG_CHECK_VERSION, - RUNTIME_OS_OH, - CONSTANT_STEP_0, - CONSTANT_STEP_1, - CONSTANT_STEP_2, - CONSTANT_STEP_3, - GLOBAL_DECLARE_WHITE_LIST, - SINCE_TAG_NAME, - SINCE_TAG_CHECK_ERROER, - VERSION_CHECK_FUNCTION_NAME -} from './api_check_define'; -import { JsDocCheckService } from './api_check_permission'; - -/** - * bundle info - * - * @interface BundleInfo - */ -interface BundleInfo { - bundlePath: string; - bundleVersion: string; -} - -export interface CheckValidCallbackInterface { - (jsDocTag: ts.JSDocTag, config: ts.JsDocNodeCheckConfigItem): boolean; -} - -export interface CheckJsDocSpecialValidCallbackInterface { - (jsDocTags: readonly ts.JSDocTag[], config: ts.JsDocNodeCheckConfigItem): boolean; -} - -export interface checkConditionValidCallbackInterface { - (node: ts.CallExpression, specifyFuncName: string, importSymbol: string, jsDocs?: ts.JSDoc[]): boolean; -} - -interface HasJSDocNode extends ts.Node { - jsDoc?: ts.JSDoc[]; -} - -/** - * get the bundleInfo of ohm - * - * @param {string} modulePath - * @return {BundleInfo} - */ -function parseOhmBundle(modulePath: string): BundleInfo { - const apiCode: string = fs.readFileSync(modulePath, { encoding: 'utf-8' }); - const bundleTags: string[] = apiCode.match(/@bundle.+/g); - const bundleInfo: BundleInfo = { - bundlePath: '', - bundleVersion: '' - }; - if (bundleTags && bundleTags.length > CONSTANT_STEP_0) { - const bundleTag: string = bundleTags[CONSTANT_STEP_0]; - const bundleInfos: string[] = bundleTag.split(' '); - if (bundleInfos.length === CONSTANT_STEP_3) { - bundleInfo.bundlePath = bundleInfos[CONSTANT_STEP_1]; - bundleInfo.bundleVersion = bundleInfos[CONSTANT_STEP_2]; - } - } - return bundleInfo; -} - -/** - * jude a version string , string has two format - * xx:is a number and need greater than 10 - * x.x.x: a string join '.', the first part and second part is number and need greater than 4.1 - * - * @param {string} bundleVersion - version string - * @returns {boolean} - */ -function checkBundleVersion(bundleVersion: string): boolean { - if (!projectConfig.compatibleSdkVersion) { - return true; - } - const compatibleSdkVersion: string = projectConfig.compatibleSdkVersion; - let bundleVersionNumber: number = 0; - const bundleVersionArr = bundleVersion.match(/(?<=\().*(?=\))/g); - if (bundleVersionArr && bundleVersionArr.length === 1) { - bundleVersionNumber = Number(bundleVersionArr[CONSTANT_STEP_0]); - } else { - bundleVersionNumber = Number(bundleVersion); - } - if (bundleVersion && bundleVersion !== '' && !isNaN(bundleVersionNumber) && - !isNaN(Number(compatibleSdkVersion)) && Number(compatibleSdkVersion) >= bundleVersionNumber) { - return true; - } - return false; -} - -/** - * get the real path about a list in module path - * - * @param {string[]} apiDirs - file list - * @param {string} moduleName - module dir - * @param {string[]} exts - ext - * @returns {ResolveModuleInfo} - */ -export function getRealModulePath(apiDirs: string[], moduleName: string, exts: string[]): ResolveModuleInfo { - const resolveResult: ResolveModuleInfo = { - modulePath: '', - isEts: true - }; - for (let i = 0; i < apiDirs.length; i++) { - const dir = apiDirs[i]; - for (let i = 0; i < exts.length; i++) { - const ext = exts[i]; - const moduleDir = path.resolve(dir, moduleName + ext); - if (!fs.existsSync(moduleDir)) { - continue; - } - resolveResult.modulePath = moduleDir; - if (ext === '.d.ts') { - resolveResult.isEts = false; - } - break; - } - } - return resolveResult; -} - -/** - * get a request path about ohos - * - * @param {string} moduleRequest - import request path - * @param {string} _ - import request path - * @param {number} moduleType - * @param {string} systemKey - * @returns {string} - */ -export function moduleRequestCallback(moduleRequest: string, _: string, - moduleType: string, systemKey: string): string { - for (const config of extendSdkConfigs.values()) { - if (config.prefix === '@arkui-x') { - continue; - } - if (moduleRequest.startsWith(config.prefix + '.')) { - let compileRequest: string = `${config.prefix}:${systemKey}`; - const resolveModuleInfo: ResolveModuleInfo = getRealModulePath(config.apiPath, moduleRequest, - ['.d.ts', '.d.ets']); - const modulePath: string = resolveModuleInfo.modulePath; - if (!fs.existsSync(modulePath)) { - return compileRequest; - } - const bundleInfo: BundleInfo = parseOhmBundle(modulePath); - if (checkBundleVersion(bundleInfo.bundleVersion)) { - compileRequest = `@bundle:${bundleInfo.bundlePath}`; - } - return compileRequest; - } - } - return ''; -} - -/** - * check arkui dependences in ts files - * api check from sdk - * - * @param {ts.TypeReferenceNode} node - typeReferenceNode - * @param {IFileLog} transformLog - log info - */ -export function checkTypeReference(node: ts.TypeReferenceNode, transformLog: IFileLog): void { - const fileName: string = transformLog.sourceFile.fileName; - const currentTypeName: string = node.getText(); - if (/(? 0) { - sourceFile = ts.getSourceFileOfNode(type.aliasSymbol.declarations[0]); - } else if (type && type.symbol && type.symbol.declarations && type.symbol.declarations.length > 0) { - sourceFile = ts.getSourceFileOfNode(type.symbol.declarations[0]); - } - if (!sourceFile) { - return; - } - const sourceBaseName: string = path.basename(sourceFile.fileName); - if (isArkuiDependence(sourceFile.fileName) && - sourceBaseName !== 'common_ts_ets_api.d.ts' && - sourceBaseName !== 'global.d.ts' - ) { - // TODO: change to error - transformLog.errors.push({ - type: LogType.WARN, - message: `Cannot find name '${currentTypeName}'.`, - pos: node.getStart() - }); - } else if (GLOBAL_DECLARE_WHITE_LIST.has(currentTypeName) && - ohosSystemModulePaths.includes(sourceFile.fileName.replace(/\//g, '\\'))) { - transformLog.errors.push({ - type: LogType.WARN, - message: `Cannot find name '${currentTypeName}'.`, - pos: node.getStart() - }); - } - } -} - -/** - * get jsDocNodeCheckConfigItem object - * - * @param {string[]} tagName - tag name - * @param {string} message - error message - * @param {ts.DiagnosticCategory} type - error type - * @param {boolean} tagNameShouldExisted - tag is required - * @param {CheckValidCallbackInterface} checkValidCallback - * @param {CheckJsDocSpecialValidCallbackInterface} checkJsDocSpecialValidCallback - * @param {checkConditionValidCallbackInterface} checkConditionValidCallback - * @returns {ts.JsDocNodeCheckConfigItem} - */ -function getJsDocNodeCheckConfigItem(tagName: string[], message: string, needConditionCheck: boolean, - type: ts.DiagnosticCategory, specifyCheckConditionFuncName: string, - tagNameShouldExisted: boolean, checkValidCallback?: CheckValidCallbackInterface, - checkJsDocSpecialValidCallback?: CheckJsDocSpecialValidCallbackInterface, - checkConditionValidCallback?: checkConditionValidCallbackInterface): ts.JsDocNodeCheckConfigItem { - return { - tagName: tagName, - message: message, - needConditionCheck: needConditionCheck, - type: type, - specifyCheckConditionFuncName: specifyCheckConditionFuncName, - tagNameShouldExisted: tagNameShouldExisted, - checkValidCallback: checkValidCallback, - checkJsDocSpecialValidCallback: checkJsDocSpecialValidCallback, - checkConditionValidCallback: checkConditionValidCallback - }; -} - -/** - * judge a file is card file - * - * @param {string} file - file path - * @returns {boolean} - */ -export function isCardFile(file: string): boolean { - for (const key in projectConfig.cardEntryObj) { - if (path.normalize(projectConfig.cardEntryObj[key]) === path.normalize(file)) { - return true; - } - } - return false; -} - -const jsDocNodeCheckConfigCache: Map> = new Map>(); -let permissionsArray: string[] = []; -/** - * get tagName where need to be determined based on the file path - * - * @param {string} fileName - file name - * @param {string} sourceFileName - resource reference path - * @returns {ts.JsDocNodeCheckConfig} - */ -export function getJsDocNodeCheckConfig(fileName: string, sourceFileName: string): ts.JsDocNodeCheckConfig { - let byFileName: Map | undefined = jsDocNodeCheckConfigCache.get(fileName); - if (byFileName === undefined) { - byFileName = new Map(); - jsDocNodeCheckConfigCache.set(fileName, byFileName); - } - let result: ts.JsDocNodeCheckConfig | undefined = byFileName.get(sourceFileName); - if (result !== undefined) { - return result; - } - let needCheckResult: boolean = false; - const checkConfigArray: ts.JsDocNodeCheckConfigItem[] = []; - const apiName: string = path.basename(fileName); - const sourceBaseName: string = path.basename(sourceFileName); - if (/(? 0) { - const fileContent: string = fs.readFileSync(fileName, { encoding: 'utf-8' }); - const needCanIUseCheck: boolean = /canIUse\(.*\)/.test(fileContent); - checkConfigArray.push(getJsDocNodeCheckConfigItem([SYSCAP_TAG_CHECK_NAME], - SYSCAP_TAG_CHECK_WARNING, needCanIUseCheck, ts.DiagnosticCategory.Warning, CANIUSE_FUNCTION_NAME, false, undefined, - checkSyscapAbility, checkSyscapConditionValidCallback)); - } - if (projectConfig.projectRootPath) { - const ohosTestDir = ts.sys.resolvePath(path.join(projectConfig.projectRootPath, 'entry', 'src', 'ohosTest')); - // TODO:fix error type in the feature - if (!ts.sys.resolvePath(fileName).startsWith(ohosTestDir)) { - permissionsArray = projectConfig.requestPermissions; - checkConfigArray.push(getJsDocNodeCheckConfigItem([TEST_TAG_CHECK_NAME], TEST_TAG_CHECK_ERROR, false, - ts.DiagnosticCategory.Warning, '', false)); - } - } - checkConfigArray.push(getJsDocNodeCheckConfigItem([PERMISSION_TAG_CHECK_NAME], PERMISSION_TAG_CHECK_ERROR, false, - ts.DiagnosticCategory.Warning, '', false, undefined, checkPermissionValue)); - if (isCardFile(fileName)) { - needCheckResult = true; - checkConfigArray.push(getJsDocNodeCheckConfigItem([FORM_TAG_CHECK_NAME], FORM_TAG_CHECK_ERROR, false, - ts.DiagnosticCategory.Error, '', true)); - } - if (projectConfig.isCrossplatform) { - needCheckResult = true; - const logType: ts.DiagnosticCategory = projectConfig.ignoreCrossplatformCheck !== true ? ts.DiagnosticCategory.Error : - ts.DiagnosticCategory.Warning; - checkConfigArray.push(getJsDocNodeCheckConfigItem([CROSSPLATFORM_TAG_CHECK_NAME], CROSSPLATFORM_TAG_CHECK_ERROER, - false, logType, '', true)); - } - if (process.env.compileMode === STAGE_COMPILE_MODE) { - needCheckResult = true; - checkConfigArray.push(getJsDocNodeCheckConfigItem([FA_TAG_CHECK_NAME, FA_TAG_HUMP_CHECK_NAME], - FA_TAG_CHECK_ERROR, false, ts.DiagnosticCategory.Error, '', false)); - } else if (process.env.compileMode !== '') { - needCheckResult = true; - checkConfigArray.push(getJsDocNodeCheckConfigItem([STAGE_TAG_CHECK_NAME, STAGE_TAG_HUMP_CHECK_NAME], - STAGE_TAG_CHECK_ERROR, false, - ts.DiagnosticCategory.Error, '', false)); - } - if (projectConfig.bundleType === ATOMICSERVICE_BUNDLE_TYPE && - projectConfig.compileSdkVersion >= ATOMICSERVICE_TAG_CHECK_VERSION) { - needCheckResult = true; - checkConfigArray.push(getJsDocNodeCheckConfigItem([ATOMICSERVICE_TAG_CHECK_NAME], ATOMICSERVICE_TAG_CHECK_ERROER, - false, ts.DiagnosticCategory.Error, '', true)); - } - } - result = { - nodeNeedCheck: needCheckResult, - checkConfig: checkConfigArray - }; - byFileName.set(sourceFileName, result); - return result; -} - -const arkuiDependenceMap: Map = new Map(); -/** - * return a file path is Arkui path - * - * @param {string} file - file path - * @returns {boolean} - */ -function isArkuiDependence(file: string): boolean { - let exists: boolean | undefined = arkuiDependenceMap.get(file); - if (exists !== undefined) { - return exists; - } - const fileDir: string = path.dirname(file); - const declarationsPath: string = path.resolve(__dirname, '../../../declarations').replace(/\\/g, '/'); - const componentPath: string = path.resolve(__dirname, '../../../../../component').replace(/\\/g, '/'); - exists = fileDir === declarationsPath || fileDir === componentPath; - arkuiDependenceMap.set(file, exists); - return exists; -} - -/** - * check a secondary directory of Arkui is used in the moduleSpecifier of import - * - * @param {ts.Expression} moduleSpecifier - the moduleSpecifier of import - * @param {LogInfo[]} log - log list - */ -export function validateModuleSpecifier(moduleSpecifier: ts.Expression, log: LogInfo[]): void { - const moduleSpecifierStr: string = moduleSpecifier.getText().replace(/'|"/g, ''); - const hasSubDirPath: boolean = ohosSystemModuleSubDirPaths.some((filePath: string) => { - return filePath === moduleSpecifierStr; - }); - if (hasSubDirPath) { - // TODO: change to error - const error: LogInfo = { - type: LogType.WARN, - message: `Cannot find module '${moduleSpecifierStr}' or its corresponding type declarations.`, - pos: moduleSpecifier.getStart() - }; - log.push(error); - } -} - -interface SystemConfig { - deviceTypesMessage: string, - deviceTypes: string[], - runtimeOS: string, - externalApiPaths: string[], - syscapIntersectionSet: Set, - syscapUnionSet: Set -} - -interface SyscapConfig { - SysCaps: string[] -} - -/** - * configure syscapInfo to this.share.projectConfig - * - * @param config this.share.projectConfig - */ -export function configureSyscapInfo(config: SystemConfig): void { - config.deviceTypesMessage = config.deviceTypes.join(','); - const deviceDir: string = path.resolve(__dirname, '../../../../../api/device-define/'); - const deviceInfoMap: Map = new Map(); - const syscaps: Array = []; - let allSyscaps: string[] = []; - config.deviceTypes.forEach((deviceType: string) => { - collectOhSyscapInfos(deviceType, deviceDir, deviceInfoMap); - }); - if (config.runtimeOS !== RUNTIME_OS_OH) { - collectExternalSyscapInfos(config.externalApiPaths, config.deviceTypes, deviceInfoMap); - } - deviceInfoMap.forEach((value: string[]) => { - syscaps.push(value); - allSyscaps = allSyscaps.concat(value); - }); - const intersectNoRepeatTwice = (arrs: Array) => { - return arrs.reduce(function (prev: string[], cur: string[]) { - return Array.from(new Set(cur.filter((item: string) => { - return prev.includes(item); - }))); - }); - }; - let syscapIntersection: string[] = []; - if (config.deviceTypes.length === 1 || syscaps.length === 1) { - syscapIntersection = syscaps[0]; - } else if (syscaps.length > 1) { - syscapIntersection = intersectNoRepeatTwice(syscaps); - } - config.syscapIntersectionSet = new Set(syscapIntersection); - config.syscapUnionSet = new Set(allSyscaps); -} - -function collectOhSyscapInfos(deviceType: string, deviceDir: string, deviceInfoMap: Map) { - let syscapFilePath: string = ''; - if (deviceType === 'phone') { - syscapFilePath = path.resolve(deviceDir, 'default.json'); - } else { - syscapFilePath = path.resolve(deviceDir, deviceType + '.json'); - } - if (fs.existsSync(syscapFilePath)) { - const content: SyscapConfig = JSON.parse(fs.readFileSync(syscapFilePath, 'utf-8')); - if (deviceInfoMap.get(deviceType)) { - deviceInfoMap.set(deviceType, deviceInfoMap.get(deviceType).concat(content.SysCaps)); - } else { - deviceInfoMap.set(deviceType, content.SysCaps); - } - } -} - -function collectExternalSyscapInfos( - externalApiPaths: string[], - deviceTypes: string[], - deviceInfoMap: Map -) { - const externalDeviceDirs: string[] = []; - externalApiPaths.forEach((externalApiPath: string) => { - const externalDeviceDir: string = path.resolve(externalApiPath, './api/device-define'); - if (fs.existsSync(externalDeviceDir)) { - externalDeviceDirs.push(externalDeviceDir); - } - }); - externalDeviceDirs.forEach((externalDeviceDir: string) => { - deviceTypes.forEach((deviceType: string) => { - let syscapFilePath: string = ''; - const files: string[] = fs.readdirSync(externalDeviceDir); - files.forEach((fileName: string) => { - if (fileName.startsWith(deviceType)) { - syscapFilePath = path.resolve(externalDeviceDir, fileName); - if (fs.existsSync(syscapFilePath)) { - const content: SyscapConfig = JSON.parse(fs.readFileSync(syscapFilePath, 'utf-8')); - if (deviceInfoMap.get(deviceType)) { - deviceInfoMap.set(deviceType, deviceInfoMap.get(deviceType).concat(content.SysCaps)); - } else { - deviceInfoMap.set(deviceType, content.SysCaps); - } - } - } - }); - }); - }); -} - -/** - * Determine the necessity of since check. - * - * @param jsDocTags - * @param config - * @returns - */ -function checkSinceValue(jsDocTags: readonly ts.JSDocTag[], config: ts.JsDocNodeCheckConfigItem): boolean { - if (!jsDocTags[0]?.parent?.parent || !projectConfig.compatibleSdkVersion) { - return false; - } - const currentNode: HasJSDocNode = jsDocTags[0].parent.parent as HasJSDocNode; - if (!currentNode.jsDoc) { - return false; - } - const minSince: string = getMinVersion(currentNode.jsDoc); - const hasSince: boolean = minSince !== ''; - - const compatibleSdkVersion: string = projectConfig.compatibleSdkVersion.toString(); - if (!isCompliantSince(minSince) || !isCompliantSince(compatibleSdkVersion)) { - return false; - } - if (hasSince && comparePointVersion(compatibleSdkVersion.toString(), minSince) === -1) { - config.message = SINCE_TAG_CHECK_ERROER.replace('$SINCE1', minSince).replace('$SINCE2', compatibleSdkVersion); - return true; - } - return false; -} - -/** - * Confirm compliance since - * Only major version can be passed in, such as "19"; - * major and minor version can be passed in, such as "19.1"; major minor and patch - * patch version can be passed in, such as "19.1.2" - * the major version be from 1-999 - * the minor version be from 0-999 - * the patch version be from 0-999 - * - * @param {string} since - * @return {boolean} - */ -function isCompliantSince(since: string): boolean { - return /^(?!0\d)[1-9]\d{0,2}(?:\.[1-9]\d{0,2}|\.0){0,2}$\d{0,2}$/.test(since); -} - -/** - * Determine the necessity of syscap check. - * @param jsDocTags - * @param config - * @returns - */ -export function checkSyscapAbility(jsDocTags: readonly ts.JSDocTag[], config: ts.JsDocNodeCheckConfigItem): boolean { - let currentSyscapValue: string = ''; - for (let i = 0; i < jsDocTags.length; i++) { - const jsDocTag: ts.JSDocTag = jsDocTags[i]; - if (jsDocTag && jsDocTag.tagName.escapedText.toString() === SYSCAP_TAG_CHECK_NAME) { - currentSyscapValue = jsDocTag.comment as string; - break; - } - } - return projectConfig.syscapIntersectionSet && !projectConfig.syscapIntersectionSet.has(currentSyscapValue); -} - -interface ConfigPermission { - requestPermissions: Array<{ name: string }>; - definePermissions: Array<{ name: string }>; -} - -interface PermissionsConfig { - permission: ConfigPermission, - requestPermissions: string[], - definePermissions: string[], -} -/** - * configure permissionInfo to this.share.projectConfig - * - * @param config this.share.projectConfig - */ -export function configurePermission(config: PermissionsConfig): void { - const permission: ConfigPermission = config.permission; - config.requestPermissions = []; - config.definePermissions = []; - if (permission.requestPermissions) { - config.requestPermissions = getNameFromArray(permission.requestPermissions); - } - if (permission.definePermissions) { - config.definePermissions = getNameFromArray(permission.definePermissions); - } -} - -function getNameFromArray(array: Array<{ name: string }>): string[] { - return array.map((item: { name: string }) => { - return String(item.name); - }); -} - -/** - * Determine the necessity of permission check - * - * @param {ts.JSDocTag[]} jsDocTags - * @param {ts.JsDocNodeCheckConfigItem} config - * @returns {boolean} - */ -export function checkPermissionValue(jsDocTags: readonly ts.JSDocTag[], config: ts.JsDocNodeCheckConfigItem): boolean { - const jsDocTag: ts.JSDocTag = jsDocTags.find((item: ts.JSDocTag) => { - return item.tagName.getText() === PERMISSION_TAG_CHECK_NAME; - }); - if (!jsDocTag) { - return false; - } - const comment: string = typeof jsDocTag.comment === 'string' ? - jsDocTag.comment : - ts.getTextOfJSDocComment(jsDocTag.comment); - config.message = PERMISSION_TAG_CHECK_ERROR.replace('$DT', comment); - return comment !== '' && !JsDocCheckService.validPermission(comment, permissionsArray); -} - -/** - * custom condition check - * @param { ts.FileCheckModuleInfo } jsDocFileCheckedInfo - * @param { ts.JsDocTagInfo[] } jsDocTagInfos - * @param { ?ts.JSDoc[] } jsDocs - * @returns - */ -export function getJsDocNodeConditionCheckResult(jsDocFileCheckedInfo: ts.FileCheckModuleInfo, jsDocTagInfos: ts.JsDocTagInfo[], jsDocs?: ts.JSDoc[]): - ts.ConditionCheckResult { - let result: ts.ConditionCheckResult = { - valid: true - }; - if (jsDocFileCheckedInfo.tagName.includes(SYSCAP_TAG_CHECK_NAME)) { - result = checkSyscapCondition(jsDocTagInfos); - } else if (jsDocFileCheckedInfo.tagName.includes(SINCE_TAG_NAME) && jsDocs) { - result = checkSinceCondition(jsDocs); - } - return result; -} - -/** - * syscap condition check - * @param { ts.JSDoc[] } jsDocs - * @returns { ts.ConditionCheckResult } - */ -function checkSyscapCondition(jsDocs: ts.JsDocTagInfo[]): ts.ConditionCheckResult { - const result: ts.ConditionCheckResult = { - valid: true - }; - let currentSyscapValue: string = ''; - for (let i = 0; i < jsDocs.length; i++) { - const jsDocTag: ts.JsDocTagInfo = jsDocs[i]; - if (jsDocTag.name === SYSCAP_TAG_CHECK_NAME) { - currentSyscapValue = jsDocTag.text as string; - break; - } - } - if (!projectConfig.syscapIntersectionSet || !projectConfig.syscapUnionSet) { - return result; - } - if (!projectConfig.syscapIntersectionSet.has(currentSyscapValue) && projectConfig.syscapUnionSet.has(currentSyscapValue)) { - result.valid = false; - result.type = ts.DiagnosticCategory.Warning; - result.message = SYSCAP_TAG_CONDITION_CHECK_WARNING; - } else if (!projectConfig.syscapUnionSet.has(currentSyscapValue)) { - result.valid = false; - // TODO: fix to error in the feature - result.type = ts.DiagnosticCategory.Warning; - result.message = SYSCAP_TAG_CHECK_WARNING.replace('$DT', projectConfig.deviceTypesMessage); - } - return result; -} - -/** - * version condition check - * @param { ts.JSDoc[] } jsDocs - * @returns { ts.ConditionCheckResult } - */ -function checkSinceCondition(jsDocs: ts.JSDoc[]): ts.ConditionCheckResult { - const result: ts.ConditionCheckResult = { - valid: true - }; - if (!jsDocs || !jsDocs[0] || !projectConfig.compatibleSdkVersion) { - return result; - } - const minVersion: string = getMinVersion(jsDocs); - const hasSince: boolean = minVersion !== ''; - - const compatibleSdkVersion: string = projectConfig.compatibleSdkVersion.toString(); - - if (hasSince && comparePointVersion(compatibleSdkVersion, minVersion) === -1) { - result.valid = false; - result.type = ts.DiagnosticCategory.Warning; - result.message = SINCE_TAG_CHECK_ERROER.replace('$SINCE1', minVersion).replace('$SINCE2', compatibleSdkVersion); - } - return result; -} - -/** - * version condition check, print error message - * @param { ts.CallExpression } node - * @param { string } specifyFuncName - * @param { string } targetVersion - * @param { ?ts.JSDoc[] } jsDocs - * @returns { boolean } - */ -function checkVersionConditionValidCallback(node: ts.CallExpression, specifyFuncName: string, targetVersion: string, jsDocs?: ts.JSDoc[]): boolean { - if (ts.isIdentifier(node.expression) && node.arguments.length === 1 && node.expression.escapedText.toString() === specifyFuncName) { - const expression = node.arguments[0]; - if (ts.isStringLiteral(expression) && jsDocs && comparePointVersion(expression.text.toString(), getMinVersion(jsDocs)) !== -1) { - return true; - } - } - return false; -} - -/** - * syscap condition check, print error message - * @param { ts.CallExpression } node - * @param { string } specifyFuncName - * @param { string } tagValue - * @param { ?ts.JSDoc[] } jsDocs - * @returns { boolean } - */ -function checkSyscapConditionValidCallback(node: ts.CallExpression, specifyFuncName: string, tagValue: string, jsDocs?: ts.JSDoc[]): boolean { - if (ts.isIdentifier(node.expression) && node.arguments.length === 1 && node.expression.escapedText.toString() === specifyFuncName) { - const expression = node.arguments[0]; - if (ts.isStringLiteral(expression) && tagValue === expression.text) { - return true; - } else if (ts.isIdentifier(expression)) { - const typeChecker: ts.TypeChecker = globalProgram.program.getTypeChecker(); - const arguSymbol: ts.Symbol | undefined = typeChecker.getSymbolAtLocation(expression); - return arguSymbol && arguSymbol.valueDeclaration && ts.isVariableDeclaration(arguSymbol.valueDeclaration) && - arguSymbol.valueDeclaration.initializer && ts.isStringLiteral(arguSymbol.valueDeclaration.initializer) && - arguSymbol.valueDeclaration.initializer.text === tagValue; - } - } - return false; -} - -/** - * get minversion - * @param { ts.JSDoc[] } jsDocs - * @returns string - */ -function getMinVersion(jsDocs: ts.JSDoc[]): string { - if (!jsDocs || !jsDocs[0]) { - return ''; - } - let minVersion: string = ''; - jsDocs.some((doc: ts.JSDoc) => { - return doc.tags?.some((tag: ts.JSDocTag) => { - if (tag.tagName.escapedText.toString() === SINCE_TAG_NAME) { - minVersion = tag.comment.toString(); - return true; - } - return false; - }); - }); - return minVersion; -} - -/** - * compare point version - * @param { string } firstVersion - * @param { string } secondVersion - * @returns { number } - */ -function comparePointVersion(firstVersion: string, secondVersion: string): number { - const firstPointVersion = firstVersion.split('.'); - const secondPointVersion = secondVersion.split('.'); - for (let i = 0; i < 3; i++) { - const part1 = parseInt(firstPointVersion[i] || '0', 10); - const part2 = parseInt(secondPointVersion[i] || '0', 10); - - if (part1 < part2) { - return -1; - } - if (part1 > part2) { - return 1; - } - } - return 0; -} \ No newline at end of file diff --git a/compiler/src/fast_build/system_api/rollup-plugin-system-api.ts b/compiler/src/fast_build/system_api/rollup-plugin-system-api.ts deleted file mode 100644 index 41f03c9cb0490d03d5ccedc5f1a1231d37f5a0f9..0000000000000000000000000000000000000000 --- a/compiler/src/fast_build/system_api/rollup-plugin-system-api.ts +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import MagicString, { SourceMap } from 'magic-string'; -import { createFilter } from '@rollup/pluginutils'; -import path from 'path'; -import { - NATIVE_MODULE, - ARKUI_X_PLUGIN, - GLOBAL_THIS_REQUIRE_NATIVE_MODULE, - GLOBAL_THIS_REQUIRE_NAPI -} from '../../pre_define'; -import { - systemModules, - projectConfig, - sdkConfigs, - sdkConfigPrefix, - extendSdkConfigs -} from '../../../main'; - -import { - writeUseOSFiles, - writeCollectionFile, - getAllComponentsOrModules -} from '../../utils'; -import { appComponentCollection } from '../../ets_checker'; -import { hasTsNoCheckOrTsIgnoreFiles } from '../ark_compiler/utils'; -import { shouldEmitJsFlagById } from '../ets_ui/rollup-plugin-ets-typescript'; - -const filterCrossplatform: (id: string) => boolean = createFilter(/(? boolean = createFilter(/(? = new Set(); - -export const appImportModuleCollection: Map> = new Map(); -export const kitModules: Map>> = new Map(); - -export function apiTransform() { - const useOSFiles: Set = new Set(); - let needModuleCollection: boolean = false; - let needComponentCollection: boolean = false; - return { - name: 'apiTransform', - load(id: string): void { - allFiles.add(path.join(id)); - }, - buildStart(): void { - if (this.share.projectConfig.isCrossplatform) { - needModuleCollection = true; - needComponentCollection = true; - } else if (this.share.projectConfig.widgetCompile) { - needModuleCollection = false; - needComponentCollection = true; - } - }, - transform(code: string, id: string): { - code: string; - map: SourceMap; - } { - let hiresStatus: boolean = this.share.projectConfig.needCompleteSourcesMap; - const shouldEmitJsFlag: boolean = id.endsWith('.js') || - shouldEmitJsFlagById(id) || projectConfig.compileMode !== 'esmodule'; - if (!shouldEmitJsFlag && - !this.share.projectConfig.isCrossplatform && - !this.share.projectConfig.widgetCompile) { - return null; - } - - if (projectConfig.isCrossplatform ? filterCrossplatform(id) : filter(id)) { - if (projectConfig.compileMode === 'esmodule') { - code = processSystemApiAndLibso(code, id, useOSFiles); - hiresStatus = hiresStatus || hasTsNoCheckOrTsIgnoreFiles.includes(id) ? - true : - false; - } else { - code = processSystemApi(code, id); - code = processLibso(code, id, useOSFiles); - hiresStatus = true; - } - } - if (!shouldEmitJsFlag) { - return null; - } - const magicString: MagicString = new MagicString(code); - return { - code: code, - map: magicString.generateMap({ hires: hiresStatus }) - }; - }, - beforeBuildEnd(): void { - this.share.allFiles = allFiles; - if (process.env.watchMode !== 'true' && !projectConfig.xtsMode && needComponentCollection) { - let widgetPath: string; - if (projectConfig.widgetCompile) { - widgetPath = path.resolve(projectConfig.aceModuleBuild, 'widget'); - } - this.share.allComponents = getAllComponentsOrModules(allFiles, 'component_collection.json'); - writeCollectionFile(projectConfig.cachePath, appComponentCollection, - this.share.allComponents, 'component_collection.json', this.share.allFiles, widgetPath); - } - }, - buildEnd(): void { - if (projectConfig.isPreview && projectConfig.aceSoPath && - useOSFiles && useOSFiles.size > 0) { - writeUseOSFiles(useOSFiles); - } - if (process.env.watchMode !== 'true' && !projectConfig.xtsMode && needModuleCollection) { - replaceKitModules(); - const allModules: Map> = getAllComponentsOrModules(allFiles, 'module_collection.json'); - writeCollectionFile(projectConfig.cachePath, appImportModuleCollection, allModules, 'module_collection.json'); - } - }, - cleanUp(): void { - allFiles.clear(); - appImportModuleCollection.clear(); - useOSFiles.clear(); - kitModules.clear(); - } - }; -} - - -function processSystemApi(content: string, sourcePath: string): string { - // 'arkui-x' represents cross platform related APIs, processed as 'ohos' - const REG_SYSTEM: RegExp = - new RegExp(`import\\s+(.+)\\s+from\\s+['"]@(${sdkConfigPrefix})\\.(\\S+)['"]|import\\s+(.+)\\s*=\\s*require\\(\\s*['"]@(${sdkConfigPrefix})\\.(\\S+)['"]\\s*\\)`, 'g'); - appImportModuleCollection.set(path.join(sourcePath), new Set()); - return content.replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6) => { - const moduleType: string = item2 || item5; - const systemKey: string = item3 || item6; - const systemValue: string = item1 || item4; - const systemModule: string = `${moduleType}.${systemKey}`; - appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); - checkModuleExist(systemModule, sourcePath); - const externalModuleParam: string = isExtendModuleType(moduleType) && - moduleType !== ARKUI_X_PLUGIN ? `, false, '', '${moduleType}'` : ``; - if (NATIVE_MODULE.has(systemModule)) { - item = `var ${systemValue} = ${GLOBAL_THIS_REQUIRE_NATIVE_MODULE}('${moduleType}.${systemKey}')`; - } else if (checkModuleType(moduleType)) { - item = `var ${systemValue} = ${GLOBAL_THIS_REQUIRE_NAPI}('${systemKey}'${externalModuleParam})`; - } - return item; - }); -} - -interface SdkConfig { - apiPath: string; - prefix: string; -} - -function isExtendModuleType(moduleType: string): boolean { - for (let i = 0; i < extendSdkConfigs.length; i++) { - const config: SdkConfig = extendSdkConfigs[i]; - if (config.prefix === `@${moduleType}`) { - return true; - } - } - return false; -} - -function checkModuleType(moduleType: string): boolean { - for (let i = 0; i < sdkConfigs.length; i++) { - const config = sdkConfigs[i]; - if (config.prefix === `@${moduleType}`) { - return true; - } - } - return false; -} - -function checkModuleExist(systemModule: string, sourcePath: string): void { - const module: string = `@${systemModule.trim()}.d.ts`; - if (/\.js$/.test(sourcePath) && !systemModules.includes(module)) { - const message: string = - `Cannot find module '${module}' or its corresponding type declarations.`; - console.error(`BUILDERROR File: ${sourcePath}\n ${message}`); - } -} - -function processLibso(content: string, sourcePath: string, useOSFiles: Set): string { - const REG_LIB_SO: RegExp = - /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; - return content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { - useOSFiles.add(sourcePath); - const libSoValue: string = item1 || item3; - const libSoKey: string = item2 || item4; - return projectConfig.bundleName && projectConfig.moduleName - ? `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true, "${projectConfig.bundleName}/${projectConfig.moduleName}");` - : `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`; - }); -} - -// It is rare to use `import xxx = require('module')` for system module and user native library, -// Here keep tackling with this for compatibility concern. -function processSystemApiAndLibso(content: string, sourcePath: string, useOSFiles: Set): string { - // 'arkui-x' represents cross platform related APIs, processed as 'ohos' - const REG_REQUIRE_SYSTEM: RegExp = new RegExp(`import\\s+(.+)\\s*=\\s*require\\(\\s*['"]@(${sdkConfigPrefix})\\.(\\S+)['"]\\s*\\)`, 'g'); - // Import libso should be recored in useOSFiles. - const REG_LIB_SO: RegExp = - /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; - // 'arkui-x' represents cross platform related APIs, processed as 'ohos' - const REG_IMPORT_SYSTEM = new RegExp(`import\\s+(.+)\\s+from\\s+['"]@(${sdkConfigPrefix})\\.(\\S+)['"]`, 'g'); - appImportModuleCollection.set(path.join(sourcePath), new Set()); - content.replace(REG_IMPORT_SYSTEM, (_, item1, item2, item3, item4, item5, item6) => { - const moduleType: string = item2 || item5; - const systemKey: string = item3 || item6; - const systemValue: string = item1 || item4; - const systemModule: string = `${moduleType}.${systemKey}`; - appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); - return _; - }); - return content.replace(REG_REQUIRE_SYSTEM, (_, item1, item2, item3, item4, item5, item6) => { - const moduleType: string = item2 || item5; - const systemKey: string = item3 || item6; - const systemValue: string = item1 || item4; - const systemModule: string = `${moduleType}.${systemKey}`; - appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); - checkModuleExist(systemModule, sourcePath); - return `import ${systemValue} from '@${moduleType}.${systemKey}'`; - }).replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { - useOSFiles.add(sourcePath); - const libSoValue: string = item1 || item3; - const libSoKey: string = item2 || item4; - return `import ${libSoValue} from 'lib${libSoKey}.so'`; - }); -} - -export function collectKitModules(fileName: string, key: string, value: string): void { - key = key.replace('@', ''); - value = value.replace('@', ''); - const currentValue: Map> = kitModules.get(fileName); - if (currentValue) { - const currentModuleName: Set = currentValue.get(key); - if (currentModuleName && !currentModuleName.has(value)) { - currentModuleName.add(value); - currentValue.set(key, currentModuleName); - } else if (!currentModuleName) { - const moduleSet: Set = new Set(); - currentValue.set(key, moduleSet.add(value)); - } - } else { - const moduleMap: Map> = new Map(); - const moduleSet: Set = new Set(); - moduleMap.set(key, moduleSet.add(value)); - kitModules.set(fileName, moduleMap); - } -} - -function compareKitModules(value: Set, kitKey: string, kitValue: Map>): void { - const realModules: Set = new Set(); - value.forEach((element: string) => { - if (kitValue.get(element)) { - kitValue.get(element).forEach((kitModuleRequest: string) => { - realModules.add(kitModuleRequest.replace(/\.d\.e?ts$/, '')); - }); - } else { - realModules.add(element); - } - }); - appImportModuleCollection.set(kitKey, realModules); -} - -function replaceKitModules(): void { - appImportModuleCollection.forEach((value: Set, key: string) => { - kitModules.forEach((kitValue: Map>, kitKey: string) => { - if (key === kitKey && value && value.size > 0) { - compareKitModules(value, kitKey, kitValue); - } - }); - }); -}