From 49e4429a79153d5a0349484d5aead5667ebb7d47 Mon Sep 17 00:00:00 2001 From: zhaojunxia Date: Thu, 3 Nov 2022 16:27:54 +0800 Subject: [PATCH 1/3] add api_scan_vs_plugin Signed-off-by: zhaojunxia --- hdc/API-Scan/package.json | 12 +- hdc/API-Scan/scan.js | 2 +- hdc/api_scan_vs_plugin/docs/DEVELOP_ZH.md | 83 ++++++++ hdc/api_scan_vs_plugin/package.json | 29 +++ hdc/api_scan_vs_plugin/src/extension.js | 172 +++++++++++++++ .../src/gen/tools/VsPluginLog.js | 78 +++++++ .../src/gen/tools/VsPluginRe.js | 65 ++++++ .../src/gen/tools/VsPluginTool.js | 112 ++++++++++ hdc/api_scan_vs_plugin/src/images/file.png | Bin 0 -> 311 bytes hdc/api_scan_vs_plugin/src/images/path.png | Bin 0 -> 608 bytes hdc/api_scan_vs_plugin/src/jsconfig.json | 13 ++ hdc/api_scan_vs_plugin/src/package.json | 65 ++++++ .../src/vs_plugin_view.html | 197 ++++++++++++++++++ 13 files changed, 825 insertions(+), 3 deletions(-) create mode 100644 hdc/api_scan_vs_plugin/docs/DEVELOP_ZH.md create mode 100644 hdc/api_scan_vs_plugin/package.json create mode 100644 hdc/api_scan_vs_plugin/src/extension.js create mode 100644 hdc/api_scan_vs_plugin/src/gen/tools/VsPluginLog.js create mode 100644 hdc/api_scan_vs_plugin/src/gen/tools/VsPluginRe.js create mode 100644 hdc/api_scan_vs_plugin/src/gen/tools/VsPluginTool.js create mode 100644 hdc/api_scan_vs_plugin/src/images/file.png create mode 100644 hdc/api_scan_vs_plugin/src/images/path.png create mode 100644 hdc/api_scan_vs_plugin/src/jsconfig.json create mode 100644 hdc/api_scan_vs_plugin/src/package.json create mode 100644 hdc/api_scan_vs_plugin/src/vs_plugin_view.html diff --git a/hdc/API-Scan/package.json b/hdc/API-Scan/package.json index 84bb6e5b..507d800a 100755 --- a/hdc/API-Scan/package.json +++ b/hdc/API-Scan/package.json @@ -9,7 +9,15 @@ "author": "", "license": "ISC", "dependencies": { - "xlsx": "^0.18.5", - "stdio": "^2.1.1" + "stdio": "^2.1.1", + "typescript": "^4.8.4", + "xlsx": "^0.18.5" + }, + "bin": "./scan.js", + "pkg": { + "assets": [ + "node_modules/typescript/**/*", + "./*.xlsx" + ] } } diff --git a/hdc/API-Scan/scan.js b/hdc/API-Scan/scan.js index 72c2dffe..00bae8a4 100755 --- a/hdc/API-Scan/scan.js +++ b/hdc/API-Scan/scan.js @@ -64,7 +64,7 @@ function collectFromSheet(sheet) { } return [collectInclude, collectFunction] } -let wb = xlsx.readFile("Andr_N_Games_api.xlsx"); +let wb = xlsx.readFile(path.join(__dirname, "Andr_N_Games_api.xlsx")); let c1 = collectFromSheet(wb.Sheets.Games); let c2 = collectFromSheet(wb.Sheets.N); diff --git a/hdc/api_scan_vs_plugin/docs/DEVELOP_ZH.md b/hdc/api_scan_vs_plugin/docs/DEVELOP_ZH.md new file mode 100644 index 00000000..801deede --- /dev/null +++ b/hdc/api_scan_vs_plugin/docs/DEVELOP_ZH.md @@ -0,0 +1,83 @@ +# NAPI框架生成工具VSCode插件开发说明 + +若当前工具功能不满足开发者需求,开发者需增强工具能力,则可基于已有源码进行工具二次开发,编译打包生成自定义的VS Code插件。 + +## VS Code插件打包说明 + +### Linux + +1.在API_Scan目录下,将search-linux下可执行文件复制到napi_generator/hdc/api_scan_vs_plugin/src/目录下,执行命令如下: + + cp search-linux hdc/api_scan_vs_plugin/src/ + +2.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i + +3.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件ApiScan-0.0.1.vsix。结果如下: + + kaihong1@ubuntu:~/napi_generator_gjj/hdc/api_scan_vs_plugin/src$ npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3282 files, out of which 1547 are JavaScript files. For performance reasons, you shoude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: /home/kaihong1/napi_generator_gjj/hdc/api_scan_vs_plugin/src/ApiScan-0.0.1.vsix (3282 files, 50.34MB) + + +### Windows + +1.将napi_generator目录下的search-win.exe可执行文件复制到napi_generator/hdc/api_scan_vs_plugin/src/目录下。 + +2.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i + +3.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/api_scan_vs_plugin/src/目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件ApiScan-0.0.1.vsix。结果如下: + + C:\napi_generator_GJJ\hdc\api_scan_vs_plugin\src>npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3282 files, out of which 1547 are JavaScript files. For performance reasons, you should bundle your extension: https://aka.ms/vscode-bundle-extension . You should also exclude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: C:\napi_generator_GJJ\hdc\api_scan_vs_plugin\src\ApiScan-0.0.1.vsix (3282 files, 47.42MB) + +## 工具测试 + + 进行工具二次开发后,本地可进行单元测试、story特性测试确保工具的可用性。左键单击以下链接了解详情: + + [单元测试]暂无 + + [story测试]暂无 + diff --git a/hdc/api_scan_vs_plugin/package.json b/hdc/api_scan_vs_plugin/package.json new file mode 100644 index 00000000..bbbd314e --- /dev/null +++ b/hdc/api_scan_vs_plugin/package.json @@ -0,0 +1,29 @@ +{ + "name": "api_scan_vs_plugin", + "version": "1.0.0", + "description": "This tool can scan the Android APIs in OpenHarmony Projects.", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "dependencies": { + "mocha": "^9.2.1", + "node-gyp": "^8.4.1", + "stdio": "^2.1.1", + "typescript": "^4.5.5" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@gitee.com:joeysun001/napi_generator.git" + }, + "author": "", + "license": "ISC", + "pkg": { + "assets": [ + "src/node_modules/typescript/**/*" + ] + } +} diff --git a/hdc/api_scan_vs_plugin/src/extension.js b/hdc/api_scan_vs_plugin/src/extension.js new file mode 100644 index 00000000..c0c563af --- /dev/null +++ b/hdc/api_scan_vs_plugin/src/extension.js @@ -0,0 +1,172 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = require('vscode'); +const fs = require('fs'); +const re = require("./gen/tools/VsPluginRe"); +const { VsPluginLog } = require("./gen/tools/VsPluginLog"); +const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool'); +const path = require('path'); +var exeFilePath = null; +const dirCache={}; +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed + +/** + * @param {vscode.ExtensionContext} context + */ +function activate(context) { + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "gnapi" is now active!'); + let disposable = register(context, 'api_scan'); + let disposableMenu = register(context, 'api_scan_menu'); + context.subscriptions.push(disposable); + context.subscriptions.push(disposableMenu); + var platform = detectPlatform(); + if (platform == 'win') { + exeFilePath = __dirname + "/search-win.exe"; + } else if (platform == 'mac') { + exeFilePath = __dirname + "/search-macos"; + } else if (platform == 'Linux') { + exeFilePath = __dirname + "/search-linux"; + } +} + +function executorApiscan(name, genDir) { + if (genDir == "" || genDir == null) { + genDir = name; + } + var command = exeFilePath + " -d " + name + " -o " + genDir; + var exec = require('child_process').exec; + exec(command, function (error, stdout, stderr) { + VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); + if (error || stdout.indexOf("errno") > 0) { + vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); + return VsPluginLog.logError("VsPlugin:" + error + stdout); + } + vscode.window.showInformationMessage("api scan successfully"); + }); +} + +function exeFileExit() { + if (fs.existsSync(exeFilePath)) { + return true; + } + return false; +} + +function register(context, command) { + let disposable = vscode.commands.registerCommand(command, function (uri) { + // The code you place here will be executed every time your command is executed + // Display a message box to the user + const panel = vscode.window.createWebviewPanel( + 'api_scan', // Identifies the type of WebView + 'Api Scan', // Title of the panel displayed to the user + vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor + { + enableScripts: true, // Enable or disable JS, default is Enable + retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset + } + ); + panel.webview.html = getWebviewContent(context); + let msg; + panel.webview.onDidReceiveMessage(message => { + msg = message.msg; + if (msg == "cancel") { + panel.dispose(); + } + else if (msg == "api_scan") { + let name = message.fileNames; + let genDir = message.genDir; + name = re.replaceAll(name, " ", ""); + if ("" == name) { + vscode.window.showErrorMessage("Please enter the path!"); + return; + } + if (exeFileExit()) { + executorApiscan(name, genDir); + } else { + vscode.window.showInformationMessage("Copy executable program to " + __dirname); + } + }else { + selectPath(panel, message); + } + }, undefined, context.subscriptions); + let fn = re.getFileInPath(uri.fsPath); + let tt = re.match("[a-zA-Z_0-9]", fn); + var result = { + msg: "selectASFilePath", + path: tt ? uri.fsPath : "" + } + panel.webview.postMessage(result); + }); + return disposable; +} + +/** +* 选择本地目录/文件夹 +*/ +function selectPath(panel, message) { + const options = { + canSelectMany: false,//是否可以选择多个 + canSelectFolders: true,//是否选择文件夹 + defaultUri:vscode.Uri.file('')//默认打开本地路径 + }; + + return vscode.window.showOpenDialog(options).then(fileUri => { + if (fileUri && fileUri[0]) { + console.log('Selected file: ' + fileUri[0].fsPath); + let filePath = ""; + for (let index = 0; index < fileUri.length; index++) { + filePath += fileUri[index].fsPath.concat(","); + } + var result = { + msg: message.msg, + path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath + } + panel.webview.postMessage(result); + return fileUri[0].fsPath + } + }); +} + +// this method is called when your extension is deactivated +function deactivate() { } + +function getWebviewContent(context) { + let data = readFile(__dirname + '/vs_plugin_view.html'); + data = getWebViewContent(context, '/vs_plugin_view.html'); + return data.toString(); +} + +function getWebViewContent(context, templatePath) { + const resourcePath = path.join(context.extensionPath, templatePath); + const dirPath = path.dirname(resourcePath); + let html = fs.readFileSync(resourcePath, 'utf-8'); + html = html.replace(/( { + if ($2.indexOf("https://") < 0) return $1 + vscode.Uri.file(path.resolve(dirPath, $2)) + .with({ scheme: 'vscode-resource' }).toString() + '"'; + else return $1 + $2 + '"'; + }); + return html; +} + +module.exports = { + activate, + deactivate +} \ No newline at end of file diff --git a/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginLog.js b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginLog.js new file mode 100644 index 00000000..6ce4e7e3 --- /dev/null +++ b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginLog.js @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const fs = require('fs'); + +class VsPluginLog { + constructor() { + } +} +VsPluginLog.LEV_NONE = 0; +VsPluginLog.LEV_ERROR = 1; +VsPluginLog.LEV_DEBUG = 2; +VsPluginLog.LEV_INFO = 3; + +const LEV_STR = ["[NON]", "[ERR]", "[DBG]", "[INF]"] +var logLevel = VsPluginLog.LEV_ERROR; +var logFileName = null; +var logResultMessage = [true, ""] + +function getDateString() { + let nowDate = new Date(); + return nowDate.toLocaleString(); +} + +function saveLog(dateStr, levStr, detail) { + if (logFileName) { + let logStr = dateStr + " " + levStr + " " + detail + "\n"; + fs.appendFileSync(logFileName, logStr); + } +} + +VsPluginLog.init = function (level, fileName) { + logLevel = level in [VsPluginLog.LEV_NONE, VsPluginLog.LEV_ERROR, VsPluginLog.LEV_DEBUG, VsPluginLog.LEV_INFO] + ? level : VsPluginLog.LEV_ERROR; + logFileName = fileName ? fileName : "napi_generator.log"; +} + +function recordLog(lev, ...args) { + let dataStr = getDateString(); + let detail = args.join(" "); + saveLog(dataStr, LEV_STR[lev], detail); + if (lev == VsPluginLog.LEV_ERROR) { + logResultMessage = [false, detail]; + } + if (logLevel < lev) return; + VsPluginLog.logInfo(dataStr + LEV_STR[lev] + detail); +} + +VsPluginLog.logError = function (...args) { + recordLog(VsPluginLog.LEV_ERROR, args); +} + +VsPluginLog.logDebug = function (...args) { + recordLog(VsPluginLog.LEV_DEBUG, args); +} + +VsPluginLog.logInfo = function (...args) { + recordLog(VsPluginLog.LEV_INFO, args); +} + +VsPluginLog.getResult = function () { + return logResultMessage; +} + +module.exports = { + VsPluginLog +} \ No newline at end of file diff --git a/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginRe.js b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginRe.js new file mode 100644 index 00000000..909d7d54 --- /dev/null +++ b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginRe.js @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const path = require('path'); + +function search(ss, data) { + ss = replaceAll(ss, "\\.", "\\.") + let reg = new RegExp(ss); + let tt = reg.exec(data); + if (tt == null) return null; + let ret = { "regs": [] } + for (let i = 0; i < tt.length; i++) { + let p = data.indexOf(tt[i]); + if (tt[i] == null) { + ret["regs"].push([-1, -1]) + } + else { + ret["regs"].push([p, p + tt[i].length]) + } + } + + return ret; +} + +function match(ss, data) { + let tt = search(ss, data) + if (tt != null && tt.regs[0][0] == 0) return tt; + return null; +} + +function getFileInPath(tpath) { + return path.parse(tpath).base; +} + +function getPathInPath(tpath) { + return path.parse(tpath).dir; +} + +function all(sfrom) { + return new RegExp(sfrom, "g"); +} + +function replaceAll(ss, sfrom, sto) { + return ss.replace(all(sfrom), sto) +} + +module.exports = { + search, + match, + getFileInPath, + getPathInPath, + replaceAll, + all +} \ No newline at end of file diff --git a/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginTool.js b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginTool.js new file mode 100644 index 00000000..c00a6a71 --- /dev/null +++ b/hdc/api_scan_vs_plugin/src/gen/tools/VsPluginTool.js @@ -0,0 +1,112 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const os = require('os'); +const tsc = require("../../node_modules/typescript"); +const fs = require('fs'); +let vscode = null; +try { + vscode = require('vscode'); +} +catch (err) { + vscode = null; +} + +function replaceAll(s, sfrom, sto) { + while (s.indexOf(sfrom) >= 0) { + s = s.replace(sfrom, sto) + } + return s; +} + +function detectPlatform() { + if (os.type() == 'Windows_NT') { + return 'win'; + } else if (os.type() == 'Darwin') { + return 'mac'; + } else if (os.type() == 'Linux') { + return 'Linux'; + } +} + +function checkFileError(ifname) { + let program = tsc.createProgram([ifname], {}) + let emitResult = program.emit(); + let allDiagnostics = tsc.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + let errorMsg = '' + allDiagnostics.forEach(diagnostic => { + if (diagnostic.file) { + let { line, character } = tsc.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + let message = tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); + errorMsg += `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}\n`; + } else { + errorMsg += tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n") + "\n"; + } + }); + + if (allDiagnostics.length > 0) { + return [false, errorMsg]; + } + return [true, ""]; +} + +function utf8ArrayToStr(array) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) { + c = array[i++]; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + + return out; + } + + function readFile(fn) { + if (!fs.existsSync(fn)) { + return ""; + } + let data = fs.readFileSync(fn); + data = utf8ArrayToStr(data); + return data; + } + +module.exports = { + replaceAll, + detectPlatform, + checkFileError, + readFile +} \ No newline at end of file diff --git a/hdc/api_scan_vs_plugin/src/images/file.png b/hdc/api_scan_vs_plugin/src/images/file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c365a02e99414acb29c643fc2d64d150cff9f0 GIT binary patch literal 311 zcmV-70m%M|P)Px#@kvBMR9Hvtmr)ABFc3uFqQ?;Y67(=Ccni_v=tTt2q9BNR4_!$~rCQr&n}Q(8 zZ+CXyPSVf{KVI@K>M5`WhHXGv0eIsXuxe|Z!&U+qrn&n2U?(E?P@SsQZ$Ut#n}7dJ#+{yl0LaRc z#sos{fdr5eNC~6_QUd>-K+JR&Z5Q7I7Qa$$2_ULlggE^hJ^@2>!y!FdR_nk literal 0 HcmV?d00001 diff --git a/hdc/api_scan_vs_plugin/src/images/path.png b/hdc/api_scan_vs_plugin/src/images/path.png new file mode 100644 index 0000000000000000000000000000000000000000..56f408a584f243956fab1916d9152f34364cdf78 GIT binary patch literal 608 zcmV-m0-ybfP)Px%8c9S!R9HvtmphD2Q51&1Kk=%(;t>^%3bkjn6iB8Kl|)BWBGI5iBN-~9lc<J56Lj|zC5_nvcf|A>muCcug*q%%nX8gAa^Mh@#08XbS zv=vxdD%`Se{xZxA6V-4B*s?&;su4vA-<-D*WdOHaWa!wR@* zzW69QWT>C!h~yUoMG%R;q2Jg>xW5J uhP!}h&974#&WiUAP?E}CBd`ci5`o_-qRb&!3c5Z30000 + + + + + + Napi + + + + + +
+
+ + +
+
+ 扫描项目路径: + + +
+ +
+ 结果输出路径: + + +
+ +
+ + + + + +
+
+
+
+ + + \ No newline at end of file -- Gitee From 4a1ce9659ccb8f2e72c0af9ace42796fa2679d1d Mon Sep 17 00:00:00 2001 From: zhaojunxia Date: Thu, 3 Nov 2022 16:28:33 +0800 Subject: [PATCH 2/3] add gn_vs_plugin Signed-off-by: zhaojunxia --- hdc/gn_vs_plugin/docs/DEVELOP_ZH.md | 82 +++++ hdc/gn_vs_plugin/package.json | 29 ++ hdc/gn_vs_plugin/src/extension.js | 237 +++++++++++++++ hdc/gn_vs_plugin/src/gen/tools/VsPluginLog.js | 78 +++++ hdc/gn_vs_plugin/src/gen/tools/VsPluginRe.js | 65 ++++ .../src/gen/tools/VsPluginTool.js | 112 +++++++ hdc/gn_vs_plugin/src/images/file.png | Bin 0 -> 311 bytes hdc/gn_vs_plugin/src/images/path.png | Bin 0 -> 608 bytes hdc/gn_vs_plugin/src/jsconfig.json | 13 + hdc/gn_vs_plugin/src/package.json | 65 ++++ hdc/gn_vs_plugin/src/vs_plugin_view.html | 287 ++++++++++++++++++ 11 files changed, 968 insertions(+) create mode 100644 hdc/gn_vs_plugin/docs/DEVELOP_ZH.md create mode 100644 hdc/gn_vs_plugin/package.json create mode 100644 hdc/gn_vs_plugin/src/extension.js create mode 100644 hdc/gn_vs_plugin/src/gen/tools/VsPluginLog.js create mode 100644 hdc/gn_vs_plugin/src/gen/tools/VsPluginRe.js create mode 100644 hdc/gn_vs_plugin/src/gen/tools/VsPluginTool.js create mode 100644 hdc/gn_vs_plugin/src/images/file.png create mode 100644 hdc/gn_vs_plugin/src/images/path.png create mode 100644 hdc/gn_vs_plugin/src/jsconfig.json create mode 100644 hdc/gn_vs_plugin/src/package.json create mode 100644 hdc/gn_vs_plugin/src/vs_plugin_view.html diff --git a/hdc/gn_vs_plugin/docs/DEVELOP_ZH.md b/hdc/gn_vs_plugin/docs/DEVELOP_ZH.md new file mode 100644 index 00000000..07853694 --- /dev/null +++ b/hdc/gn_vs_plugin/docs/DEVELOP_ZH.md @@ -0,0 +1,82 @@ +# NAPI框架生成工具VSCode插件开发说明 + +若当前工具功能不满足开发者需求,开发者需增强工具能力,则可基于已有源码进行工具二次开发,编译打包生成自定义的VS Code插件。 + +## VS Code插件打包说明 + +### Linux + +1.在napi_generator目录下,将gn-gen-linux下可执行文件复制到napi_generator/hdc/gn_vs_plugin/src/目录下,执行命令如下: + + cp gn-gen-linux hdc/gn_vs_plugin/src/ + +2.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i + +3.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件gnapi-0.0.1.vsix。结果如下: + + kaihong1@ubuntu:~/napi_generator_gjj/hdc/gn_vs_plugin/src$ npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3290 files, out of which 1547 are JavaScript files. For performance reasons, you should bundle your extension: https://aka.ms/vscode-bundle-extension . You should also exclude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: /home/kaihong1/napi_generator_gjj/hdc/gn_vs_plugin/src/gn-0.0.1.vsix (3290 files, 38.93MB) + +### Windows + +1.将napi_generator目录下的gn-gen-win.exe可执行文件复制到napi_generator/hdc/gn_vs_plugin/src/目录下。 + +2.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i + +3.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/gn_vs_plugin/src目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件gn-0.0.1.vsix。结果如下: + + C:\napi_generator_GJJ\hdc\gn_vs_plugin\src>npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3290 files, out of which 1547 are JavaScript files. For performance reasons, you should bundle your extension: https://aka.ms/vscode-bundle-extension . You should also exclude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: C:\napi_generator_GJJ\hdc\gn_vs_plugin\src\gn-0.0.1.vsix (3290 files, 36.01MB) + +## 工具测试 + + 进行工具二次开发后,本地可进行单元测试、story特性测试确保工具的可用性。左键单击以下链接了解详情: + + [单元测试]暂无 + + [story测试]暂无 + diff --git a/hdc/gn_vs_plugin/package.json b/hdc/gn_vs_plugin/package.json new file mode 100644 index 00000000..240c914a --- /dev/null +++ b/hdc/gn_vs_plugin/package.json @@ -0,0 +1,29 @@ +{ + "name": "gn_vs_plugin", + "version": "1.0.0", + "description": "This tool can convert other compiled scripts (such as cmake, make, etc.) into gn scripts in the OpenHarmony project, or reverse the conversion.", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "dependencies": { + "mocha": "^9.2.1", + "node-gyp": "^8.4.1", + "stdio": "^2.1.1", + "typescript": "^4.5.5" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@gitee.com:joeysun001/napi_generator.git" + }, + "author": "", + "license": "ISC", + "pkg": { + "assets": [ + "src/node_modules/typescript/**/*" + ] + } +} diff --git a/hdc/gn_vs_plugin/src/extension.js b/hdc/gn_vs_plugin/src/extension.js new file mode 100644 index 00000000..f3a670f5 --- /dev/null +++ b/hdc/gn_vs_plugin/src/extension.js @@ -0,0 +1,237 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = require('vscode'); +const fs = require('fs'); +const re = require("./gen/tools/VsPluginRe"); +const { VsPluginLog } = require("./gen/tools/VsPluginLog"); +const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool'); +const path = require('path'); +const os = require('os'); +var exeFilePath = null; +var flag = ""; +var isTrue = false; +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed + +/** + * @param {vscode.ExtensionContext} context + */ +function activate(context) { + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "gnapi" is now active!'); + let disposable = register(context, 'generate_gn'); + let disposableMenu = register(context, 'generate_gn_menu'); + context.subscriptions.push(disposable); + context.subscriptions.push(disposableMenu); + var platform = detectPlatform(); + if (platform == 'win') { + exeFilePath = __dirname + "/gn-gen-win.exe"; + } else if (platform == 'mac') { + exeFilePath = __dirname + "/gn-gen-macos"; + } else if (platform == 'Linux') { + exeFilePath = __dirname + "/gn-gen-linux"; + } +} + +function gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { + var exec = require('child_process').exec; + exec(genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions), function (error, stdout, stderr) { + VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); + if (error || stdout.indexOf("generate gn ok") < 0) { + vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); + return VsPluginLog.logError("VsPlugin:" + error + stdout); + } + vscode.window.showInformationMessage("Generated successfully"); + }); +} + +function genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { + var command = exeFilePath + " -o " + outputCodeDir + " -p " + originCodeDir + " -f " + inputScriptDir + " -t " + scriptType + + " -s " + subsystemName + " -m " + componentName + " -d " + transplantDir; + if (compileOptions != "") { + command += " -a " + "\"" + compileOptions + "\""; + } + var platform = detectPlatform(); + if (platform == 'win') { + command = re.replaceAll(command, '\\\\', '/'); + } + return command; +} + +function exeFileExit() { + if (fs.existsSync(exeFilePath)) { + return true; + } + return false; +} + +function register(context, command) { + let disposable = vscode.commands.registerCommand(command, function (uri) { + // The code you place here will be executed every time your command is executed + // Display a message box to the user + const panel = vscode.window.createWebviewPanel( + 'generate', // Identifies the type of WebView + 'Gn Generate Frame', // Title of the panel displayed to the user + vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor + { + enableScripts: true, // Enable or disable JS, default is Enable + retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset + } + ); + panel.webview.html = getWebviewContent(context); + let msg; + panel.webview.onDidReceiveMessage(message => { + msg = message.msg; + if (msg == "cancel") { + panel.dispose(); + } else if(msg == "gn") { + let outputCodeDir = message.outputCodeDir; + let originCodeDir = message.originCodeDir; + let inputScriptDir = message.inputScriptDir; + let scriptType = message.scriptType; + let transplantDir = message.transplantDir; + let subsystemName = message.subsystemName; + let componentName = message.componentName; + let compileOptions = message.compileOptions; + checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions); + } else { + selectPath(panel, message); + } + }, undefined, context.subscriptions); + let fn = re.getFileInPath(uri.fsPath); + let tt = re.match("([a-zA-Z_0-9]+.[a-zA-Z_0-9])", fn); + var result = { + msg: "selectinputScriptDir", + path: tt ? uri.fsPath : "" + } + panel.webview.postMessage(result); + }); + return disposable; +} + +/** +* 选择本地目录/文件夹 +*/ + function selectPath(panel, message) { + let mode = 1; + if (message.mode != undefined) { + mode = message.mode; + } + flag = flag == "" ? '' : flag; + const options = { + canSelectMany: false,//是否可以选择多个 + canSelectFiles: mode == 0 ? true : false,//是否选择文件 + canSelectFolders: mode == 0 ? false : true,//是否选择文件夹 + defaultUri:vscode.Uri.file(flag),//默认打开本地路径 + filters: { + 'All files': ['*'] + } + }; + + return vscode.window.showOpenDialog(options).then(fileUri => { + if (fileUri && fileUri[0]) { + console.log('Selected file: ' + fileUri[0].fsPath); + var filePath = ""; + filePath = fileUri[0].fsPath.concat(','); + filePath = re.replaceAll(filePath, '/', '\\'); + var result = { + msg: message.msg, + path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath + } + console.log('message.msg: ' + message.msg); + if (!isTrue && message.msg == "selectoutputCodeDir"){ + flag = filePath.substring(0, filePath.length - 1); + let fileTempName = "out"; + let pos = flag.indexOf(fileTempName); + flag = flag.substr(0,pos-1); + isTrue = true; + } + panel.webview.postMessage(result); + return fileUri[0].fsPath + } + }); +} + +function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { + outputCodeDir = re.replaceAll(outputCodeDir, " ", ""); + if ("" == outputCodeDir) { + vscode.window.showErrorMessage("Please enter the outputCodeDir path!"); + return; + } + originCodeDir = re.replaceAll(originCodeDir, " ", ""); + if ("" == originCodeDir) { + vscode.window.showErrorMessage("Please enter the originCodeDir path!"); + return; + } + inputScriptDir = re.replaceAll(inputScriptDir, " ", ""); + if ("" == inputScriptDir) { + vscode.window.showErrorMessage("Please enter the inputScriptDir path!"); + return; + } + if (inputScriptDir.indexOf(".") < 0) { + vscode.window.showErrorMessage("Please enter the correct file path!"); + return; + } + transplantDir = re.replaceAll(transplantDir, " ", ""); + if ("" == transplantDir) { + vscode.window.showErrorMessage("Please enter the transplantDir path!"); + return; + } + subsystemName = re.replaceAll(subsystemName, " ", ""); + if ("" == subsystemName) { + vscode.window.showErrorMessage("Please enter the subsystemName!"); + return; + } + componentName = re.replaceAll(componentName, " ", ""); + if ("" == componentName) { + vscode.window.showErrorMessage("Please enter the componentName!"); + return; + } + if (exeFileExit()) { + gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions); + } else { + vscode.window.showInformationMessage("Copy executable program to " + __dirname); + } +} + +// this method is called when your extension is deactivated +function deactivate() { } + +function getWebviewContent(context) { + let data = readFile(__dirname + '/vs_plugin_view.html'); + data = getWebViewContent(context, '/vs_plugin_view.html'); + return data.toString(); +} + +function getWebViewContent(context, templatePath) { + const reoriginCodeDir = path.join(context.extensionPath, templatePath); + const dirPath = path.dirname(reoriginCodeDir); + let html = fs.readFileSync(reoriginCodeDir, 'utf-8'); + html = html.replace(/( { + if($2.indexOf("https://")<0)return $1 + vscode.Uri.file(path.resolve(dirPath, $2)) + .with({ scheme: 'vscode-resource' }).toString() + '"'; + else return $1 + $2+'"'; + }); + return html; +} + +module.exports = { + activate, + deactivate +} \ No newline at end of file diff --git a/hdc/gn_vs_plugin/src/gen/tools/VsPluginLog.js b/hdc/gn_vs_plugin/src/gen/tools/VsPluginLog.js new file mode 100644 index 00000000..6ce4e7e3 --- /dev/null +++ b/hdc/gn_vs_plugin/src/gen/tools/VsPluginLog.js @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const fs = require('fs'); + +class VsPluginLog { + constructor() { + } +} +VsPluginLog.LEV_NONE = 0; +VsPluginLog.LEV_ERROR = 1; +VsPluginLog.LEV_DEBUG = 2; +VsPluginLog.LEV_INFO = 3; + +const LEV_STR = ["[NON]", "[ERR]", "[DBG]", "[INF]"] +var logLevel = VsPluginLog.LEV_ERROR; +var logFileName = null; +var logResultMessage = [true, ""] + +function getDateString() { + let nowDate = new Date(); + return nowDate.toLocaleString(); +} + +function saveLog(dateStr, levStr, detail) { + if (logFileName) { + let logStr = dateStr + " " + levStr + " " + detail + "\n"; + fs.appendFileSync(logFileName, logStr); + } +} + +VsPluginLog.init = function (level, fileName) { + logLevel = level in [VsPluginLog.LEV_NONE, VsPluginLog.LEV_ERROR, VsPluginLog.LEV_DEBUG, VsPluginLog.LEV_INFO] + ? level : VsPluginLog.LEV_ERROR; + logFileName = fileName ? fileName : "napi_generator.log"; +} + +function recordLog(lev, ...args) { + let dataStr = getDateString(); + let detail = args.join(" "); + saveLog(dataStr, LEV_STR[lev], detail); + if (lev == VsPluginLog.LEV_ERROR) { + logResultMessage = [false, detail]; + } + if (logLevel < lev) return; + VsPluginLog.logInfo(dataStr + LEV_STR[lev] + detail); +} + +VsPluginLog.logError = function (...args) { + recordLog(VsPluginLog.LEV_ERROR, args); +} + +VsPluginLog.logDebug = function (...args) { + recordLog(VsPluginLog.LEV_DEBUG, args); +} + +VsPluginLog.logInfo = function (...args) { + recordLog(VsPluginLog.LEV_INFO, args); +} + +VsPluginLog.getResult = function () { + return logResultMessage; +} + +module.exports = { + VsPluginLog +} \ No newline at end of file diff --git a/hdc/gn_vs_plugin/src/gen/tools/VsPluginRe.js b/hdc/gn_vs_plugin/src/gen/tools/VsPluginRe.js new file mode 100644 index 00000000..909d7d54 --- /dev/null +++ b/hdc/gn_vs_plugin/src/gen/tools/VsPluginRe.js @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const path = require('path'); + +function search(ss, data) { + ss = replaceAll(ss, "\\.", "\\.") + let reg = new RegExp(ss); + let tt = reg.exec(data); + if (tt == null) return null; + let ret = { "regs": [] } + for (let i = 0; i < tt.length; i++) { + let p = data.indexOf(tt[i]); + if (tt[i] == null) { + ret["regs"].push([-1, -1]) + } + else { + ret["regs"].push([p, p + tt[i].length]) + } + } + + return ret; +} + +function match(ss, data) { + let tt = search(ss, data) + if (tt != null && tt.regs[0][0] == 0) return tt; + return null; +} + +function getFileInPath(tpath) { + return path.parse(tpath).base; +} + +function getPathInPath(tpath) { + return path.parse(tpath).dir; +} + +function all(sfrom) { + return new RegExp(sfrom, "g"); +} + +function replaceAll(ss, sfrom, sto) { + return ss.replace(all(sfrom), sto) +} + +module.exports = { + search, + match, + getFileInPath, + getPathInPath, + replaceAll, + all +} \ No newline at end of file diff --git a/hdc/gn_vs_plugin/src/gen/tools/VsPluginTool.js b/hdc/gn_vs_plugin/src/gen/tools/VsPluginTool.js new file mode 100644 index 00000000..c00a6a71 --- /dev/null +++ b/hdc/gn_vs_plugin/src/gen/tools/VsPluginTool.js @@ -0,0 +1,112 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const os = require('os'); +const tsc = require("../../node_modules/typescript"); +const fs = require('fs'); +let vscode = null; +try { + vscode = require('vscode'); +} +catch (err) { + vscode = null; +} + +function replaceAll(s, sfrom, sto) { + while (s.indexOf(sfrom) >= 0) { + s = s.replace(sfrom, sto) + } + return s; +} + +function detectPlatform() { + if (os.type() == 'Windows_NT') { + return 'win'; + } else if (os.type() == 'Darwin') { + return 'mac'; + } else if (os.type() == 'Linux') { + return 'Linux'; + } +} + +function checkFileError(ifname) { + let program = tsc.createProgram([ifname], {}) + let emitResult = program.emit(); + let allDiagnostics = tsc.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + let errorMsg = '' + allDiagnostics.forEach(diagnostic => { + if (diagnostic.file) { + let { line, character } = tsc.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + let message = tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); + errorMsg += `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}\n`; + } else { + errorMsg += tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n") + "\n"; + } + }); + + if (allDiagnostics.length > 0) { + return [false, errorMsg]; + } + return [true, ""]; +} + +function utf8ArrayToStr(array) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) { + c = array[i++]; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + + return out; + } + + function readFile(fn) { + if (!fs.existsSync(fn)) { + return ""; + } + let data = fs.readFileSync(fn); + data = utf8ArrayToStr(data); + return data; + } + +module.exports = { + replaceAll, + detectPlatform, + checkFileError, + readFile +} \ No newline at end of file diff --git a/hdc/gn_vs_plugin/src/images/file.png b/hdc/gn_vs_plugin/src/images/file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c365a02e99414acb29c643fc2d64d150cff9f0 GIT binary patch literal 311 zcmV-70m%M|P)Px#@kvBMR9Hvtmr)ABFc3uFqQ?;Y67(=Ccni_v=tTt2q9BNR4_!$~rCQr&n}Q(8 zZ+CXyPSVf{KVI@K>M5`WhHXGv0eIsXuxe|Z!&U+qrn&n2U?(E?P@SsQZ$Ut#n}7dJ#+{yl0LaRc z#sos{fdr5eNC~6_QUd>-K+JR&Z5Q7I7Qa$$2_ULlggE^hJ^@2>!y!FdR_nk literal 0 HcmV?d00001 diff --git a/hdc/gn_vs_plugin/src/images/path.png b/hdc/gn_vs_plugin/src/images/path.png new file mode 100644 index 0000000000000000000000000000000000000000..56f408a584f243956fab1916d9152f34364cdf78 GIT binary patch literal 608 zcmV-m0-ybfP)Px%8c9S!R9HvtmphD2Q51&1Kk=%(;t>^%3bkjn6iB8Kl|)BWBGI5iBN-~9lc<J56Lj|zC5_nvcf|A>muCcug*q%%nX8gAa^Mh@#08XbS zv=vxdD%`Se{xZxA6V-4B*s?&;su4vA-<-D*WdOHaWa!wR@* zzW69QWT>C!h~yUoMG%R;q2Jg>xW5J uhP!}h&974#&WiUAP?E}CBd`ci5`o_-qRb&!3c5Z30000 + + + + + Napi + + + + +
+
+ + +
+
+ 工程输出路径*: + + +
+
+ 工程源码路径*: + + +
+
+ 输入脚本路径*: + + +
+
+ 输入脚本类型*: + +
+
+ GN生成路径*:   + + +
+
+ 子系统名称*:   + +
+
+ 组件名称*:     + +
+
+ 编译选项:      + +
+
+ + + + + +
+
+
+
+ + \ No newline at end of file -- Gitee From f9d0600de5f43b1769ebdd432832b4d8f3bd6bab Mon Sep 17 00:00:00 2001 From: zhaojunxia Date: Thu, 3 Nov 2022 16:29:29 +0800 Subject: [PATCH 3/3] add service_vs_plugin Signed-off-by: zhaojunxia --- hdc/gn_vs_plugin/src/extension.js | 22 +- hdc/service_vs_plugin/docs/DEVELOP_ZH.md | 82 +++++++ hdc/service_vs_plugin/package.json | 29 +++ hdc/service_vs_plugin/src/extension.js | 175 +++++++++++++ .../src/gen/tools/VsPluginLog.js | 78 ++++++ .../src/gen/tools/VsPluginRe.js | 65 +++++ .../src/gen/tools/VsPluginTool.js | 112 +++++++++ hdc/service_vs_plugin/src/images/file.png | Bin 0 -> 311 bytes hdc/service_vs_plugin/src/images/path.png | Bin 0 -> 608 bytes hdc/service_vs_plugin/src/jsconfig.json | 13 + hdc/service_vs_plugin/src/package.json | 65 +++++ hdc/service_vs_plugin/src/vs_plugin_view.html | 231 ++++++++++++++++++ 12 files changed, 864 insertions(+), 8 deletions(-) create mode 100644 hdc/service_vs_plugin/docs/DEVELOP_ZH.md create mode 100644 hdc/service_vs_plugin/package.json create mode 100644 hdc/service_vs_plugin/src/extension.js create mode 100644 hdc/service_vs_plugin/src/gen/tools/VsPluginLog.js create mode 100644 hdc/service_vs_plugin/src/gen/tools/VsPluginRe.js create mode 100644 hdc/service_vs_plugin/src/gen/tools/VsPluginTool.js create mode 100644 hdc/service_vs_plugin/src/images/file.png create mode 100644 hdc/service_vs_plugin/src/images/path.png create mode 100644 hdc/service_vs_plugin/src/jsconfig.json create mode 100644 hdc/service_vs_plugin/src/package.json create mode 100644 hdc/service_vs_plugin/src/vs_plugin_view.html diff --git a/hdc/gn_vs_plugin/src/extension.js b/hdc/gn_vs_plugin/src/extension.js index f3a670f5..5633efb1 100644 --- a/hdc/gn_vs_plugin/src/extension.js +++ b/hdc/gn_vs_plugin/src/extension.js @@ -49,9 +49,11 @@ function activate(context) { } } -function gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { +function gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, + subsystemName, componentName, compileOptions) { var exec = require('child_process').exec; - exec(genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions), function (error, stdout, stderr) { + exec(genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, + subsystemName, componentName, compileOptions), function (error, stdout, stderr) { VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); if (error || stdout.indexOf("generate gn ok") < 0) { vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); @@ -61,9 +63,10 @@ function gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, tr }); } -function genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { - var command = exeFilePath + " -o " + outputCodeDir + " -p " + originCodeDir + " -f " + inputScriptDir + " -t " + scriptType - + " -s " + subsystemName + " -m " + componentName + " -d " + transplantDir; +function genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, + transplantDir, subsystemName, componentName, compileOptions) { + var command = exeFilePath + " -o " + outputCodeDir + " -p " + originCodeDir + " -f " + inputScriptDir + + " -t " + scriptType + " -s " + subsystemName + " -m " + componentName + " -d " + transplantDir; if (compileOptions != "") { command += " -a " + "\"" + compileOptions + "\""; } @@ -109,7 +112,8 @@ function register(context, command) { let subsystemName = message.subsystemName; let componentName = message.componentName; let compileOptions = message.compileOptions; - checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions); + checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, + transplantDir, subsystemName, componentName, compileOptions); } else { selectPath(panel, message); } @@ -168,7 +172,8 @@ function register(context, command) { }); } -function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions) { +function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, + transplantDir, subsystemName, componentName, compileOptions) { outputCodeDir = re.replaceAll(outputCodeDir, " ", ""); if ("" == outputCodeDir) { vscode.window.showErrorMessage("Please enter the outputCodeDir path!"); @@ -204,7 +209,8 @@ function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType, tra return; } if (exeFileExit()) { - gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir, subsystemName, componentName, compileOptions); + gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, + transplantDir, subsystemName, componentName, compileOptions); } else { vscode.window.showInformationMessage("Copy executable program to " + __dirname); } diff --git a/hdc/service_vs_plugin/docs/DEVELOP_ZH.md b/hdc/service_vs_plugin/docs/DEVELOP_ZH.md new file mode 100644 index 00000000..87f1c6aa --- /dev/null +++ b/hdc/service_vs_plugin/docs/DEVELOP_ZH.md @@ -0,0 +1,82 @@ +# NAPI框架生成工具VSCode插件开发说明 + +若当前工具功能不满足开发者需求,开发者需增强工具能力,则可基于已有源码进行工具二次开发,编译打包生成自定义的VS Code插件。 + +## VS Code插件打包说明 + +### Linux + +1.在napi_generator目录下,将service-gen-linux下可执行文件复制到napi_generator/hdc/service_vs_plugin/src/目录下,执行命令如下: + + cp service-gen-linux hdc/service_vs_plugin/src/ + +2.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i + +3.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件gnapi-0.0.1.vsix。结果如下: + + kaihong1@ubuntu:~/napi_generator_gjj/hdc/service_vs_plugin/src$ npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3282 files, out of which 1547 are JavaScript files. For performance reasons, you should bundle your extension: https://aka.ms/vscode-bundle-extension . You should also exclude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: /home/kaihong1/napi_generator_gjj/hdc/service_vs_plugin/src/service-0.0.1.vsix (3282 files, 60.4MB) + +### Windows + +1.将napi_generator目录下的service-gen-win.exe可执行文件复制到napi_generator/hdc/service_vs_plugin/src/目录下。 + +2.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i + +3.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i typescript + +4.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npm i vsce + +5.在napi_generator/hdc/service_vs_plugin/src目录下执行命令: + + npx vsce package + + 每个选项都选择y,然后回车,最终会在当前目录下打包生成一个插件service-0.0.1.vsix。结果如下: + + C:\napi_generator_GJJ\hdc\service_vs_plugin\src>npx vsce package + WARNING A 'repository' field is missing from the 'package.json' manifest file. + Do you want to continue? [y/N] y + WARNING Using '*' activation is usually a bad idea as it impacts performance. + More info: https://code.visualstudio.com/api/references/activation-events#Start-up + Do you want to continue? [y/N] y + WARNING LICENSE.md, LICENSE.txt or LICENSE not found + Do you want to continue? [y/N] y + This extension consists of 3281 files, out of which 1547 are JavaScript files. For performance reasons, you should bundle your extension: https://aka.ms/vscode-bundle-extension . You should also exclude unnecessary files by adding them to your .vscodeignore: https://aka.ms/vscode-vscodeignore + DONE Packaged: C:\napi_generator_GJJ\hdc\service_vs_plugin\src\service-0.0.1.vsix (3281 files, 39.92MB) + +## 工具测试 + + 进行工具二次开发后,本地可进行单元测试、story特性测试确保工具的可用性。左键单击以下链接了解详情: + + [单元测试]暂无 + + [story测试]暂无 + diff --git a/hdc/service_vs_plugin/package.json b/hdc/service_vs_plugin/package.json new file mode 100644 index 00000000..aa26870b --- /dev/null +++ b/hdc/service_vs_plugin/package.json @@ -0,0 +1,29 @@ +{ + "name": "service_vs_plugin", + "version": "1.0.0", + "description": "this tool ", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "dependencies": { + "mocha": "^9.2.1", + "node-gyp": "^8.4.1", + "stdio": "^2.1.1", + "typescript": "^4.5.5" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@gitee.com:joeysun001/napi_generator.git" + }, + "author": "", + "license": "ISC", + "pkg": { + "assets": [ + "src/node_modules/typescript/**/*" + ] + } +} diff --git a/hdc/service_vs_plugin/src/extension.js b/hdc/service_vs_plugin/src/extension.js new file mode 100644 index 00000000..ebb90dcb --- /dev/null +++ b/hdc/service_vs_plugin/src/extension.js @@ -0,0 +1,175 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = require('vscode'); +const fs = require('fs'); +const re = require("./gen/tools/VsPluginRe"); +const { VsPluginLog } = require("./gen/tools/VsPluginLog"); +const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool'); +const path = require('path'); +var exeFilePath = null; +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed + +/** + * @param {vscode.ExtensionContext} context + */ +function activate(context) { + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "gnapi" is now active!'); + let disposable = register(context, 'generate_service'); + let disposableMenu = register(context, 'generate_service_menu'); + context.subscriptions.push(disposable); + context.subscriptions.push(disposableMenu); + var platform = detectPlatform(); + if (platform == 'win') { + exeFilePath = __dirname + "/service-gen-win.exe"; + } else if (platform == 'mac') { + exeFilePath = __dirname + "/service-gen-macos"; + } else if (platform == 'Linux') { + exeFilePath = __dirname + "/service-gen-linux"; + } +} + +function executorService(name, genDir, serviceId) { + var command = exeFilePath + " -f " + name + " -o " + genDir + " -s " + serviceId; + var exec = require('child_process').exec; + exec(command, function (error, stdout, stderr) { + VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); + if (error || stdout.indexOf("success") < 0) { + vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); + return VsPluginLog.logError("VsPlugin:" + error + stdout); + } + vscode.window.showInformationMessage("Generated successfully"); + }); +} + +function exeFileExit() { + if (fs.existsSync(exeFilePath)) { + return true; + } + return false; +} + +function register(context, command) { + let disposable = vscode.commands.registerCommand(command, function (uri) { + // The code you place here will be executed every time your command is executed + // Display a message box to the user + const panel = vscode.window.createWebviewPanel( + 'generate', // Identifies the type of WebView + 'Generate Service Frame', // Title of the panel displayed to the user + vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor + { + enableScripts: true, // Enable or disable JS, default is Enable + retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset + } + ); + panel.webview.html = getWebviewContent(context); + let msg; + panel.webview.onDidReceiveMessage(message => { + msg = message.msg; + if (msg == "cancel") { + panel.dispose(); + } else if(msg == "param") { + let name = message.fileNames; + let genDir = message.genDir; + let serviceId = message.serviceId; + name = re.replaceAll(name, " ", ""); + if ("" == name) { + vscode.window.showErrorMessage("Please enter the path!"); + return; + } + if (exeFileExit()) { + executorService(name, genDir, serviceId); + } else { + vscode.window.showInformationMessage("Copy executable program to " + __dirname); + } + }else { + selectPath(panel, message); + } + }, undefined, context.subscriptions); + let fn = re.getFileInPath(uri.fsPath); + let tt = re.match("([a-zA-Z_0-9]+.h)", fn); + var result = { + msg: "selectHFilePath", + path: tt ? uri.fsPath : "" + } + panel.webview.postMessage(result); + }); + return disposable; +} + +/** +* 选择本地目录/文件夹 +*/ + function selectPath(panel, message) { + let mode = 1; + if (message.mode != undefined) { + mode = message.mode; + } + const options = { + canSelectFiles: mode == 0 ? true : false,//是否选择文件 + canSelectFolders: mode == 0 ? false : true,//是否选择文件夹 + defaultUri:vscode.Uri.file(''),//默认打开本地路径 + filters: { + 'All files': ['h'] + } + }; + + return vscode.window.showOpenDialog(options).then(fileUri => { + if (fileUri && fileUri[0]) { + console.log('Selected file: ' + fileUri[0].fsPath); + let filePath = ""; + for (let index = 0; index < fileUri.length; index++) { + filePath += fileUri[index].fsPath.concat(","); + } + var result = { + msg: message.msg, + path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath + } + panel.webview.postMessage(result); + return fileUri[0].fsPath + } + }); +} + +// this method is called when your extension is deactivated +function deactivate() { } + +function getWebviewContent(context) { + let data = readFile(__dirname + '/vs_plugin_view.html'); + data = getWebViewContent(context, '/vs_plugin_view.html'); + return data.toString(); +} + +function getWebViewContent(context, templatePath) { + const resourcePath = path.join(context.extensionPath, templatePath); + const dirPath = path.dirname(resourcePath); + let html = fs.readFileSync(resourcePath, 'utf-8'); + html = html.replace(/( { + if($2.indexOf("https://")<0)return $1 + vscode.Uri.file(path.resolve(dirPath, $2)) + .with({ scheme: 'vscode-resource' }).toString() + '"'; + else return $1 + $2+'"'; + }); + return html; +} + +module.exports = { + activate, + deactivate +} \ No newline at end of file diff --git a/hdc/service_vs_plugin/src/gen/tools/VsPluginLog.js b/hdc/service_vs_plugin/src/gen/tools/VsPluginLog.js new file mode 100644 index 00000000..6ce4e7e3 --- /dev/null +++ b/hdc/service_vs_plugin/src/gen/tools/VsPluginLog.js @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const fs = require('fs'); + +class VsPluginLog { + constructor() { + } +} +VsPluginLog.LEV_NONE = 0; +VsPluginLog.LEV_ERROR = 1; +VsPluginLog.LEV_DEBUG = 2; +VsPluginLog.LEV_INFO = 3; + +const LEV_STR = ["[NON]", "[ERR]", "[DBG]", "[INF]"] +var logLevel = VsPluginLog.LEV_ERROR; +var logFileName = null; +var logResultMessage = [true, ""] + +function getDateString() { + let nowDate = new Date(); + return nowDate.toLocaleString(); +} + +function saveLog(dateStr, levStr, detail) { + if (logFileName) { + let logStr = dateStr + " " + levStr + " " + detail + "\n"; + fs.appendFileSync(logFileName, logStr); + } +} + +VsPluginLog.init = function (level, fileName) { + logLevel = level in [VsPluginLog.LEV_NONE, VsPluginLog.LEV_ERROR, VsPluginLog.LEV_DEBUG, VsPluginLog.LEV_INFO] + ? level : VsPluginLog.LEV_ERROR; + logFileName = fileName ? fileName : "napi_generator.log"; +} + +function recordLog(lev, ...args) { + let dataStr = getDateString(); + let detail = args.join(" "); + saveLog(dataStr, LEV_STR[lev], detail); + if (lev == VsPluginLog.LEV_ERROR) { + logResultMessage = [false, detail]; + } + if (logLevel < lev) return; + VsPluginLog.logInfo(dataStr + LEV_STR[lev] + detail); +} + +VsPluginLog.logError = function (...args) { + recordLog(VsPluginLog.LEV_ERROR, args); +} + +VsPluginLog.logDebug = function (...args) { + recordLog(VsPluginLog.LEV_DEBUG, args); +} + +VsPluginLog.logInfo = function (...args) { + recordLog(VsPluginLog.LEV_INFO, args); +} + +VsPluginLog.getResult = function () { + return logResultMessage; +} + +module.exports = { + VsPluginLog +} \ No newline at end of file diff --git a/hdc/service_vs_plugin/src/gen/tools/VsPluginRe.js b/hdc/service_vs_plugin/src/gen/tools/VsPluginRe.js new file mode 100644 index 00000000..909d7d54 --- /dev/null +++ b/hdc/service_vs_plugin/src/gen/tools/VsPluginRe.js @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const path = require('path'); + +function search(ss, data) { + ss = replaceAll(ss, "\\.", "\\.") + let reg = new RegExp(ss); + let tt = reg.exec(data); + if (tt == null) return null; + let ret = { "regs": [] } + for (let i = 0; i < tt.length; i++) { + let p = data.indexOf(tt[i]); + if (tt[i] == null) { + ret["regs"].push([-1, -1]) + } + else { + ret["regs"].push([p, p + tt[i].length]) + } + } + + return ret; +} + +function match(ss, data) { + let tt = search(ss, data) + if (tt != null && tt.regs[0][0] == 0) return tt; + return null; +} + +function getFileInPath(tpath) { + return path.parse(tpath).base; +} + +function getPathInPath(tpath) { + return path.parse(tpath).dir; +} + +function all(sfrom) { + return new RegExp(sfrom, "g"); +} + +function replaceAll(ss, sfrom, sto) { + return ss.replace(all(sfrom), sto) +} + +module.exports = { + search, + match, + getFileInPath, + getPathInPath, + replaceAll, + all +} \ No newline at end of file diff --git a/hdc/service_vs_plugin/src/gen/tools/VsPluginTool.js b/hdc/service_vs_plugin/src/gen/tools/VsPluginTool.js new file mode 100644 index 00000000..c00a6a71 --- /dev/null +++ b/hdc/service_vs_plugin/src/gen/tools/VsPluginTool.js @@ -0,0 +1,112 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const os = require('os'); +const tsc = require("../../node_modules/typescript"); +const fs = require('fs'); +let vscode = null; +try { + vscode = require('vscode'); +} +catch (err) { + vscode = null; +} + +function replaceAll(s, sfrom, sto) { + while (s.indexOf(sfrom) >= 0) { + s = s.replace(sfrom, sto) + } + return s; +} + +function detectPlatform() { + if (os.type() == 'Windows_NT') { + return 'win'; + } else if (os.type() == 'Darwin') { + return 'mac'; + } else if (os.type() == 'Linux') { + return 'Linux'; + } +} + +function checkFileError(ifname) { + let program = tsc.createProgram([ifname], {}) + let emitResult = program.emit(); + let allDiagnostics = tsc.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + let errorMsg = '' + allDiagnostics.forEach(diagnostic => { + if (diagnostic.file) { + let { line, character } = tsc.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + let message = tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); + errorMsg += `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}\n`; + } else { + errorMsg += tsc.flattenDiagnosticMessageText(diagnostic.messageText, "\n") + "\n"; + } + }); + + if (allDiagnostics.length > 0) { + return [false, errorMsg]; + } + return [true, ""]; +} + +function utf8ArrayToStr(array) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) { + c = array[i++]; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + + return out; + } + + function readFile(fn) { + if (!fs.existsSync(fn)) { + return ""; + } + let data = fs.readFileSync(fn); + data = utf8ArrayToStr(data); + return data; + } + +module.exports = { + replaceAll, + detectPlatform, + checkFileError, + readFile +} \ No newline at end of file diff --git a/hdc/service_vs_plugin/src/images/file.png b/hdc/service_vs_plugin/src/images/file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c365a02e99414acb29c643fc2d64d150cff9f0 GIT binary patch literal 311 zcmV-70m%M|P)Px#@kvBMR9Hvtmr)ABFc3uFqQ?;Y67(=Ccni_v=tTt2q9BNR4_!$~rCQr&n}Q(8 zZ+CXyPSVf{KVI@K>M5`WhHXGv0eIsXuxe|Z!&U+qrn&n2U?(E?P@SsQZ$Ut#n}7dJ#+{yl0LaRc z#sos{fdr5eNC~6_QUd>-K+JR&Z5Q7I7Qa$$2_ULlggE^hJ^@2>!y!FdR_nk literal 0 HcmV?d00001 diff --git a/hdc/service_vs_plugin/src/images/path.png b/hdc/service_vs_plugin/src/images/path.png new file mode 100644 index 0000000000000000000000000000000000000000..56f408a584f243956fab1916d9152f34364cdf78 GIT binary patch literal 608 zcmV-m0-ybfP)Px%8c9S!R9HvtmphD2Q51&1Kk=%(;t>^%3bkjn6iB8Kl|)BWBGI5iBN-~9lc<J56Lj|zC5_nvcf|A>muCcug*q%%nX8gAa^Mh@#08XbS zv=vxdD%`Se{xZxA6V-4B*s?&;su4vA-<-D*WdOHaWa!wR@* zzW69QWT>C!h~yUoMG%R;q2Jg>xW5J uhP!}h&974#&WiUAP?E}CBd`ci5`o_-qRb&!3c5Z30000 + + + + + Napi + + + + + +
+
+ + +
+ +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + +
.h文件选择*: + +
输出路径选择: + +
serviceID:
+ + + +
+
+
+
+ + + \ No newline at end of file -- Gitee