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; 25// this method is called when your extension is activated 26// your extension is activated the very first time the command is executed 27 28/** 29 * @param {vscode.ExtensionContext} context 30 */ 31function activate(context) { 32 // Use the console to output diagnostic information (console.log) and errors (console.error) 33 // This line of code will only be executed once when your extension is activated 34 console.log('Congratulations, your extension "gnapi" is now active!'); 35 let disposable = register(context, 'generate_napi'); 36 let disposableMenu = register(context, 'generate_napi_menu'); 37 context.subscriptions.push(disposable); 38 context.subscriptions.push(disposableMenu); 39 var platform = detectPlatform(); 40 if (platform == 'win') { 41 exeFilePath = __dirname + "/napi_generator-win.exe"; 42 } else if (platform == 'mac') { 43 exeFilePath = __dirname + "/napi_generator-macos"; 44 } else if (platform == 'Linux') { 45 exeFilePath = __dirname + "/napi_generator-linux"; 46 } 47} 48 49function executor(name, genDir, mode, importIsCheck) { 50 var exec = require('child_process').exec; 51 exec(genCommand(name, genDir, mode, importIsCheck), function (error, stdout, stderr) { 52 VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr); 53 if (error || stdout.indexOf("success") < 0) { 54 vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout); 55 return VsPluginLog.logError("VsPlugin:" + error + stdout); 56 } 57 vscode.window.showInformationMessage("Generated successfully"); 58 }); 59} 60 61function genCommand(name, genDir, mode, importIsCheck) { 62 var genFileMode = mode == 0 ? " -f " : " -d "; 63 if (genDir == ""){ 64 return exeFilePath + genFileMode + name; 65 } 66 return exeFilePath + genFileMode + name + " -o " + genDir + " -i " + importIsCheck; 67} 68 69function exeFileExit() { 70 if (fs.existsSync(exeFilePath)) { 71 return true; 72 } 73 return false; 74} 75 76function register(context, command) { 77 let disposable = vscode.commands.registerCommand(command, function (uri) { 78 // The code you place here will be executed every time your command is executed 79 // Display a message box to the user 80 const panel = vscode.window.createWebviewPanel( 81 'generate', // Identifies the type of WebView 82 'Generate Napi Frame', // Title of the panel displayed to the user 83 vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor 84 { 85 enableScripts: true, // Enable or disable JS, default is Enable 86 retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset 87 } 88 ); 89 panel.webview.html = getWebviewContent(context); 90 panel.webview.onDidReceiveMessage(message => { 91 let msg = message.msg; 92 if (msg == "cancel") { 93 panel.dispose(); 94 } else if(msg == "param") { 95 let mode = message.mode; 96 let name = message.fileNames; 97 let genDir = message.genDir; 98 let importIsCheck = message.importIsCheck; 99 checkMode(name, genDir, mode, importIsCheck); 100 } else { 101 selectPath(panel, message); 102 } 103 }, undefined, context.subscriptions); 104 let fn = re.getFileInPath(uri.fsPath); 105 let tt = re.match("@ohos.[a-zA-Z_0-9]+.d.ts", fn); 106 var result = { 107 msg: "selectInterPath", 108 path: tt ? uri.fsPath : "" 109 } 110 panel.webview.postMessage(result); 111 }); 112 return disposable; 113} 114 115/** 116* 选择本地目录/文件夹 117*/ 118 function selectPath(panel, message) { 119 let mode = 1; 120 if (message.mode != undefined) { 121 mode = message.mode; 122 } 123 const options = { 124 canSelectMany: mode == 0 ? true : false,//是否可以选择多个 125 openLabel: mode == 0 ? '选择文件' : '选择文件夹',//打开选择的右下角按钮label 126 canSelectFiles: mode == 0 ? true : false,//是否选择文件 127 canSelectFolders: mode == 0 ? false : true,//是否选择文件夹 128 defaultUri:vscode.Uri.file(''),//默认打开本地路径 129 filters: { 130 'Text files': ['d.ts'] 131 } 132 }; 133 134 return vscode.window.showOpenDialog(options).then(fileUri => { 135 if (fileUri && fileUri[0]) { 136 console.log('Selected file: ' + fileUri[0].fsPath); 137 let filePath = ""; 138 for (let index = 0; index < fileUri.length; index++) { 139 filePath += fileUri[index].fsPath.concat(","); 140 } 141 var result = { 142 msg: message.msg, 143 path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath 144 } 145 panel.webview.postMessage(result); 146 return fileUri[0].fsPath 147 } 148 }); 149} 150 151function checkMode(name, genDir, mode, importIsCheck) { 152 name = re.replaceAll(name, " ", ""); 153 if ("" == name) { 154 vscode.window.showErrorMessage("Please enter the path!"); 155 return; 156 } 157 if (mode == 0) { 158 if (name.indexOf(".") < 0) { 159 vscode.window.showErrorMessage("Please enter the correct file path!"); 160 return; 161 } 162 } else { 163 if (name.indexOf(".") > 0 || !fs.lstatSync(name).isDirectory()) { 164 vscode.window.showErrorMessage("Please enter the correct folder folder!"); 165 return; 166 } 167 } 168 if (exeFileExit()) { 169 executor(name, genDir, mode, importIsCheck); 170 } else { 171 vscode.window.showInformationMessage("Copy executable program to " + __dirname); 172 } 173} 174 175// this method is called when your extension is deactivated 176function deactivate() { } 177 178function getWebviewContent(context) { 179 let data = readFile(__dirname + '/vs_plugin_view.html'); 180 data = getWebViewContent(context, '/vs_plugin_view.html'); 181 return data.toString(); 182} 183 184function getWebViewContent(context, templatePath) { 185 const resourcePath = path.join(context.extensionPath, templatePath); 186 const dirPath = path.dirname(resourcePath); 187 let html = fs.readFileSync(resourcePath, 'utf-8'); 188 html = html.replace(/(<link.+?href="|<script.+?src="|<iframe.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => { 189 if($2.indexOf("https://")<0)return $1 + vscode.Uri.file(path.resolve(dirPath, $2)) 190 .with({ scheme: 'vscode-resource' }).toString() + '"'; 191 else return $1 + $2+'"'; 192 }); 193 return html; 194} 195 196module.exports = { 197 activate, 198 deactivate 199}