1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16// The module 'vscode' contains the VS Code extensibility API 17// Import the module and reference it with the alias vscode in your code below 18const vscode = require('vscode'); 19const fs = require('fs'); 20const re = require("./gen/tools/VsPluginRe"); 21const { VsPluginLog } = require("./gen/tools/VsPluginLog"); 22const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool'); 23const path = require('path'); 24var exeFilePath = null; 25const dirCache={}; 26var globalPanel = null; 27 28var importToolChain = false; 29var extensionIds = []; 30var nextPluginId = null; 31// this method is called when your extension is activated 32// your extension is activated the very first time the command is executed 33 34/** 35 * @param {vscode.ExtensionContext} context 36 */ 37function activate(context) { 38 // Use the console to output diagnostic information (console.log) and errors (console.error) 39 // This line of code will only be executed once when your extension is activated 40 console.log('Congratulations, your extension "ApiScan" is now active!'); 41 let disposable = register(context, 'api_scan'); 42 let disposableMenu = register(context, 'api_scan_menu'); 43 context.subscriptions.push(disposable); 44 context.subscriptions.push(disposableMenu); 45 var platform = detectPlatform(); 46 if (platform == 'win') { 47 exeFilePath = __dirname + "/search-win.exe"; 48 } else if (platform == 'mac') { 49 exeFilePath = __dirname + "/search-macos"; 50 } else if (platform == 'Linux') { 51 exeFilePath = __dirname + "/search-linux"; 52 } 53} 54 55function executorApiscan(name, genDir) { 56 if (genDir == "" || genDir == null) { 57 genDir = name; 58 } 59 var command = exeFilePath + " -d " + name + " -o " + genDir; 60 var exec = require('child_process').exec; 61 exec(command, function (error, stdout, stderr) { 62 VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); 63 if (error || stdout.indexOf("errno") > 0) { 64 vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); 65 return VsPluginLog.logError("VsPlugin:" + error + stdout); 66 } 67 vscode.window.showInformationMessage("Api Scan Successfully"); 68 }); 69} 70 71function exeFileExit() { 72 if (fs.existsSync(exeFilePath)) { 73 return true; 74 } 75 return false; 76} 77 78function register(context, command) { 79 let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) { 80 // The code you place here will be executed every time your command is executed 81 // Display a message box to the user 82 globalPanel = vscode.window.createWebviewPanel( 83 'api_scan', // Identifies the type of WebView 84 'Api Scan', // Title of the panel displayed to the user 85 vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor 86 { 87 enableScripts: true, // Enable or disable JS, default is Enable 88 retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset 89 } 90 ); 91 92 if (typeof(boolValue) == 'boolean' && Array.isArray(items)) { 93 if (boolValue == true) { 94 //遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理 95 let myExtensionId = 'kaihong.ApiScan'; 96 for (let i = 0; i < items.length; i++) { 97 if (myExtensionId == items[i] && (i == items.length - 1)) { 98 importToolChain = false; 99 } else if (myExtensionId == items[i] && (i != items.length - 1)) { 100 importToolChain = boolValue; 101 nextPluginId = items[i + 1]; 102 } 103 extensionIds.push(items[i]); 104 } 105 } 106 } 107 108 globalPanel.webview.html = getWebviewContent(context, importToolChain); 109 let msg; 110 globalPanel.webview.onDidReceiveMessage(message => { 111 msg = message.msg; 112 if (msg == "cancel") { 113 globalPanel.dispose(); 114 } 115 else if (msg == "api_scan") { 116 checkReceiveMsg(message); 117 } else { 118 selectPath(globalPanel, message); 119 } 120 }, undefined, context.subscriptions); 121 let fn = re.getFileInPath(uri.fsPath); 122 let tt = re.match("[a-zA-Z_0-9]", fn); 123 var result = { 124 msg: "selectASFilePath", 125 path: tt ? uri.fsPath : "" 126 } 127 globalPanel.webview.postMessage(result); 128 }); 129 return disposable; 130} 131 132function checkReceiveMsg(message) { 133 let name = message.fileNames; 134 let genDir = message.genDir; 135 let buttonName = message.buttonName; 136 name = re.replaceAll(name, " ", ""); 137 if ("" == name) { 138 vscode.window.showErrorMessage("Please enter the path!"); 139 return; 140 } 141 if (exeFileExit()) { 142 executorApiscan(name, genDir); 143 if (buttonName == 'Next') { 144 startNextPlugin(); 145 } 146 } else { 147 vscode.window.showInformationMessage("Copy executable program to " + __dirname); 148 } 149} 150 151/** 152* 获取插件执行命令 153*/ 154function nextPluginExeCommand(nextPluginId) { 155 if (nextPluginId == "kaihong.ApiScan") { 156 return 'api_scan'; 157 } else if (nextPluginId == "kaihong.gn-gen") { 158 return 'generate_gn'; 159 } else if (nextPluginId == "kaihong.service-gen") { 160 return 'generate_service'; 161 } else if (nextPluginId == "kaihong.ts-gen") { 162 return 'generate_ts'; 163 } else if (nextPluginId == "kaihong.napi-gen") { 164 return 'generate_napi'; 165 } else { 166 return null; 167 } 168} 169 170/** 171* 执行完毕后开启工具链中下一个插件 172*/ 173function startNextPlugin() { 174 const extension = vscode.extensions.getExtension(nextPluginId); 175 if (extension) { 176 let startNextPlugin = nextPluginExeCommand(nextPluginId); 177 try { 178 vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds); 179 } catch (error) { 180 console.error(error); 181 } 182 } 183} 184 185/** 186* 选择本地目录/文件夹 187*/ 188function selectPath(panel, message) { 189 const options = { 190 canSelectMany: false,//是否可以选择多个 191 canSelectFolders: true,//是否选择文件夹 192 defaultUri:vscode.Uri.file(message.filePath)//默认打开本地路径 193 }; 194 195 return vscode.window.showOpenDialog(options).then(fileUri => { 196 if (fileUri && fileUri[0]) { 197 console.log('Selected file: ' + fileUri[0].fsPath); 198 let filePath = ""; 199 for (let index = 0; index < fileUri.length; index++) { 200 filePath += fileUri[index].fsPath.concat(","); 201 } 202 var result = { 203 msg: message.msg, 204 path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath 205 } 206 panel.webview.postMessage(result); 207 return fileUri[0].fsPath 208 } 209 }); 210} 211 212// this method is called when your extension is deactivated 213function deactivate() { } 214 215function getWebviewContent(context, importToolChain) { 216 let data = readFile(__dirname + '/vs_plugin_view.html'); 217 data = getWebViewContent(context, '/vs_plugin_view.html'); 218 let content = data.toString(); 219 if (importToolChain) { 220 content = content.replace('Ok', 'Next'); 221 } 222 return content; 223} 224 225function getWebViewContent(context, templatePath) { 226 const resourcePath = path.join(context.extensionPath, templatePath); 227 const dirPath = path.dirname(resourcePath); 228 let html = fs.readFileSync(resourcePath, 'utf-8'); 229 html = html.replace(/(<link.+?href="|<script.+?src="|<iframe.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => { 230 if ($2.indexOf("https://") < 0) { 231 return $1 + globalPanel.webview.asWebviewUri(vscode.Uri.file(path.resolve(dirPath, $2))) + '"'; 232 } else { 233 return $1 + $2 + '"'; 234 } 235 }); 236 return html; 237} 238 239module.exports = { 240 activate, 241 deactivate 242}