From 71a3e3487337699f0f0bc0c38036ad0e309c564f Mon Sep 17 00:00:00 2001 From: hufeng Date: Tue, 3 May 2022 23:55:42 +0800 Subject: [PATCH 1/8] compile with ohm_url module Signed-off-by: hufeng Change-Id: I84ebf3292aae496a0e2acf546328063eb91d9c33 --- compiler/src/ets_checker.ts | 23 ++++ compiler/src/resolve_ohm_url.ts | 62 ++++++++++ compiler/src/validate_ui_syntax.ts | 186 ++++++++++++++++++++++------- compiler/webpack.config.js | 2 + 4 files changed, 230 insertions(+), 43 deletions(-) create mode 100644 compiler/src/resolve_ohm_url.ts diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index db1c6ef..ec79efb 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -36,6 +36,7 @@ import { JS_BIND_COMPONENTS } from './component_map'; import { getName } from './process_component_build'; import { INNER_COMPONENT_NAMES } from './component_map'; import { props } from './compile_info'; +import { resolveSourceFile } from './resolve_ohm_url'; function readDeaclareFiles(): string[] { const declarationsFileNames: string[] = []; @@ -109,6 +110,21 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi return ts.createLanguageService(servicesHost, ts.createDocumentRegistry()); } +function getOhmUrlFile(moduleName: string): {modulePath: string, suffix: string} { + let modulePath = resolveSourceFile(moduleName); + let suffix: string; + if (modulePath.endsWith('.ets')) { + suffix = '.ets'; + } else if (modulePath.endsWith('.ts')) { + suffix = '.ts'; + } else { + modulePath = modulePath.replace('.js', '.d.ts'); + suffix = '.d.ts'; + } + + return {modulePath, suffix}; +} + function resolveModuleNames(moduleNames: string[], containingFile: string): ts.ResolvedModuleFull[] { const resolvedModules: ts.ResolvedModuleFull[] = []; for (const moduleName of moduleNames) { @@ -122,6 +138,13 @@ function resolveModuleNames(moduleNames: string[], containingFile: string): ts.R }); if (result.resolvedModule) { resolvedModules.push(result.resolvedModule); + } else if (/^@bundle:/.test(moduleName.trim())) { + const module = getOhmUrlFile(moduleName.trim()); + if (ts.sys.fileExists(module.modulePath)) { + resolvedModules.push(getResolveModule(module.modulePath, module.suffix)); + } else { + resolvedModules.push(null); + } } else if (/^@(system|ohos)/.test(moduleName.trim())) { const modulePath: string = path.resolve(__dirname, '../../../api', moduleName + '.d.ts'); if (ts.sys.fileExists(modulePath)) { diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts new file mode 100644 index 0000000..58bd303 --- /dev/null +++ b/compiler/src/resolve_ohm_url.ts @@ -0,0 +1,62 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { logger } from './compile_info'; +const { projectConfig } = require('../main'); + +const red: string = '\u001b[31m'; +const reset: string = '\u001b[39m'; + +const REG_OHM_URL = /^@bundle:(\S+)\/(\S+)\/(ets|js|node_modules)\/(\S+)$/; + +export class OHMResolverPlugin { + private source: any; + private target: any; + + constructor(source = 'resolve', target = 'resolve') { + this.source = source; + this.target = target; + } + + apply(resolver) { + const target = resolver.ensureHook(this.target); + resolver.getHook(this.source).tapAsync("OHMResolverPlugin", (request, resolveContext, callback) => { + if (/^@bundle:/.test(request.request)) { + var resolvedSourceFile: string = resolveSourceFile(request.request); + var obj = Object.assign({}, request, { + request: resolvedSourceFile + }); + return resolver.doResolve(target, obj, null, resolveContext, callback); + } + callback(); + }); + } +} + +export function resolveSourceFile(ohmUrl: string): string { + const result = ohmUrl.match(REG_OHM_URL); + // let bundleName = result[1]; + let moduleName = result[2]; + let srcKind = result[3]; + let file = path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main', srcKind, result[4]); + if(srcKind == 'ets') { + if (!file.endsWith('.ets') && !file.endsWith('ts')) { + if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) { + file += '.ets'; + } else { + file += '.ts'; + } + } + } else if(srcKind == 'js') { + if (!file.endsWith('.js')) { + file += '.js'; + } + } else { + // Todo: node_modules + } + + if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { + logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); + } + + return file; +} \ No newline at end of file diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index 318cf08..b4d9087 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -126,6 +126,7 @@ export const localStoragePropCollection: Map>> = export const isStaticViewCollection: Map = new Map(); +export const packageCollection: Map> = new Map(); export const moduleCollection: Set = new Set(); export const useOSFiles: Set = new Set(); @@ -829,56 +830,155 @@ export function preprocessNewExtend(content: string, extendCollection?: Set { + if (packageCollection.has(configFile)) { + return packageCollection.get(configFile); + } + + const rawData: string = fs.readFileSync(configFile, 'utf-8'); + const data = JSON.parse(rawData); + const bundleName = data.app.bundleName; + const moduleName = data.module.distro.moduleName; + packageCollection.set(configFile, [bundleName, moduleName]); + return [bundleName, moduleName]; +} + +function replaceSystemApi(item: string, systemValue: string, moduleType: string, systemKey: string) { + moduleCollection.add(`${moduleType}.${systemKey}`); + if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) { + item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; + } else if (moduleType === SYSTEM_PLUGIN) { + item = `var ${systemValue} = isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ? ` + + `globalThis.systemplugin.${systemKey} : globalThis.requireNapi('${systemKey}')`; + } else if (moduleType === OHOS_PLUGIN) { + item = `var ${systemValue} = globalThis.requireNapi('${systemKey}') || ` + + `(isSystemplugin('${systemKey}', '${OHOS_PLUGIN}') ? ` + + `globalThis.ohosplugin.${systemKey} : isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ` + + `? globalThis.systemplugin.${systemKey} : undefined)`; + } + return item; +} + +function replaceLibSo(importValue: string, libSoKey: string, sourcePath: string = null) { + if (sourcePath) { + useOSFiles.add(sourcePath); + } + return `var ${importValue} = globalThis.requireNapi("${libSoKey}", true);`; +} + +function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: string, moduleRequest: string, sourcePath: string = null) { + const result = moduleRequest.match(/^@(\S+):(\S+)$/) + let urlType: string = result[1]; + let url: string = result[2]; + switch(urlType) { + case 'bundle': { + let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); + let moduleKind = urlResult[3]; + if (moduleKind == 'lib') { + item = replaceLibSo(importValue, moduleRequest, sourcePath); + } + break; + } + case 'module': { + let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)$/); + let moduleName = urlResult[1]; + let moduleKind = urlResult[2]; + let modulePath = urlResult[3]; + const configJsonFile: string = + path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main/config.json'); + let bundleName = getPackageInfo(configJsonFile)[0]; + moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; + item = moduleKind == 'lib' ? + replaceLibSo(importValue, moduleRequest, sourcePath) : item.replace(/['"](\S+)['"]/, moduleRequest); + break; + } + case 'ohos': { + url = url.replace('/', '.'); + let urlResult = url.match(/^system\.(\S+)/) + moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; + if (!isSystemModule) { + item = item.replace(/['"](\S+)['"]/, moduleRequest); + } else { + let moduleType = urlResult ? 'system' : 'ohos'; + let systemKey = urlResult ? url.substring(7) : url; + item = replaceSystemApi(item, importValue, moduleType, systemKey); + } + break; + } + case 'lib': { + item = replaceLibSo(importValue, url, sourcePath); + break; + } + case 'local': { + let result = sourcePath.match(/(S+)\/src\/main\/(S+)/); + const configJsonFile: string = `${result[1]}/src/main/config.json`; + let packageInfo = getPackageInfo(configJsonFile); + let urlResult = url.match(/^(ets|js|lib)\/(S+)$/); + let moduleKind = urlResult[1]; + let modulePath = urlResult[2]; + if (moduleKind == 'lib') { + item = replaceLibSo(importValue, modulePath, sourcePath); + } else { + moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; + item = item.replace(/['"](\S+)['"]/, moduleRequest); + } + break; + } + default: + console.error("Incorrect OpenHarmony module kind: ", urlType); + } + return item; +} + +function replaceRelativePath(moduleRequest: string, sourcePath: string) { + let filePath = path.resolve(sourcePath, moduleRequest); + let result = filePath.match(/(S+)\/src\/main\/(ets|js)\/(S+)/); + const configJsonFile: string = `${result[1]}/src/main/config.json`; + let packageInfo = getPackageInfo(configJsonFile); + let bundleName = packageInfo[0]; + let moduleName = packageInfo[1]; + + return `@bundle:${bundleName}/${moduleName}/${result[2]}/${result[3]}`; +} + export function processSystemApi(content: string, isProcessAllowList: boolean = false, sourcePath: string = null, isSystemModule: boolean = false): string { - let REG_SYSTEM: RegExp; - if (isProcessAllowList) { - REG_SYSTEM = - /(import|const)\s+(.+)\s*=\s*(\_\_importDefault\()?require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)(\))?/g; - } else { - REG_SYSTEM = - /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)/g; - } - const REG_LIB_SO: RegExp = - /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; const systemValueCollection: Set = new Set(); - const newContent: string = content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { - const libSoValue: string = item1 || item3; - const libSoKey: string = item2 || item4; - if (sourcePath) { - useOSFiles.add(sourcePath); + const REG_IMPORT_DECL = isProcessAllowList ? + /(import|const)\s+(.+)\s*=\s*(\_\_importDefault\()?require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)(\))?/g : + /import\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; + + const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5) => { + let importValue: string = isProcessAllowList ? item2 : item1 || item3; + + if (isProcessAllowList) { + systemValueCollection.add(importValue); + return replaceSystemApi(item, importValue, item4, item5); } - return `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`; - }).replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6, item7) => { - let moduleType: string = item2 || item5; - let systemKey: string = item3 || item6; - let systemValue: string = item1 || item4; - if (!VALIDATE_MODULE.includes(systemValue)) { - importModuleCollection.add(systemValue); - } - if (!isProcessAllowList && !isSystemModule) { - return item; - } else if (isProcessAllowList) { - systemValue = item2; - moduleType = item4; - systemKey = item5; - systemValueCollection.add(systemValue); - } - moduleCollection.add(`${moduleType}.${systemKey}`); - if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) { - item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; - } else if (moduleType === SYSTEM_PLUGIN) { - item = `var ${systemValue} = isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ? ` + - `globalThis.systemplugin.${systemKey} : globalThis.requireNapi('${systemKey}')`; - } else if (moduleType === OHOS_PLUGIN) { - item = `var ${systemValue} = globalThis.requireNapi('${systemKey}') || ` + - `(isSystemplugin('${systemKey}', '${OHOS_PLUGIN}') ? ` + - `globalThis.ohosplugin.${systemKey} : isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ` + - `? globalThis.systemplugin.${systemKey} : undefined)`; + + let moduleRequest: string = item2 || item4; + if (/^@(\S+):/.test(moduleRequest)) { // ohmURL + return replaceOhmUrl(isSystemModule, item, importValue, moduleRequest, sourcePath); + } else if (/^@(system|ohos)\./.test(moduleRequest)) { //ohos/system.api + // ets & ts file need compile with .d.ts, so do not replace at the phase of pre_process + if (!isSystemModule) { + return item; + } + let result = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); + let moduleType: string = result[1]; + let apiName: string = result[2]; + return replaceSystemApi(item, importValue, moduleType, apiName); + } else if (/^(\.|\.\.)\//.test(moduleRequest)) { // relativePath + return replaceRelativePath(moduleRequest, sourcePath); + } else if (/^lib(\S+)\.so$/.test(moduleRequest)) { // libxxx.so + let result = moduleRequest.match(/^lib(\S+)\.so$/); + let libSoKey = result[1]; + return replaceLibSo(importValue, libSoKey, sourcePath); } + // node_modules return item; }); - return processInnerModule(newContent, systemValueCollection); + return isProcessAllowList ? processInnerModule(processedContent, systemValueCollection) : processedContent; } function processInnerModule(content: string, systemValueCollection: Set): string { diff --git a/compiler/webpack.config.js b/compiler/webpack.config.js index 3c6758a..ad3881a 100644 --- a/compiler/webpack.config.js +++ b/compiler/webpack.config.js @@ -18,6 +18,7 @@ const fs = require('fs'); const CopyPlugin = require('copy-webpack-plugin'); const Webpack = require('webpack'); const { GenAbcPlugin } = require('./lib/gen_abc_plugin'); +const { OHMResolverPlugin } = require('./lib/resolve_ohm_url'); const buildPipeServer = require('./server/build_pipe_server'); const { @@ -100,6 +101,7 @@ function initConfig(config) { global: false }, resolve: { + plugins: [new OHMResolverPlugin()], extensions: ['.js', '.ets', '.ts', '.d.ts'], modules: [ projectPath, From 1b844ddf804eb6e93f879135fa60279a00d6e136 Mon Sep 17 00:00:00 2001 From: hufeng Date: Wed, 4 May 2022 16:59:28 +0800 Subject: [PATCH 2/8] Adapt for process_import Signed-off-by: hufeng Change-Id: I23a3a7c50e5ce70795c77d07e32f439b54de1e96 --- compiler/src/process_import.ts | 8 ++++++-- compiler/src/resolve_ohm_url.ts | 6 +++++- compiler/src/validate_ui_syntax.ts | 26 ++++++++++++++------------ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/compiler/src/process_import.ts b/compiler/src/process_import.ts index e80549f..87b83b8 100644 --- a/compiler/src/process_import.ts +++ b/compiler/src/process_import.ts @@ -45,6 +45,7 @@ import { } from './validate_ui_syntax'; import { LogInfo, LogType } from './utils'; import { projectConfig } from '../main'; +import { isOhmUrl, resolveSourceFile } from './resolve_ohm_url'; export default function processImport(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration | ts.ExportDeclaration, pagesDir: string, log: LogInfo[]): void { @@ -74,12 +75,15 @@ export default function processImport(node: ts.ImportDeclaration | ts.ImportEqua defaultName = node.name.escapedText.toString(); } } - if (filePath && path.extname(filePath) !== EXTNAME_ETS && !isModule(filePath)) { + if (filePath && path.extname(filePath) !== EXTNAME_ETS && !isModule(filePath) && !isOhmUrl(filePath)) { filePath += EXTNAME_ETS; } + try { let fileResolvePath: string; - if (/^(\.|\.\.)\//.test(filePath) && filePath.indexOf(NODE_MODULES) < 0) { + if (isOhmUrl(filePath) && filePath.indexOf(NODE_MODULES) < 0) { + fileResolvePath = resolveSourceFile(filePath); + } else if (/^(\.|\.\.)\//.test(filePath) && filePath.indexOf(NODE_MODULES) < 0) { fileResolvePath = path.resolve(pagesDir, filePath); } else if (/^\//.test(filePath) && filePath.indexOf(NODE_MODULES) < 0) { fileResolvePath = filePath; diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts index 58bd303..098e982 100644 --- a/compiler/src/resolve_ohm_url.ts +++ b/compiler/src/resolve_ohm_url.ts @@ -20,7 +20,7 @@ export class OHMResolverPlugin { apply(resolver) { const target = resolver.ensureHook(this.target); resolver.getHook(this.source).tapAsync("OHMResolverPlugin", (request, resolveContext, callback) => { - if (/^@bundle:/.test(request.request)) { + if (isOhmUrl(request.request)) { var resolvedSourceFile: string = resolveSourceFile(request.request); var obj = Object.assign({}, request, { request: resolvedSourceFile @@ -32,6 +32,10 @@ export class OHMResolverPlugin { } } +export function isOhmUrl(moduleRequest: string) { + return /^@(\S+):/.test(moduleRequest) ? true : false; +} + export function resolveSourceFile(ohmUrl: string): string { const result = ohmUrl.match(REG_OHM_URL); // let bundleName = result[1]; diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index b4d9087..4d23f3f 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -70,6 +70,7 @@ import { projectConfig } from '../main'; import { collectExtend } from './process_ui_syntax'; import { importModuleCollection } from './ets_checker'; import { isExtendFunction } from './process_ui_syntax'; +import { isOhmUrl } from './resolve_ohm_url'; export interface ComponentCollection { localStorageName: string; @@ -835,8 +836,7 @@ function getPackageInfo(configFile: string): Array { return packageCollection.get(configFile); } - const rawData: string = fs.readFileSync(configFile, 'utf-8'); - const data = JSON.parse(rawData); + const data = JSON.parse(fs.readFileSync(configFile).toString()); const bundleName = data.app.bundleName; const moduleName = data.module.distro.moduleName; packageCollection.set(configFile, [bundleName, moduleName]); @@ -910,7 +910,7 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin break; } case 'local': { - let result = sourcePath.match(/(S+)\/src\/main\/(S+)/); + let result = sourcePath.match(/(S+)\/src\/main\/(ets|js)\/(S+)/); const configJsonFile: string = `${result[1]}/src/main/config.json`; let packageInfo = getPackageInfo(configJsonFile); let urlResult = url.match(/^(ets|js|lib)\/(S+)$/); @@ -930,15 +930,17 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin return item; } -function replaceRelativePath(moduleRequest: string, sourcePath: string) { +function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string) { let filePath = path.resolve(sourcePath, moduleRequest); let result = filePath.match(/(S+)\/src\/main\/(ets|js)\/(S+)/); - const configJsonFile: string = `${result[1]}/src/main/config.json`; - let packageInfo = getPackageInfo(configJsonFile); - let bundleName = packageInfo[0]; - let moduleName = packageInfo[1]; - - return `@bundle:${bundleName}/${moduleName}/${result[2]}/${result[3]}`; + if (result) { + const configJsonFile: string = `${result[1]}/src/main/config.json`; + let packageInfo = getPackageInfo(configJsonFile); + let bundleName = packageInfo[0]; + let moduleName = packageInfo[1]; + item = `@bundle:${bundleName}/${moduleName}/${result[2]}/${result[3]}`; + } + return item; } export function processSystemApi(content: string, isProcessAllowList: boolean = false, @@ -957,7 +959,7 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = } let moduleRequest: string = item2 || item4; - if (/^@(\S+):/.test(moduleRequest)) { // ohmURL + if (isOhmUrl(moduleRequest)) { // ohmURL return replaceOhmUrl(isSystemModule, item, importValue, moduleRequest, sourcePath); } else if (/^@(system|ohos)\./.test(moduleRequest)) { //ohos/system.api // ets & ts file need compile with .d.ts, so do not replace at the phase of pre_process @@ -969,7 +971,7 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = let apiName: string = result[2]; return replaceSystemApi(item, importValue, moduleType, apiName); } else if (/^(\.|\.\.)\//.test(moduleRequest)) { // relativePath - return replaceRelativePath(moduleRequest, sourcePath); + return replaceRelativePath(item, moduleRequest, sourcePath); } else if (/^lib(\S+)\.so$/.test(moduleRequest)) { // libxxx.so let result = moduleRequest.match(/^lib(\S+)\.so$/); let libSoKey = result[1]; From 51fea3119f165ef297dd639a63b66d2f38f6cf69 Mon Sep 17 00:00:00 2001 From: hufeng Date: Wed, 4 May 2022 23:47:40 +0800 Subject: [PATCH 3/8] minor bugfixs Signed-off-by: hufeng Change-Id: I52069bf199492867711d9e852146c1c22920abf3 --- compiler/src/ets_checker.ts | 11 ++++++----- compiler/src/resolve_ohm_url.ts | 23 ++++++++--------------- compiler/src/validate_ui_syntax.ts | 29 +++++++++++++++++------------ 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index ec79efb..1a13724 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -91,7 +91,7 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi return undefined; } if (/(? { if (packageCollection.has(configFile)) { return packageCollection.get(configFile); } - const data = JSON.parse(fs.readFileSync(configFile).toString()); const bundleName = data.app.bundleName; const moduleName = data.module.distro.moduleName; @@ -889,7 +890,7 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin let bundleName = getPackageInfo(configJsonFile)[0]; moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; item = moduleKind == 'lib' ? - replaceLibSo(importValue, moduleRequest, sourcePath) : item.replace(/['"](\S+)['"]/, moduleRequest); + replaceLibSo(importValue, moduleRequest, sourcePath) : item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); break; } case 'ohos': { @@ -897,7 +898,7 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin let urlResult = url.match(/^system\.(\S+)/) moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; if (!isSystemModule) { - item = item.replace(/['"](\S+)['"]/, moduleRequest); + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } else { let moduleType = urlResult ? 'system' : 'ohos'; let systemKey = urlResult ? url.substring(7) : url; @@ -910,17 +911,20 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin break; } case 'local': { - let result = sourcePath.match(/(S+)\/src\/main\/(ets|js)\/(S+)/); - const configJsonFile: string = `${result[1]}/src/main/config.json`; + let result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); + const configJsonFile: string = path.join(result[1], 'src/main/config.json'); let packageInfo = getPackageInfo(configJsonFile); - let urlResult = url.match(/^(ets|js|lib)\/(S+)$/); + let urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); let moduleKind = urlResult[1]; let modulePath = urlResult[2]; if (moduleKind == 'lib') { item = replaceLibSo(importValue, modulePath, sourcePath); + } else if (moduleKind == 'node_modules') { + moduleRequest = `${modulePath}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } else { moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; - item = item.replace(/['"](\S+)['"]/, moduleRequest); + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } break; } @@ -931,14 +935,15 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin } function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string) { - let filePath = path.resolve(sourcePath, moduleRequest); - let result = filePath.match(/(S+)\/src\/main\/(ets|js)\/(S+)/); + let filePath = path.resolve(path.dirname(sourcePath), moduleRequest); + let result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); if (result) { - const configJsonFile: string = `${result[1]}/src/main/config.json`; + const configJsonFile: string = path.join(result[1], 'src/main/config.json'); let packageInfo = getPackageInfo(configJsonFile); let bundleName = packageInfo[0]; let moduleName = packageInfo[1]; - item = `@bundle:${bundleName}/${moduleName}/${result[2]}/${result[3]}`; + moduleRequest = `@bundle:${bundleName}/${moduleName}/${result[5]}/${toUnixPath(result[7])}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } return item; } From bdba1995c14f4e568079c737537f382bba1f2005 Mon Sep 17 00:00:00 2001 From: hufeng Date: Sun, 8 May 2022 16:25:07 +0800 Subject: [PATCH 4/8] Read the module.json with sdk of api-9 Signed-off-by: hufeng Change-Id: Iedb4afeae573296059ce1f3781ce5c9f62c9551d --- compiler/src/validate_ui_syntax.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index 6e28b20..a9836bb 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -839,7 +839,7 @@ function getPackageInfo(configFile: string): Array { } const data = JSON.parse(fs.readFileSync(configFile).toString()); const bundleName = data.app.bundleName; - const moduleName = data.module.distro.moduleName; + const moduleName = projectConfig.aceModuleJsonPath ? data.module.name : data.module.distro.moduleName; packageCollection.set(configFile, [bundleName, moduleName]); return [bundleName, moduleName]; } @@ -885,7 +885,7 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin let moduleName = urlResult[1]; let moduleKind = urlResult[2]; let modulePath = urlResult[3]; - const configJsonFile: string = + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main/config.json'); let bundleName = getPackageInfo(configJsonFile)[0]; moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; @@ -912,7 +912,8 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin } case 'local': { let result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); - const configJsonFile: string = path.join(result[1], 'src/main/config.json'); + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : + path.join(result[1], 'src/main/config.json'); let packageInfo = getPackageInfo(configJsonFile); let urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); let moduleKind = urlResult[1]; @@ -938,7 +939,8 @@ function replaceRelativePath(item:string, moduleRequest: string, sourcePath: str let filePath = path.resolve(path.dirname(sourcePath), moduleRequest); let result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); if (result) { - const configJsonFile: string = path.join(result[1], 'src/main/config.json'); + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : + path.join(result[1], 'src/main/config.json'); let packageInfo = getPackageInfo(configJsonFile); let bundleName = packageInfo[0]; let moduleName = packageInfo[1]; @@ -953,20 +955,20 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = const systemValueCollection: Set = new Set(); const REG_IMPORT_DECL = isProcessAllowList ? /(import|const)\s+(.+)\s*=\s*(\_\_importDefault\()?require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)(\))?/g : - /import\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; + /(import|export)\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5) => { - let importValue: string = isProcessAllowList ? item2 : item1 || item3; + let importValue: string = isProcessAllowList ? item2 : item2 || item4; if (isProcessAllowList) { systemValueCollection.add(importValue); return replaceSystemApi(item, importValue, item4, item5); } - let moduleRequest: string = item2 || item4; + let moduleRequest: string = item3 || item5; if (isOhmUrl(moduleRequest)) { // ohmURL return replaceOhmUrl(isSystemModule, item, importValue, moduleRequest, sourcePath); - } else if (/^@(system|ohos)\./.test(moduleRequest)) { //ohos/system.api + } else if (/^@(system|ohos)\./.test(moduleRequest)) { // ohos/system.api // ets & ts file need compile with .d.ts, so do not replace at the phase of pre_process if (!isSystemModule) { return item; From 3a23fc8465ca5448a03bfdecc5b9cb8777fb1234 Mon Sep 17 00:00:00 2001 From: hufeng Date: Tue, 10 May 2022 14:21:37 +0800 Subject: [PATCH 5/8] Fix ut tests Signed-off-by: hufeng Change-Id: Ibba3d45b78bf6d10981d034a5e6e61834f8812df --- compiler/src/ets_checker.ts | 12 +-- compiler/src/resolve_ohm_url.ts | 126 ++++++++++++++++------------- compiler/src/validate_ui_syntax.ts | 26 +++--- 3 files changed, 85 insertions(+), 79 deletions(-) diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index 1a13724..7a13c0a 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -112,14 +112,8 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi function getOhmUrlFile(moduleName: string): {modulePath: string, suffix: string} { let modulePath = resolveSourceFile(moduleName); - let suffix: string; - if (modulePath.endsWith('.ets')) { - suffix = '.ets'; - } else if (modulePath.endsWith('.ts')) { - suffix = '.ts'; - } else if (modulePath.endsWith('.js')) { - suffix = '.js'; - } else { + let suffix: string = path.extname(modulePath); + if (suffix === 'ts' && modulePath.endsWith('.d.ts')) { suffix = '.d.ts'; } @@ -140,7 +134,7 @@ function resolveModuleNames(moduleNames: string[], containingFile: string): ts.R if (result.resolvedModule) { resolvedModules.push(result.resolvedModule); } else if (/^@bundle:/.test(moduleName.trim())) { - const module = getOhmUrlFile(moduleName.trim()); + const module: {modulePath: string, suffix: string} = getOhmUrlFile(moduleName.trim()); if (ts.sys.fileExists(module.modulePath)) { resolvedModules.push(getResolveModule(module.modulePath, module.suffix)); } else { diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts index 959ffba..8a906b1 100644 --- a/compiler/src/resolve_ohm_url.ts +++ b/compiler/src/resolve_ohm_url.ts @@ -1,59 +1,69 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import { logger } from './compile_info'; -const { projectConfig } = require('../main'); - -const red: string = '\u001b[31m'; -const reset: string = '\u001b[39m'; - -const REG_OHM_URL = /^@bundle:(\S+)\/(\S+)\/(ets|js)\/(\S+)$/; - -export class OHMResolverPlugin { - private source: any; - private target: any; - - constructor(source = 'resolve', target = 'resolve') { - this.source = source; - this.target = target; - } - - apply(resolver) { - const target = resolver.ensureHook(this.target); - resolver.getHook(this.source).tapAsync("OHMResolverPlugin", (request, resolveContext, callback) => { - if (isOhmUrl(request.request)) { - var resolvedSourceFile: string = resolveSourceFile(request.request); - var obj = Object.assign({}, request, { - request: resolvedSourceFile - }); - return resolver.doResolve(target, obj, null, resolveContext, callback); - } - callback(); - }); - } -} - -export function isOhmUrl(moduleRequest: string) { - return /^@(\S+):/.test(moduleRequest) ? true : false; -} - -export function resolveSourceFile(ohmUrl: string): string { - const result = ohmUrl.match(REG_OHM_URL); - let moduleName = result[2]; - let srcKind = result[3]; - let file = path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main', srcKind, result[4]); - if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) { - file += '.ets'; - } else if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) { - file += '.ts'; - } else if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) { - file += '.js'; - } else { - file += '.d.ts'; - } - - if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { - logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); - } - - return file; +import * as fs from 'fs'; +import * as path from 'path'; +import { logger } from './compile_info'; +const { projectConfig } = require('../main'); + +const red: string = '\u001b[31m'; +const reset: string = '\u001b[39m'; + +const REG_OHM_URL: RegExp = /^@bundle:(\S+)\/(\S+)\/(ets|js)\/(\S+)$/; + +export class OHMResolverPlugin { + private source: any; + private target: any; + + constructor(source = 'resolve', target = 'resolve') { + this.source = source; + this.target = target; + } + + apply(resolver) { + const target = resolver.ensureHook(this.target); + resolver.getHook(this.source).tapAsync("OHMResolverPlugin", (request, resolveContext, callback) => { + if (isOhmUrl(request.request)) { + var resolvedSourceFile: string = resolveSourceFile(request.request); + var obj = Object.assign({}, request, { + request: resolvedSourceFile + }); + return resolver.doResolve(target, obj, null, resolveContext, callback); + } + callback(); + }); + } +} + +export function isOhmUrl(moduleRequest: string): boolean { + return /^@(\S+):/.test(moduleRequest) ? true : false; +} + +function addExtension(file: string): string { + if (path.extname(file) != '') { + return file; + } + + let extension: string = '.d.ts'; + if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) { + extension = '.ets'; + } + if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) { + extension = '.ts'; + } + if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) { + extension = '.js'; + } + return file + extension; +} + +export function resolveSourceFile(ohmUrl: string): string { + const result = ohmUrl.match(REG_OHM_URL); + let moduleName = result[2]; + let srcKind = result[3]; + let file = path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main', srcKind, result[4]); + file = addExtension(file); + + if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { + logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); + } + + return file; } \ No newline at end of file diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index a9836bb..a7b9564 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -844,7 +844,7 @@ function getPackageInfo(configFile: string): Array { return [bundleName, moduleName]; } -function replaceSystemApi(item: string, systemValue: string, moduleType: string, systemKey: string) { +function replaceSystemApi(item: string, systemValue: string, moduleType: string, systemKey: string): string { moduleCollection.add(`${moduleType}.${systemKey}`); if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) { item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; @@ -860,7 +860,7 @@ function replaceSystemApi(item: string, systemValue: string, moduleType: string, return item; } -function replaceLibSo(importValue: string, libSoKey: string, sourcePath: string = null) { +function replaceLibSo(importValue: string, libSoKey: string, sourcePath: string = null): string { if (sourcePath) { useOSFiles.add(sourcePath); } @@ -936,16 +936,18 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin } function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string) { - let filePath = path.resolve(path.dirname(sourcePath), moduleRequest); - let result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); - if (result) { - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(result[1], 'src/main/config.json'); - let packageInfo = getPackageInfo(configJsonFile); - let bundleName = packageInfo[0]; - let moduleName = packageInfo[1]; - moduleRequest = `@bundle:${bundleName}/${moduleName}/${result[5]}/${toUnixPath(result[7])}`; - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + if (sourcePath) { + let filePath = path.resolve(path.dirname(sourcePath), moduleRequest); + let result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); + if (result) { + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : + path.join(result[1], 'src/main/config.json'); + let packageInfo = getPackageInfo(configJsonFile); + let bundleName = packageInfo[0]; + let moduleName = packageInfo[1]; + moduleRequest = `@bundle:${bundleName}/${moduleName}/${result[5]}/${toUnixPath(result[7])}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } } return item; } From 78a5eceda7be9468de0895b21a79aa6f1bf7c52b Mon Sep 17 00:00:00 2001 From: hufeng Date: Mon, 16 May 2022 22:22:49 +0800 Subject: [PATCH 6/8] Switch ts-loader's module to ESM Signed-off-by: hufeng Change-Id: I76cb403661677e3bfb4f610178a10e23470989d7 --- compiler/src/resolve_ohm_url.ts | 20 ++++- compiler/src/validate_ui_syntax.ts | 83 +++++++++---------- compiler/test/ut/import/importAllEts.ts | 30 +------ compiler/test/ut/import/importEts.ts | 46 +++------- compiler/test/ut/import/importExportEts.ts | 15 ++-- compiler/test/ut/import/importTs.ts | 15 ++-- .../render_component/if/if.ts | 10 +-- .../render_decorator/@styles/@stylesExport.ts | 6 +- compiler/tsconfig.json | 2 +- 9 files changed, 86 insertions(+), 141 deletions(-) diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts index 8a906b1..dbf0845 100644 --- a/compiler/src/resolve_ohm_url.ts +++ b/compiler/src/resolve_ohm_url.ts @@ -36,8 +36,8 @@ export function isOhmUrl(moduleRequest: string): boolean { return /^@(\S+):/.test(moduleRequest) ? true : false; } -function addExtension(file: string): string { - if (path.extname(file) != '') { +function addExtension(file: string, srcPath: string): string { + if (path.extname(file) !== '') { return file; } @@ -46,9 +46,15 @@ function addExtension(file: string): string { extension = '.ets'; } if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) { + if (extension != '.d.ts') { + logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); + } extension = '.ts'; } if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) { + if (extension != '.d.ts') { + logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); + } extension = '.js'; } return file + extension; @@ -58,8 +64,16 @@ export function resolveSourceFile(ohmUrl: string): string { const result = ohmUrl.match(REG_OHM_URL); let moduleName = result[2]; let srcKind = result[3]; + let file = path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main', srcKind, result[4]); - file = addExtension(file); + + if (projectConfig.aceBuildJson) { + const buildJson = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString()); + const modulePath = buildJson.modulePathMap[moduleName]; + file = path.join(modulePath, 'src/main', srcKind, result[4]); + } + + file = addExtension(file, result[4]); if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index a7b9564..a3fcb3e 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -874,28 +874,32 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin switch(urlType) { case 'bundle': { let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); - let moduleKind = urlResult[3]; - if (moduleKind == 'lib') { - item = replaceLibSo(importValue, moduleRequest, sourcePath); + if (urlResult) { + let moduleKind = urlResult[3]; + if (moduleKind === 'lib') { + item = replaceLibSo(importValue, moduleRequest, sourcePath); + } } break; } case 'module': { let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)$/); - let moduleName = urlResult[1]; - let moduleKind = urlResult[2]; - let modulePath = urlResult[3]; - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main/config.json'); - let bundleName = getPackageInfo(configJsonFile)[0]; - moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; - item = moduleKind == 'lib' ? - replaceLibSo(importValue, moduleRequest, sourcePath) : item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + if (urlResult) { + let moduleName = urlResult[1]; + let moduleKind = urlResult[2]; + let modulePath = urlResult[3]; + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : + path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main/config.json'); + let bundleName = getPackageInfo(configJsonFile)[0]; + moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; + item = moduleKind === 'lib' ? replaceLibSo(importValue, moduleRequest, sourcePath) : + item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } break; } case 'ohos': { url = url.replace('/', '.'); - let urlResult = url.match(/^system\.(\S+)/) + let urlResult = url.match(/^system\.(\S+)/); moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; if (!isSystemModule) { item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); @@ -912,20 +916,24 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin } case 'local': { let result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(result[1], 'src/main/config.json'); - let packageInfo = getPackageInfo(configJsonFile); - let urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); - let moduleKind = urlResult[1]; - let modulePath = urlResult[2]; - if (moduleKind == 'lib') { - item = replaceLibSo(importValue, modulePath, sourcePath); - } else if (moduleKind == 'node_modules') { - moduleRequest = `${modulePath}`; - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); - } else { - moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + if (result) { + const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : + path.join(result[1], 'src/main/config.json'); + let packageInfo = getPackageInfo(configJsonFile); + let urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); + if (urlResult) { + let moduleKind = urlResult[1]; + let modulePath = urlResult[2]; + if (moduleKind === 'lib') { + item = replaceLibSo(importValue, modulePath, sourcePath); + } else if (moduleKind === 'node_modules') { + moduleRequest = `${modulePath}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } else { + moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } + } } break; } @@ -954,17 +962,14 @@ function replaceRelativePath(item:string, moduleRequest: string, sourcePath: str export function processSystemApi(content: string, isProcessAllowList: boolean = false, sourcePath: string = null, isSystemModule: boolean = false): string { - const systemValueCollection: Set = new Set(); - const REG_IMPORT_DECL = isProcessAllowList ? - /(import|const)\s+(.+)\s*=\s*(\_\_importDefault\()?require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)(\))?/g : + const REG_IMPORT_DECL = isProcessAllowList ? /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]/g : /(import|export)\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5) => { - let importValue: string = isProcessAllowList ? item2 : item2 || item4; + let importValue: string = isProcessAllowList ? item1 : item2 || item4; if (isProcessAllowList) { - systemValueCollection.add(importValue); - return replaceSystemApi(item, importValue, item4, item5); + return replaceSystemApi(item, importValue, item2, item3); } let moduleRequest: string = item3 || item5; @@ -989,17 +994,7 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = // node_modules return item; }); - return isProcessAllowList ? processInnerModule(processedContent, systemValueCollection) : processedContent; -} - -function processInnerModule(content: string, systemValueCollection: Set): string { - systemValueCollection.forEach(element => { - const target: string = element.trim() + '.default'; - while (content.includes(target)) { - content = content.replace(target, element.trim()); - } - }); - return content; + return processedContent; } const VALIDATE_MODULE_REG: RegExp = new RegExp('^(' + VALIDATE_MODULE.join('|') + ')'); diff --git a/compiler/test/ut/import/importAllEts.ts b/compiler/test/ut/import/importAllEts.ts index 17441fd..fc7a23c 100644 --- a/compiler/test/ut/import/importAllEts.ts +++ b/compiler/test/ut/import/importAllEts.ts @@ -49,36 +49,12 @@ struct ImportTest { ` exports.expectResult = -`"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const AllComponent = __importStar(require("./test/pages/NamespaceComponent")); -const TsModule_1 = __importDefault(require("./test/pages/TsModule")); +`import * as AllComponent from './test/pages/NamespaceComponent'; +import TsModule from './test/pages/TsModule'; class ImportTest extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); - this.__myState1 = new ObservedPropertyObject(new TsModule_1.default(1).method(), this, "myState1"); + this.__myState1 = new ObservedPropertyObject(new TsModule(1).method(), this, "myState1"); this.__myState2 = new ObservedPropertySimple(0, this, "myState2"); this.__myState3 = new ObservedPropertySimple(false, this, "myState3"); this.__myState4 = new ObservedPropertySimple('ImportTest', this, "myState4"); diff --git a/compiler/test/ut/import/importEts.ts b/compiler/test/ut/import/importEts.ts index f57ba18..9536544 100644 --- a/compiler/test/ut/import/importEts.ts +++ b/compiler/test/ut/import/importEts.ts @@ -21,7 +21,7 @@ LinkComponentDefault, { LinkComponent3 } from './test/pages/LinkComponent' import DefaultComponent from "./test/pages/DefaultComponent" -import AMDComponentDefault = require('./test/pages/AMDComponent') +import AMDComponentDefault from "./test/pages/AMDComponent" import TsModule from './test/pages/TsModule' @Entry @@ -99,38 +99,14 @@ struct ImportTest { ` exports.expectResult = -`"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const LinkComponent_1 = __importStar(require("./test/pages/LinkComponent")); -const DefaultComponent_1 = __importDefault(require("./test/pages/DefaultComponent")); -const AMDComponentDefault = require("./test/pages/AMDComponent"); -const TsModule_1 = __importDefault(require("./test/pages/TsModule")); +`import LinkComponentDefault, { LinkComponent as LinkComponent1Ref, LinkComponent2 as LinkComponent2Ref, LinkComponent3 } from './test/pages/LinkComponent'; +import DefaultComponent from "./test/pages/DefaultComponent"; +import AMDComponentDefault from "./test/pages/AMDComponent"; +import TsModule from './test/pages/TsModule'; class ImportTest extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); - this.__myState1 = new ObservedPropertyObject(new TsModule_1.default(1).method(), this, "myState1"); + this.__myState1 = new ObservedPropertyObject(new TsModule(1).method(), this, "myState1"); this.__myState2 = new ObservedPropertySimple(0, this, "myState2"); this.__myState3 = new ObservedPropertySimple(false, this, "myState3"); this.__myState4 = new ObservedPropertySimple('ImportTest', this, "myState4"); @@ -185,7 +161,7 @@ class ImportTest extends View { Column.create(); let earlierCreatedChild_2 = this.findChildById("2"); if (earlierCreatedChild_2 == undefined) { - View.create(new LinkComponent_1.LinkComponent2("2", this, { + View.create(new LinkComponent2Ref("2", this, { LinkComponent2Link1: this.__myState1, LinkComponent2Link2: this.__myState2, LinkComponent2Link3: this.__myState3, @@ -211,7 +187,7 @@ class ImportTest extends View { Text.pop(); let earlierCreatedChild_3 = this.findChildById("3"); if (earlierCreatedChild_3 == undefined) { - View.create(new LinkComponent_1.LinkComponent("3", this, { + View.create(new LinkComponent1Ref("3", this, { LinkComponent1Link1: this.__myState1, LinkComponent1Link2: this.__myState2, LinkComponent1Link3: this.__myState3, @@ -233,7 +209,7 @@ class ImportTest extends View { } let earlierCreatedChild_4 = this.findChildById("4"); if (earlierCreatedChild_4 == undefined) { - View.create(new DefaultComponent_1.default("4", this, { + View.create(new DefaultComponent("4", this, { DefaultComponentLink1: this.__myState1, DefaultComponentLink2: this.__myState2, DefaultComponentLink3: this.__myState3, @@ -251,7 +227,7 @@ class ImportTest extends View { } let earlierCreatedChild_5 = this.findChildById("5"); if (earlierCreatedChild_5 == undefined) { - View.create(new LinkComponent_1.default("5", this, { + View.create(new LinkComponentDefault("5", this, { LinkComponent3Link1: this.__myState1, LinkComponent3Link2: this.__myState2, LinkComponent3Link3: this.__myState3, @@ -291,7 +267,7 @@ class ImportTest extends View { } let earlierCreatedChild_7 = this.findChildById("7"); if (earlierCreatedChild_7 == undefined) { - View.create(new LinkComponent_1.LinkComponent3("7", this, { + View.create(new LinkComponent3("7", this, { LinkComponent3Link1: this.__myState1, LinkComponent3Link2: this.__myState2, LinkComponent3Link3: this.__myState3, diff --git a/compiler/test/ut/import/importExportEts.ts b/compiler/test/ut/import/importExportEts.ts index 652a822..8b11bb5 100644 --- a/compiler/test/ut/import/importExportEts.ts +++ b/compiler/test/ut/import/importExportEts.ts @@ -53,17 +53,12 @@ struct ImportTest { ` exports.expectResult = -`"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const ExportStarComponent_1 = require("./test/pages/ExportStarComponent"); -const TsModule_1 = __importDefault(require("./test/pages/TsModule")); +`import { AllStarComponent } from './test/pages/ExportStarComponent'; +import TsModule from './test/pages/TsModule'; class ImportTest extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); - this.__myState1 = new ObservedPropertyObject(new TsModule_1.default(1).method(), this, "myState1"); + this.__myState1 = new ObservedPropertyObject(new TsModule(1).method(), this, "myState1"); this.__myState2 = new ObservedPropertySimple(0, this, "myState2"); this.__myState3 = new ObservedPropertySimple(false, this, "myState3"); this.__myState4 = new ObservedPropertySimple('ImportTest', this, "myState4"); @@ -118,7 +113,7 @@ class ImportTest extends View { Column.create(); let earlierCreatedChild_2 = this.findChildById("2"); if (earlierCreatedChild_2 == undefined) { - View.create(new ExportStarComponent_1.AllStarComponent.ExportComponent("2", this, { + View.create(new AllStarComponent.ExportComponent("2", this, { ExportComponent1Link1: this.__myState1, ExportComponent1Link2: this.__myState2, ExportComponent1Link3: this.__myState3, @@ -140,7 +135,7 @@ class ImportTest extends View { } let earlierCreatedChild_3 = this.findChildById("3"); if (earlierCreatedChild_3 == undefined) { - View.create(new ExportStarComponent_1.AllStarComponent.default("3", this, { + View.create(new AllStarComponent.default("3", this, { ExportComponent4Link1: this.__myState1, ExportComponent4Link2: this.__myState2, ExportComponent4Link3: this.__myState3, diff --git a/compiler/test/ut/import/importTs.ts b/compiler/test/ut/import/importTs.ts index ad5e964..40570ff 100644 --- a/compiler/test/ut/import/importTs.ts +++ b/compiler/test/ut/import/importTs.ts @@ -53,17 +53,12 @@ struct ImportTest { ` exports.expectResult = -`"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const ExportStarComponent_1 = require("./test/pages/ExportStarComponent"); -const TsModule_1 = __importDefault(require("./test/pages/TsModule")); +`import { AllStarComponent } from './test/pages/ExportStarComponent'; +import TsModule from './test/pages/TsModule'; class ImportTest extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); - this.__myState1 = new ObservedPropertyObject(new TsModule_1.default(1).method(), this, "myState1"); + this.__myState1 = new ObservedPropertyObject(new TsModule(1).method(), this, "myState1"); this.__myState2 = new ObservedPropertySimple(0, this, "myState2"); this.__myState3 = new ObservedPropertySimple(false, this, "myState3"); this.__myState4 = new ObservedPropertySimple('ImportTest', this, "myState4"); @@ -118,7 +113,7 @@ class ImportTest extends View { Column.create(); let earlierCreatedChild_2 = this.findChildById("2"); if (earlierCreatedChild_2 == undefined) { - View.create(new ExportStarComponent_1.AllStarComponent.ExportComponent("2", this, { + View.create(new AllStarComponent.ExportComponent("2", this, { ExportComponent1Link1: this.__myState1, ExportComponent1Link2: this.__myState2, ExportComponent1Link3: this.__myState3, @@ -140,7 +135,7 @@ class ImportTest extends View { } let earlierCreatedChild_3 = this.findChildById("3"); if (earlierCreatedChild_3 == undefined) { - View.create(new ExportStarComponent_1.AllStarComponent.default("3", this, { + View.create(new AllStarComponent.default("3", this, { ExportComponent4Link1: this.__myState1, ExportComponent4Link2: this.__myState2, ExportComponent4Link3: this.__myState3, diff --git a/compiler/test/ut/inner_commponent_transform/render_component/if/if.ts b/compiler/test/ut/inner_commponent_transform/render_component/if/if.ts index 16dda28..539115c 100644 --- a/compiler/test/ut/inner_commponent_transform/render_component/if/if.ts +++ b/compiler/test/ut/inner_commponent_transform/render_component/if/if.ts @@ -52,10 +52,8 @@ struct MyComponent { ` exports.expectResult = -`"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const TestComponent_1 = require("./test/pages/TestComponent"); -const TsModule_1 = require("./test/pages/TsModule"); +`import { TestComponent } from './test/pages/TestComponent'; +import { Animal } from './test/pages/TsModule'; class MyComponent extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); @@ -110,11 +108,11 @@ class MyComponent extends View { } If.pop(); If.create(); - if (TsModule_1.Animal.Dog) { + if (Animal.Dog) { If.branchId(0); let earlierCreatedChild_2 = this.findChildById("2"); if (earlierCreatedChild_2 == undefined) { - View.create(new TestComponent_1.TestComponent("2", this, { content: 'if (import enum)' })); + View.create(new TestComponent("2", this, { content: 'if (import enum)' })); } else { earlierCreatedChild_2.updateWithValueParams({ diff --git a/compiler/test/ut/render_decorator/@styles/@stylesExport.ts b/compiler/test/ut/render_decorator/@styles/@stylesExport.ts index df32684..45d3e8a 100644 --- a/compiler/test/ut/render_decorator/@styles/@stylesExport.ts +++ b/compiler/test/ut/render_decorator/@styles/@stylesExport.ts @@ -55,10 +55,7 @@ export struct FancyUseExp { ` exports.expectResult = -`"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FancyUseExp = void 0; -class FancyUseExp extends View { +`export class FancyUseExp extends View { constructor(compilerAssignedUniqueChildId, parent, params) { super(compilerAssignedUniqueChildId, parent); this.__enable = new ObservedPropertySimple(true, this, "enable"); @@ -109,6 +106,5 @@ class FancyUseExp extends View { Column.pop(); } } -exports.FancyUseExp = FancyUseExp; loadDocument(new FancyUseExp("1", undefined, {})); ` diff --git a/compiler/tsconfig.json b/compiler/tsconfig.json index 09ad1cd..b37d725 100644 --- a/compiler/tsconfig.json +++ b/compiler/tsconfig.json @@ -557,7 +557,7 @@ "resolveJsonModule": true, "skipLibCheck": true, "sourceMap": true, - "module": "commonjs", + "module": "es2020", "target": "es2017", "types": [], "typeRoots": [], From 9f8db0b3c6926b948a4ca33ea73fb159f13b61d0 Mon Sep 17 00:00:00 2001 From: hufeng Date: Sat, 28 May 2022 11:25:05 +0800 Subject: [PATCH 7/8] Change tsconfig's module type automatically Signed-off-by: hufeng Change-Id: I28675a1c6efdfe08cab43847bd78ba90b1735dbf --- compiler/src/compile_info.ts | 2 +- compiler/src/ets_checker.ts | 2 +- compiler/src/resolve_ohm_url.ts | 96 ++--- compiler/src/validate_ui_syntax.ts | 161 ++++---- compiler/tsconfig.cjs.json | 571 +++++++++++++++++++++++++++++ compiler/webpack.config.js | 16 + 6 files changed, 726 insertions(+), 122 deletions(-) create mode 100644 compiler/tsconfig.cjs.json diff --git a/compiler/src/compile_info.ts b/compiler/src/compile_info.ts index 24c37a8..01bfccb 100644 --- a/compiler/src/compile_info.ts +++ b/compiler/src/compile_info.ts @@ -220,7 +220,7 @@ export class ResultStates { if (lastModuleCollection && lastModuleCollection !== 'NULL') { lastModuleCollection.split(',').forEach(item => { moduleCollection.add(item); - }) + }); } } const moduleContent: string = diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index 7a13c0a..f976be3 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -111,7 +111,7 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi } function getOhmUrlFile(moduleName: string): {modulePath: string, suffix: string} { - let modulePath = resolveSourceFile(moduleName); + const modulePath: string = resolveSourceFile(moduleName); let suffix: string = path.extname(modulePath); if (suffix === 'ts' && modulePath.endsWith('.d.ts')) { suffix = '.d.ts'; diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts index dbf0845..0bc8c0b 100644 --- a/compiler/src/resolve_ohm_url.ts +++ b/compiler/src/resolve_ohm_url.ts @@ -13,71 +13,73 @@ export class OHMResolverPlugin { private target: any; constructor(source = 'resolve', target = 'resolve') { - this.source = source; - this.target = target; + this.source = source; + this.target = target; } apply(resolver) { - const target = resolver.ensureHook(this.target); - resolver.getHook(this.source).tapAsync("OHMResolverPlugin", (request, resolveContext, callback) => { - if (isOhmUrl(request.request)) { - var resolvedSourceFile: string = resolveSourceFile(request.request); - var obj = Object.assign({}, request, { - request: resolvedSourceFile - }); - return resolver.doResolve(target, obj, null, resolveContext, callback); - } - callback(); - }); + const target = resolver.ensureHook(this.target); + resolver.getHook(this.source).tapAsync('OHMResolverPlugin', (request, resolveContext, callback) => { + if (isOhmUrl(request.request)) { + const resolvedSourceFile: string = resolveSourceFile(request.request); + const obj = Object.assign({}, request, { + request: resolvedSourceFile + }); + return resolver.doResolve(target, obj, null, resolveContext, callback); + } + callback(); + }); } } export function isOhmUrl(moduleRequest: string): boolean { - return /^@(\S+):/.test(moduleRequest) ? true : false; + return !!/^@(\S+):/.test(moduleRequest); } function addExtension(file: string, srcPath: string): string { - if (path.extname(file) !== '') { - return file; - } + if (path.extname(file) !== '') { + return file; + } - let extension: string = '.d.ts'; - if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) { - extension = '.ets'; + let extension: string = '.d.ts'; + if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) { + extension = '.ets'; + } + if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) { + if (extension !== '.d.ts') { + logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); } - if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) { - if (extension != '.d.ts') { - logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); - } - extension = '.ts'; + extension = '.ts'; + } + if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) { + if (extension !== '.d.ts') { + logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); } - if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) { - if (extension != '.d.ts') { - logger.error(red, `ETS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset); - } - extension = '.js'; - } - return file + extension; + extension = '.js'; + } + return file + extension; } export function resolveSourceFile(ohmUrl: string): string { - const result = ohmUrl.match(REG_OHM_URL); - let moduleName = result[2]; - let srcKind = result[3]; + const result = ohmUrl.match(REG_OHM_URL); + const moduleName = result[2]; + const srcKind = result[3]; - let file = path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main', srcKind, result[4]); + let file = ''; - if (projectConfig.aceBuildJson) { - const buildJson = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString()); - const modulePath = buildJson.modulePathMap[moduleName]; - file = path.join(modulePath, 'src/main', srcKind, result[4]); - } + if (projectConfig.aceBuildJson) { + const buildJson = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString()); + const modulePath = buildJson.modulePathMap[moduleName]; + file = path.join(modulePath, 'src/main', srcKind, result[4]); + } else { + logger.error(red, `ETS:ERROR Failed to resolve OhmUrl because of aceBuildJson not existing `, reset); + } - file = addExtension(file, result[4]); + file = addExtension(file, result[4]); - if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { - logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); - } + if (!fs.existsSync(file) || !fs.statSync(file).isFile()) { + logger.error(red, `ETS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset); + } - return file; -} \ No newline at end of file + return file; +} diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index a3fcb3e..94b5239 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -58,7 +58,7 @@ import { EXTEND_ATTRIBUTE, GLOBAL_STYLE_FUNCTION, STYLES_ATTRIBUTE, - CUSTOM_BUILDER_METHOD, + CUSTOM_BUILDER_METHOD } from './component_map'; import { LogType, @@ -839,7 +839,7 @@ function getPackageInfo(configFile: string): Array { } const data = JSON.parse(fs.readFileSync(configFile).toString()); const bundleName = data.app.bundleName; - const moduleName = projectConfig.aceModuleJsonPath ? data.module.name : data.module.distro.moduleName; + const moduleName = data.module.name; packageCollection.set(configFile, [bundleName, moduleName]); return [bundleName, moduleName]; } @@ -867,47 +867,82 @@ function replaceLibSo(importValue: string, libSoKey: string, sourcePath: string return `var ${importValue} = globalThis.requireNapi("${libSoKey}", true);`; } -function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: string, moduleRequest: string, sourcePath: string = null) { - const result = moduleRequest.match(/^@(\S+):(\S+)$/) - let urlType: string = result[1]; - let url: string = result[2]; - switch(urlType) { - case 'bundle': { - let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); - if (urlResult) { - let moduleKind = urlResult[3]; - if (moduleKind === 'lib') { - item = replaceLibSo(importValue, moduleRequest, sourcePath); - } +function replaceOhmStartsWithBundle(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { + const urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); + if (urlResult) { + const moduleKind = urlResult[3]; + if (moduleKind === 'lib') { + item = replaceLibSo(importValue, moduleRequest, sourcePath); + } + } + return item; +} + +function replaceOhmStartsWithModule(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { + const urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)$/); + if (urlResult && projectConfig.aceModuleJsonPath) { + const moduleName = urlResult[1]; + const moduleKind = urlResult[2]; + const modulePath = urlResult[3]; + const bundleName = getPackageInfo(projectConfig.aceModuleJsonPath)[0]; + moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; + item = moduleKind === 'lib' ? replaceLibSo(importValue, moduleRequest, sourcePath) : + item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } + return item; +} + +function replaceOhmStartsWithOhos(url: string, item: string, importValue:string, moduleRequest: string, isSystemModule: boolean) { + url = url.replace('/', '.'); + const urlResult = url.match(/^system\.(\S+)/); + moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; + if (!isSystemModule) { + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } else { + const moduleType = urlResult ? 'system' : 'ohos'; + const systemKey = urlResult ? url.substring(7) : url; + item = replaceSystemApi(item, importValue, moduleType, systemKey); + } + return item; +} + +function replaceOhmStartsWithLocal(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { + const result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); + if (result && projectConfig.aceModuleJsonPath) { + const packageInfo = getPackageInfo(projectConfig.aceModuleJsonPath); + const urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); + if (urlResult) { + const moduleKind = urlResult[1]; + const modulePath = urlResult[2]; + if (moduleKind === 'lib') { + item = replaceLibSo(importValue, modulePath, sourcePath); + } else if (moduleKind === 'node_modules') { + moduleRequest = `${modulePath}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); + } else { + moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; + item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } + } + } + return item; +} + +function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: string, moduleRequest: string, sourcePath: string = null) { + const result = moduleRequest.match(/^@(\S+):(\S+)$/); + const urlType: string = result[1]; + const url: string = result[2]; + switch (urlType) { + case 'bundle': { + item = replaceOhmStartsWithBundle(url, item, importValue, moduleRequest, sourcePath); break; } case 'module': { - let urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)$/); - if (urlResult) { - let moduleName = urlResult[1]; - let moduleKind = urlResult[2]; - let modulePath = urlResult[3]; - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(projectConfig.projectPath, '../../../../../', moduleName, 'src/main/config.json'); - let bundleName = getPackageInfo(configJsonFile)[0]; - moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; - item = moduleKind === 'lib' ? replaceLibSo(importValue, moduleRequest, sourcePath) : - item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); - } + item = replaceOhmStartsWithModule(url, item, importValue, moduleRequest, sourcePath); break; } case 'ohos': { - url = url.replace('/', '.'); - let urlResult = url.match(/^system\.(\S+)/); - moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; - if (!isSystemModule) { - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); - } else { - let moduleType = urlResult ? 'system' : 'ohos'; - let systemKey = urlResult ? url.substring(7) : url; - item = replaceSystemApi(item, importValue, moduleType, systemKey); - } + item = replaceOhmStartsWithOhos(url, item, importValue, moduleRequest, isSystemModule); break; } case 'lib': { @@ -915,44 +950,24 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin break; } case 'local': { - let result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); - if (result) { - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(result[1], 'src/main/config.json'); - let packageInfo = getPackageInfo(configJsonFile); - let urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); - if (urlResult) { - let moduleKind = urlResult[1]; - let modulePath = urlResult[2]; - if (moduleKind === 'lib') { - item = replaceLibSo(importValue, modulePath, sourcePath); - } else if (moduleKind === 'node_modules') { - moduleRequest = `${modulePath}`; - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); - } else { - moduleRequest = `@bundle:${packageInfo[0]}/${packageInfo[1]}/${moduleKind}/${modulePath}`; - item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); - } - } - } + item = replaceOhmStartsWithLocal(url, item, importValue, moduleRequest, sourcePath); break; } default: - console.error("Incorrect OpenHarmony module kind: ", urlType); + console.error('Incorrect OpenHarmony module kind: ', urlType); } return item; } function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string) { - if (sourcePath) { - let filePath = path.resolve(path.dirname(sourcePath), moduleRequest); - let result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); - if (result) { - const configJsonFile: string = projectConfig.aceModuleJsonPath ? projectConfig.aceModuleJsonPath : - path.join(result[1], 'src/main/config.json'); - let packageInfo = getPackageInfo(configJsonFile); - let bundleName = packageInfo[0]; - let moduleName = packageInfo[1]; + // Do not replace relativePath to ohmUrl when building bundle + if (sourcePath && projectConfig.compileMode === 'esmodule') { + const filePath = path.resolve(path.dirname(sourcePath), moduleRequest); + const result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); + if (result && projectConfig.aceModuleJsonPath) { + const packageInfo = getPackageInfo(projectConfig.aceModuleJsonPath); + const bundleName = packageInfo[0]; + const moduleName = packageInfo[1]; moduleRequest = `@bundle:${bundleName}/${moduleName}/${result[5]}/${toUnixPath(result[7])}`; item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } @@ -966,13 +981,13 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = /(import|export)\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5) => { - let importValue: string = isProcessAllowList ? item1 : item2 || item4; + const importValue: string = isProcessAllowList ? item1 : item2 || item4; if (isProcessAllowList) { return replaceSystemApi(item, importValue, item2, item3); } - let moduleRequest: string = item3 || item5; + const moduleRequest: string = item3 || item5; if (isOhmUrl(moduleRequest)) { // ohmURL return replaceOhmUrl(isSystemModule, item, importValue, moduleRequest, sourcePath); } else if (/^@(system|ohos)\./.test(moduleRequest)) { // ohos/system.api @@ -980,15 +995,15 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = if (!isSystemModule) { return item; } - let result = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); - let moduleType: string = result[1]; - let apiName: string = result[2]; + const result = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); + const moduleType: string = result[1]; + const apiName: string = result[2]; return replaceSystemApi(item, importValue, moduleType, apiName); } else if (/^(\.|\.\.)\//.test(moduleRequest)) { // relativePath return replaceRelativePath(item, moduleRequest, sourcePath); } else if (/^lib(\S+)\.so$/.test(moduleRequest)) { // libxxx.so - let result = moduleRequest.match(/^lib(\S+)\.so$/); - let libSoKey = result[1]; + const result = moduleRequest.match(/^lib(\S+)\.so$/); + const libSoKey = result[1]; return replaceLibSo(importValue, libSoKey, sourcePath); } // node_modules diff --git a/compiler/tsconfig.cjs.json b/compiler/tsconfig.cjs.json new file mode 100644 index 0000000..09ad1cd --- /dev/null +++ b/compiler/tsconfig.cjs.json @@ -0,0 +1,571 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "ets": { + "render": { + "method": ["build", "pageTransition"], + "decorator": "Builder" + }, + "components": [ + "AbilityComponent", + "AlphabetIndexer", + "Animator", + "Badge", + "Blank", + "Button", + "Calendar", + "Camera", + "Canvas", + "Checkbox", + "CheckboxGroup", + "Circle", + "ColorPicker", + "ColorPickerDialog", + "Column", + "ColumnSplit", + "Counter", + "DataPanel", + "DatePicker", + "Divider", + "Ellipse", + "Flex", + "FormComponent", + "Gauge", + "GeometryView", + "Grid", + "GridItem", + "GridContainer", + "Hyperlink", + "Image", + "ImageAnimator", + "Line", + "List", + "ListItem", + "LoadingProgress", + "Marquee", + "Menu", + "Navigation", + "Navigator", + "Option", + "PageTransitionEnter", + "PageTransitionExit", + "Panel", + "Path", + "PatternLock", + "Piece", + "PluginComponent", + "Polygon", + "Polyline", + "Progress", + "QRCode", + "Radio", + "Rating", + "Rect", + "Refresh", + "RelativeContainer", + "RemoteWindow", + "Row", + "RowSplit", + "RichText", + "Scroll", + "ScrollBar", + "Search", + "Section", + "Select", + "Shape", + "Sheet", + "SideBarContainer", + "Slider", + "Span", + "Stack", + "Stepper", + "StepperItem", + "Swiper", + "TabContent", + "Tabs", + "Text", + "TextPicker", + "TextClock", + "TextArea", + "TextInput", + "TextTimer", + "TimePicker", + "Toggle", + "Video", + "Web", + "XComponent" + ], + "extend": { + "decorator": "Extend", + "components": [ + { + "name": "AbilityComponent", + "type": "AbilityComponentAttribute", + "instance": "AbilityComponentInstance" + }, + { + "name": "AlphabetIndexer", + "type": "AlphabetIndexerAttribute", + "instance": "AlphabetIndexerInstance" + }, + { + "name": "Animator", + "type": "AnimatorAttribute", + "instance": "AnimatorInstance" + }, + { + "name": "Badge", + "type": "BadgeAttribute", + "instance": "BadgeInstance" + }, + { + "name": "Blank", + "type": "BlankAttribute", + "instance": "BlankInstance" + }, + { + "name": "Button", + "type": "ButtonAttribute", + "instance": "ButtonInstance" + }, + { + "name": "Calendar", + "type": "CalendarAttribute", + "instance": "CalendarInstance" + }, + { + "name": "Camera", + "type": "CameraAttribute", + "instance": "CameraInstance" + }, + { + "name": "Canvas", + "type": "CanvasAttribute", + "instance": "CanvasInstance" + }, + { + "name": "Checkbox", + "type": "CheckboxAttribute", + "instance": "CheckboxInstance" + }, + { + "name": "CheckboxGroup", + "type": "CheckboxGroupAttribute", + "instance": "CheckboxGroupInstance" + }, + { + "name": "Circle", + "type": "CircleAttribute", + "instance": "CircleInstance" + }, + { + "name": "ColorPicker", + "type": "ColorPickerAttribute", + "instance": "ColorPickerInstance" + }, + { + "name": "ColorPickerDialog", + "type": "ColorPickerDialogAttribute", + "instance": "ColorPickerDialogInstance" + }, + { + "name": "Column", + "type": "ColumnAttribute", + "instance": "ColumnInstance" + }, + { + "name": "ColumnSplit", + "type": "ColumnSplitAttribute", + "instance": "ColumnSplitInstance" + }, + { + "name": "Counter", + "type": "CounterAttribute", + "instance": "CounterInstance" + }, + { + "name": "DataPanel", + "type": "DataPanelAttribute", + "instance": "DataPanelInstance" + }, + { + "name": "DatePicker", + "type": "DatePickerAttribute", + "instance": "DatePickerInstance" + }, + { + "name": "Divider", + "type": "DividerAttribute", + "instance": "DividerInstance" + }, + { + "name": "Ellipse", + "type": "EllipseAttribute", + "instance": "EllipseInstance" + }, + { + "name": "Flex", + "type": "FlexAttribute", + "instance": "FlexInstance" + }, + { + "name": "FormComponent", + "type": "FormComponentAttribute", + "instance": "FormComponentInstance" + }, + { + "name": "Gauge", + "type": "GaugeAttribute", + "instance": "GaugeInstance" + }, + { + "name": "GeometryView", + "type": "GeometryViewAttribute", + "instance": "GeometryViewInstance" + }, + { + "name": "Grid", + "type": "GridAttribute", + "instance": "GridInstance" + }, + { + "name": "GridItem", + "type": "GridItemAttribute", + "instance": "GridItemInstance" + }, + { + "name": "GridContainer", + "type": "GridContainerAttribute", + "instance": "GridContainerInstance" + }, + { + "name": "Hyperlink", + "type": "HyperlinkAttribute", + "instance": "HyperlinkInstance" + }, + { + "name": "Image", + "type": "ImageAttribute", + "instance": "ImageInstance" + }, + { + "name": "ImageAnimator", + "type": "ImageAnimatorAttribute", + "instance": "ImageAnimatorInstance" + }, + { + "name": "Line", + "type": "LineAttribute", + "instance": "LineInstance" + }, + { + "name": "List", + "type": "ListAttribute", + "instance": "ListInstance" + }, + { + "name": "ListItem", + "type": "ListItemAttribute", + "instance": "ListItemInstance" + }, + { + "name": "LoadingProgress", + "type": "LoadingProgressAttribute", + "instance": "LoadingProgressInstance" + }, + { + "name": "Marquee", + "type": "MarqueeAttribute", + "instance": "MarqueeInstance" + }, + { + "name": "Menu", + "type": "MenuAttribute", + "instance": "MenuInstance" + }, + { + "name": "Navigation", + "type": "NavigationAttribute", + "instance": "NavigationInstance" + }, + { + "name": "Navigator", + "type": "NavigatorAttribute", + "instance": "NavigatorInstance" + }, + { + "name": "Option", + "type": "OptionAttribute", + "instance": "OptionInstance" + }, + { + "name": "PageTransitionEnter", + "type": "PageTransitionEnterAttribute", + "instance": "PageTransitionEnterInstance" + }, + { + "name": "PageTransitionExit", + "type": "PageTransitionExitAttribute", + "instance": "PageTransitionExitInstance" + }, + { + "name": "Panel", + "type": "PanelAttribute", + "instance": "PanelInstance" + }, + { + "name": "Path", + "type": "PathAttribute", + "instance": "PathInstance" + }, + { + "name": "PatternLock", + "type": "PatternLockAttribute", + "instance": "PatternLockInstance" + }, + { + "name": "Piece", + "type": "PieceAttribute", + "instance": "PieceInstance" + }, + { + "name": "PluginComponent", + "type": "PluginComponentAttribute", + "instance": "PluginComponentInstance" + }, + { + "name": "Polygon", + "type": "PolygonAttribute", + "instance": "PolygonInstance" + }, + { + "name": "Polyline", + "type": "PolylineAttribute", + "instance": "PolylineInstance" + }, + { + "name": "Progress", + "type": "ProgressAttribute", + "instance": "ProgressInstance" + }, + { + "name": "QRCode", + "type": "QRCodeAttribute", + "instance": "QRCodeInstance" + }, + { + "name": "Radio", + "type": "RadioAttribute", + "instance": "RadioInstance" + }, + { + "name": "Rating", + "type": "RatingAttribute", + "instance": "RatingInstance" + }, + { + "name": "Rect", + "type": "RectAttribute", + "instance": "RectInstance" + }, + { + "name": "RelativeContainer", + "type": "RelativeContainerAttribute", + "instance": "RelativeContainerInstance" + }, + { + "name": "Refresh", + "type": "RefreshAttribute", + "instance": "RefreshInstance" + }, + { + "name": "RemoteWindow", + "type": "RemoteWindowAttribute", + "instance": "RemoteWindowInstance" + }, + { + "name": "Row", + "type": "RowAttribute", + "instance": "RowInstance" + }, + { + "name": "RowSplit", + "type": "RowSplitAttribute", + "instance": "RowSplitInstance" + }, + { + "name": "RichText", + "type": "RichTextAttribute", + "instance": "RichTextInstance" + }, + { + "name": "Scroll", + "type": "ScrollAttribute", + "instance": "ScrollInstance" + }, + { + "name": "ScrollBar", + "type": "ScrollBarAttribute", + "instance": "ScrollBarInstance" + }, + { + "name": "Search", + "type": "SearchAttribute", + "instance": "SearchInstance" + }, + { + "name": "Section", + "type": "SectionAttribute", + "instance": "SectionInstance" + }, + { + "name": "Select", + "type": "SelectAttribute", + "instance": "SelectInstance" + }, + { + "name": "Shape", + "type": "ShapeAttribute", + "instance": "ShapeInstance" + }, + { + "name": "Sheet", + "type": "SheetAttribute", + "instance": "SheetInstance" + }, + { + "name": "SideBarContainer", + "type": "SideBarContainerAttribute", + "instance": "SideBarContainerInstance" + }, + { + "name": "Slider", + "type": "SliderAttribute", + "instance": "SliderInstance" + }, + { + "name": "Span", + "type": "SpanAttribute", + "instance": "SpanInstance" + }, + { + "name": "Stack", + "type": "StackAttribute", + "instance": "StackInstance" + }, + { + "name": "Stepper", + "type": "StepperAttribute", + "instance": "StepperInstance" + }, + { + "name": "StepperItem", + "type": "StepperItemAttribute", + "instance": "StepperItemInstance" + }, + { + "name": "Swiper", + "type": "SwiperAttribute", + "instance": "SwiperInstance" + }, + { + "name": "TabContent", + "type": "TabContentAttribute", + "instance": "TabContentInstance" + }, + { + "name": "Tabs", + "type": "TabsAttribute", + "instance": "TabsInstance" + }, + { + "name": "Text", + "type": "TextAttribute", + "instance": "TextInstance" + }, + { + "name": "TextPicker", + "type": "TextPickerAttribute", + "instance": "TextPickerInstance" + }, + { + "name": "TextClock", + "type": "TextClockAttribute", + "instance": "TextClockInstance" + }, + { + "name": "TextArea", + "type": "TextAreaAttribute", + "instance": "TextAreaInstance" + }, + { + "name": "TextInput", + "type": "TextInputAttribute", + "instance": "TextInputInstance" + }, + { + "name": "TextTimer", + "type": "TextTimerAttribute", + "instance": "TextTimerInstance" + }, + { + "name": "TimePicker", + "type": "TimePickerAttribute", + "instance": "TimePickerInstance" + }, + { + "name": "Toggle", + "type": "ToggleAttribute", + "instance": "ToggleInstance" + }, + { + "name": "Video", + "type": "VideoAttribute", + "instance": "VideoInstance" + }, + { + "name": "Web", + "type": "WebAttribute", + "instance": "WebInstance" + }, + { + "name": "XComponent", + "type": "XComponentAttribute", + "instance": "XComponentInstance" + }, + ] + }, + "styles": { + "decorator": "Styles", + "component": { + "name": "Common", + "type": "T", + "instance": "CommonInstance" + }, + "property": "stateStyles" + }, + }, + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "importsNotUsedAsValues": "preserve", + "noImplicitAny": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "experimentalDecorators": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "module": "commonjs", + "target": "es2017", + "types": [], + "typeRoots": [], + "lib": [ + "es2020" + ] + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/compiler/webpack.config.js b/compiler/webpack.config.js index ad3881a..144c862 100644 --- a/compiler/webpack.config.js +++ b/compiler/webpack.config.js @@ -287,10 +287,26 @@ function setOptimizationConfig(config, workerFile) { } } +function setTsConfigFile() { + let tsconfigTemplate = + path.resolve(__dirname, projectConfig.compileMode === 'esmodule' ? 'tsconfig.esm.json' : 'tsconfig.cjs.json'); + if (fs.existsSync(tsconfigTemplate) && fs.statSync(tsconfigTemplate).isFile()) { + let currentTsconfigFile = path.resolve(__dirname, 'tsconfig.json'); + let tsconfigTemplateNew = + currentTsconfigFile.replace(/.json$/, projectConfig.compileMode === 'esmodule' ? '.cjs.json' : '.esm.json'); + fs.renameSync(currentTsconfigFile, tsconfigTemplateNew); + + let tsconfigFileNew = + tsconfigTemplate.replace(projectConfig.compileMode === 'esmodule' ? /.esm.json$/ : /.cjs.json$/, '.json'); + fs.renameSync(tsconfigTemplate, tsconfigFileNew); + } +} + module.exports = (env, argv) => { const config = {}; setProjectConfig(env); loadEntryObj(projectConfig); + setTsConfigFile(); initConfig(config); const workerFile = readWorkerFile(); setOptimizationConfig(config, workerFile); From 8295383dc4c0a6d35cb64bee96996b810e933e88 Mon Sep 17 00:00:00 2001 From: hufeng Date: Mon, 6 Jun 2022 15:19:52 +0800 Subject: [PATCH 8/8] Add types Signed-off-by: hufeng Change-Id: I5a1b9949a5360579bb4530cc4e562ae455b78b77 --- compiler/src/resolve_ohm_url.ts | 49 ++++++++++---------- compiler/src/validate_ui_syntax.ts | 72 +++++++++++++++--------------- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/compiler/src/resolve_ohm_url.ts b/compiler/src/resolve_ohm_url.ts index 0bc8c0b..68107e8 100644 --- a/compiler/src/resolve_ohm_url.ts +++ b/compiler/src/resolve_ohm_url.ts @@ -9,27 +9,27 @@ const reset: string = '\u001b[39m'; const REG_OHM_URL: RegExp = /^@bundle:(\S+)\/(\S+)\/(ets|js)\/(\S+)$/; export class OHMResolverPlugin { - private source: any; - private target: any; + private source: any; + private target: any; - constructor(source = 'resolve', target = 'resolve') { - this.source = source; - this.target = target; - } + constructor(source = 'resolve', target = 'resolve') { + this.source = source; + this.target = target; + } - apply(resolver) { - const target = resolver.ensureHook(this.target); - resolver.getHook(this.source).tapAsync('OHMResolverPlugin', (request, resolveContext, callback) => { - if (isOhmUrl(request.request)) { - const resolvedSourceFile: string = resolveSourceFile(request.request); - const obj = Object.assign({}, request, { - request: resolvedSourceFile - }); - return resolver.doResolve(target, obj, null, resolveContext, callback); - } - callback(); - }); - } + apply(resolver) { + const target: any = resolver.ensureHook(this.target); + resolver.getHook(this.source).tapAsync('OHMResolverPlugin', (request, resolveContext, callback) => { + if (isOhmUrl(request.request)) { + const resolvedSourceFile: string = resolveSourceFile(request.request); + const obj = Object.assign({}, request, { + request: resolvedSourceFile + }); + return resolver.doResolve(target, obj, null, resolveContext, callback); + } + callback(); + }); + } } export function isOhmUrl(moduleRequest: string): boolean { @@ -61,15 +61,14 @@ function addExtension(file: string, srcPath: string): string { } export function resolveSourceFile(ohmUrl: string): string { - const result = ohmUrl.match(REG_OHM_URL); - const moduleName = result[2]; - const srcKind = result[3]; + const result: RegExpMatchArray = ohmUrl.match(REG_OHM_URL); + const moduleName: string = result[2]; + const srcKind: string = result[3]; - let file = ''; + let file: string = ''; if (projectConfig.aceBuildJson) { - const buildJson = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString()); - const modulePath = buildJson.modulePathMap[moduleName]; + const modulePath: string = projectConfig.modulePathMap[moduleName]; file = path.join(modulePath, 'src/main', srcKind, result[4]); } else { logger.error(red, `ETS:ERROR Failed to resolve OhmUrl because of aceBuildJson not existing `, reset); diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index 94b5239..fd8e5e3 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -70,9 +70,9 @@ import { } from './utils'; import { projectConfig } from '../main'; import { collectExtend } from './process_ui_syntax'; -import { importModuleCollection } from './ets_checker'; import { isExtendFunction } from './process_ui_syntax'; import { isOhmUrl } from './resolve_ohm_url'; +import { logger } from './compile_info'; export interface ComponentCollection { localStorageName: string; @@ -837,9 +837,9 @@ function getPackageInfo(configFile: string): Array { if (packageCollection.has(configFile)) { return packageCollection.get(configFile); } - const data = JSON.parse(fs.readFileSync(configFile).toString()); - const bundleName = data.app.bundleName; - const moduleName = data.module.name; + const data: any = JSON.parse(fs.readFileSync(configFile).toString()); + const bundleName: string = data.app.bundleName; + const moduleName: string = data.module.name; packageCollection.set(configFile, [bundleName, moduleName]); return [bundleName, moduleName]; } @@ -867,10 +867,10 @@ function replaceLibSo(importValue: string, libSoKey: string, sourcePath: string return `var ${importValue} = globalThis.requireNapi("${libSoKey}", true);`; } -function replaceOhmStartsWithBundle(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { - const urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); +function replaceOhmStartsWithBundle(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string): string { + const urlResult: RegExpMatchArray | null = url.match(/^(\S+)\/(\S+)\/(\S+)\/(\S+)$/); if (urlResult) { - const moduleKind = urlResult[3]; + const moduleKind: string = urlResult[3]; if (moduleKind === 'lib') { item = replaceLibSo(importValue, moduleRequest, sourcePath); } @@ -878,13 +878,13 @@ function replaceOhmStartsWithBundle(url: string, item: string, importValue: stri return item; } -function replaceOhmStartsWithModule(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { - const urlResult = url.match(/^(\S+)\/(\S+)\/(\S+)$/); +function replaceOhmStartsWithModule(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string): string { + const urlResult: RegExpMatchArray | null = url.match(/^(\S+)\/(\S+)\/(\S+)$/); if (urlResult && projectConfig.aceModuleJsonPath) { - const moduleName = urlResult[1]; - const moduleKind = urlResult[2]; - const modulePath = urlResult[3]; - const bundleName = getPackageInfo(projectConfig.aceModuleJsonPath)[0]; + const moduleName: string = urlResult[1]; + const moduleKind: string = urlResult[2]; + const modulePath: string = urlResult[3]; + const bundleName: string = getPackageInfo(projectConfig.aceModuleJsonPath)[0]; moduleRequest = `@bundle:${bundleName}/${moduleName}/${moduleKind}/${modulePath}`; item = moduleKind === 'lib' ? replaceLibSo(importValue, moduleRequest, sourcePath) : item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); @@ -892,28 +892,28 @@ function replaceOhmStartsWithModule(url: string, item: string, importValue: stri return item; } -function replaceOhmStartsWithOhos(url: string, item: string, importValue:string, moduleRequest: string, isSystemModule: boolean) { +function replaceOhmStartsWithOhos(url: string, item: string, importValue:string, moduleRequest: string, isSystemModule: boolean): string { url = url.replace('/', '.'); - const urlResult = url.match(/^system\.(\S+)/); + const urlResult: RegExpMatchArray | null = url.match(/^system\.(\S+)/); moduleRequest = urlResult ? `@${url}` : `@ohos.${url}`; if (!isSystemModule) { item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } else { - const moduleType = urlResult ? 'system' : 'ohos'; - const systemKey = urlResult ? url.substring(7) : url; + const moduleType: string = urlResult ? 'system' : 'ohos'; + const systemKey: string = urlResult ? url.substring(7) : url; item = replaceSystemApi(item, importValue, moduleType, systemKey); } return item; } -function replaceOhmStartsWithLocal(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string) { - const result = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); +function replaceOhmStartsWithLocal(url: string, item: string, importValue: string, moduleRequest: string, sourcePath: string): string { + const result: RegExpMatchArray | null = sourcePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); if (result && projectConfig.aceModuleJsonPath) { - const packageInfo = getPackageInfo(projectConfig.aceModuleJsonPath); - const urlResult = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); + const packageInfo: string[] = getPackageInfo(projectConfig.aceModuleJsonPath); + const urlResult: RegExpMatchArray | null = url.match(/^\/(ets|js|lib|node_modules)\/(\S+)$/); if (urlResult) { - const moduleKind = urlResult[1]; - const modulePath = urlResult[2]; + const moduleKind: string = urlResult[1]; + const modulePath: string = urlResult[2]; if (moduleKind === 'lib') { item = replaceLibSo(importValue, modulePath, sourcePath); } else if (moduleKind === 'node_modules') { @@ -928,8 +928,8 @@ function replaceOhmStartsWithLocal(url: string, item: string, importValue: strin return item; } -function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: string, moduleRequest: string, sourcePath: string = null) { - const result = moduleRequest.match(/^@(\S+):(\S+)$/); +function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: string, moduleRequest: string, sourcePath: string = null): string { + const result: RegExpMatchArray = moduleRequest.match(/^@(\S+):(\S+)$/); const urlType: string = result[1]; const url: string = result[2]; switch (urlType) { @@ -954,20 +954,20 @@ function replaceOhmUrl(isSystemModule: boolean, item: string, importValue: strin break; } default: - console.error('Incorrect OpenHarmony module kind: ', urlType); + logger.error('\u001b[31m', `ETS:ERROR Incorrect OpenHarmony module kind: ${urlType}`, '\u001b[39m'); } return item; } -function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string) { +function replaceRelativePath(item:string, moduleRequest: string, sourcePath: string): string { // Do not replace relativePath to ohmUrl when building bundle if (sourcePath && projectConfig.compileMode === 'esmodule') { - const filePath = path.resolve(path.dirname(sourcePath), moduleRequest); - const result = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); + const filePath: string = path.resolve(path.dirname(sourcePath), moduleRequest); + const result: RegExpMatchArray | null = filePath.match(/(\S+)(\/|\\)src(\/|\\)main(\/|\\)(ets|js)(\/|\\)(\S+)/); if (result && projectConfig.aceModuleJsonPath) { - const packageInfo = getPackageInfo(projectConfig.aceModuleJsonPath); - const bundleName = packageInfo[0]; - const moduleName = packageInfo[1]; + const packageInfo: string[] = getPackageInfo(projectConfig.aceModuleJsonPath); + const bundleName: string = packageInfo[0]; + const moduleName: string = packageInfo[1]; moduleRequest = `@bundle:${bundleName}/${moduleName}/${result[5]}/${toUnixPath(result[7])}`; item = item.replace(/['"](\S+)['"]/, '\"' + moduleRequest + '\"'); } @@ -977,7 +977,7 @@ function replaceRelativePath(item:string, moduleRequest: string, sourcePath: str export function processSystemApi(content: string, isProcessAllowList: boolean = false, sourcePath: string = null, isSystemModule: boolean = false): string { - const REG_IMPORT_DECL = isProcessAllowList ? /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]/g : + const REG_IMPORT_DECL: RegExp = isProcessAllowList ? /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]/g : /(import|export)\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5) => { @@ -995,15 +995,15 @@ export function processSystemApi(content: string, isProcessAllowList: boolean = if (!isSystemModule) { return item; } - const result = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); + const result: RegExpMatchArray = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); const moduleType: string = result[1]; const apiName: string = result[2]; return replaceSystemApi(item, importValue, moduleType, apiName); } else if (/^(\.|\.\.)\//.test(moduleRequest)) { // relativePath return replaceRelativePath(item, moduleRequest, sourcePath); } else if (/^lib(\S+)\.so$/.test(moduleRequest)) { // libxxx.so - const result = moduleRequest.match(/^lib(\S+)\.so$/); - const libSoKey = result[1]; + const result: RegExpMatchArray = moduleRequest.match(/^lib(\S+)\.so$/); + const libSoKey: string = result[1]; return replaceLibSo(importValue, libSoKey, sourcePath); } // node_modules