• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, writeFile } = require('./gen/tools/VsPluginTool');
23const path = require('path');
24const os = require('os');
25var exeFilePath = null;
26var flag = "";
27var isTrue = false;
28var globalPanel = null;
29
30var importToolChain = false;
31var extensionIds = [];
32var nextPluginId = null;
33// this method is called when your extension is activated
34// your extension is activated the very first time the command is executed
35
36/**
37 * @param {vscode.ExtensionContext} context
38 */
39function activate(context) {
40	// Use the console to output diagnostic information (console.log) and errors (console.error)
41	// This line of code will only be executed once when your extension is activated
42	console.log('Congratulations, your extension "gn-gen" is now active!');
43	let disposable = register(context, 'generate_gn');
44	let disposableMenu = register(context, 'generate_gn_menu');
45	context.subscriptions.push(disposable);
46	context.subscriptions.push(disposableMenu);
47	var platform = detectPlatform();
48	if (platform == 'win') {
49		exeFilePath = __dirname + "/gn-gen-win.exe";
50	} else if (platform == 'mac') {
51		exeFilePath = __dirname + "/gn-gen-macos";
52	} else if (platform == 'Linux') {
53		exeFilePath = __dirname + "/gn-gen-linux";
54	}
55	vscode.window.onDidChangeActiveColorTheme(colorTheme => {
56		var result = {
57			msg: "colorThemeChanged"
58		}
59		globalPanel.webview.postMessage(result);
60	});
61}
62
63function gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir,
64	subsystemName, componentName, compileOptions) {
65	var exec = require('child_process').exec;
66	exec(genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType, transplantDir,
67		subsystemName, componentName, compileOptions),
68		{
69			maxBuffer: 1024 * 1024 * 20
70		},
71		function (error, stdout, stderr) {
72		 VsPluginLog.logInfo('VsPlugin: stdout =' + stdout + ", stderr =" + stderr);
73		if (error || stdout.indexOf("generate gn ok") < 0) {
74			console.log(error)
75			vscode.window.showErrorMessage("genError:" + (error != null ? error : "") + stdout);
76			return VsPluginLog.logError("VsPlugin:" + error + stdout);
77		}
78		vscode.window.showInformationMessage("Generated successfully");
79	});
80}
81
82function genGnCommand(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
83	transplantDir, subsystemName, componentName, compileOptions) {
84	var command = exeFilePath + " -o " + outputCodeDir + " -p " + originCodeDir + " -f " + inputScriptDir
85	+ " -t " + scriptType + " -s " + subsystemName + " -m " + componentName + " -d " + transplantDir;
86	if (compileOptions != "") {
87		command += " -a " + "\"" + compileOptions + "\"";
88	}
89
90	command = re.replaceAll(command, '\\\\', '/');
91
92	console.log("command = " + command)
93	return command;
94}
95
96/**
97 * 将插件界面读取的扩展配置更新到cfg.json文件中
98 * @param extFile 用户自定义的支持文件类型
99 * @param extFlag 用户自定义的支持编译选项
100 */
101function refreshJsonCfg(extFile, extFlag) {
102	let cfgFilePath = __dirname + '/res/cfg.json';
103	let jsonCfg = readFile(cfgFilePath);
104	let cfgObj = JSON.parse(jsonCfg.toString());
105	cfgObj.fileSuffix = extFile;
106	cfgObj.compileflag = extFlag;
107	let cfgStr = JSON.stringify(cfgObj);
108	writeFile(cfgFilePath, cfgStr);
109}
110
111function exeFileExit() {
112	if (fs.existsSync(exeFilePath)) {
113		return true;
114	}
115	return false;
116}
117
118function register(context, command) {
119	let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) {
120		// The code you place here will be executed every time your command is executed
121		// Display a message box to the user
122		globalPanel = vscode.window.createWebviewPanel(
123			'generate', // Identifies the type of WebView
124			'Gn Generate Frame', // Title of the panel displayed to the user
125			vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor
126			{
127				enableScripts: true, // Enable or disable JS, default is Enable
128				retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
129			}
130		);
131		 if (typeof(boolValue) == 'boolean' && Array.isArray(items)) {
132			if (boolValue == true) {
133				//遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理
134				let myExtensionId = 'kaihong.gn-gen';
135				for (let i = 0; i < items.length; i++) {
136					if (myExtensionId == items[i] && (i == items.length - 1)) {
137						importToolChain = false;
138					} else if (myExtensionId == items[i] && (i != items.length - 1)) {
139						importToolChain = boolValue;
140						nextPluginId = items[i + 1];
141					}
142					extensionIds.push(items[i]);
143				}
144			}
145		}
146		globalPanel.webview.html = getWebviewContent(context, importToolChain);
147		let msg;
148		globalPanel.webview.onDidReceiveMessage(message => {
149			msg = message.msg;
150			if (msg == "cancel") {
151				globalPanel.dispose();
152			} else if(msg == "gn") {
153				checkReceiveMsg(message);
154			} else {
155				selectPath(globalPanel, message);
156			}
157		}, undefined, context.subscriptions);
158		let fn = re.getFileInPath(uri.fsPath);
159		let tt = re.match("([a-zA-Z_0-9]+.[a-zA-Z_0-9])", fn);
160		var result = {
161			msg: "selectinputScriptDir",
162			path: tt ? uri.fsPath : ""
163			}
164	    globalPanel.webview.postMessage(result);
165	});
166	return disposable;
167}
168
169function checkReceiveMsg(message) {
170	let outputCodeDir = message.outputCodeDir;
171	let originCodeDir = message.originCodeDir;
172	let inputScriptDir = message.inputScriptDir;
173	let scriptType = message.scriptType;
174	let transplantDir = message.transplantDir;
175	let subsystemName = message.subsystemName;
176	let componentName = message.componentName;
177	let compileOptions = message.compileOptions;
178	let buttonName = message.buttonName;
179
180	refreshJsonCfg(message.extFile, message.extFlag);
181	checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
182		transplantDir, subsystemName, componentName, compileOptions);
183
184	if (buttonName == 'Next') {
185		startNextPlugin();
186	}
187}
188
189/**
190* 获取插件执行命令
191*/
192function nextPluginExeCommand(nextPluginId) {
193    if (nextPluginId == "kaihong.ApiScan") {
194		return 'api_scan';
195	} else if (nextPluginId == "kaihong.gn-gen") {
196		return 'generate_gn';
197	} else if (nextPluginId == "kaihong.service-gen") {
198		return 'generate_service';
199	} else if (nextPluginId == "kaihong.ts-gen") {
200		return 'generate_ts';
201	} else if (nextPluginId == "kaihong.napi-gen") {
202		return 'generate_napi';
203	} else {
204		return null;
205	}
206}
207
208/**
209* 执行完毕后开启工具链中下一个插件
210*/
211function startNextPlugin() {
212	const extension = vscode.extensions.getExtension(nextPluginId);
213	if (extension) {
214		let startNextPlugin = nextPluginExeCommand(nextPluginId);
215		try {
216			vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds);
217		} catch (error) {
218			console.error(error);
219		}
220	}
221}
222
223/**
224* 选择本地目录/文件夹
225*/
226 function selectPath(panel, message) {
227	 let mode = 1;
228	if (message.mode != undefined) {
229		mode = message.mode;
230	}
231	flag = flag == "" ? '' : flag;
232	const options = {
233		canSelectMany: false,//是否可以选择多个
234		canSelectFiles: mode == 0 ? true : false,//是否选择文件
235		canSelectFolders: mode == 0 ? false : true,//是否选择文件夹
236		defaultUri:vscode.Uri.file(flag),//默认打开本地路径
237		filters: {
238			'All files': ['*']
239		}
240	};
241
242	return vscode.window.showOpenDialog(options).then(fileUri => {
243		if (fileUri && fileUri[0]) {
244			console.log('Selected file: ' + fileUri[0].fsPath);
245			var filePath = "";
246			filePath = fileUri[0].fsPath.concat(',');
247			filePath = re.replaceAll(filePath, '\\\\', '/');
248			if (filePath.substring(1,2) == ":") {
249				let filePathTemp = filePath.substring(0,1).toUpperCase()
250				filePath = filePathTemp + filePath.substring(1,filePath.length)
251			}
252			var result = {
253				 msg: message.msg,
254				 path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath
255			}
256			console.log('message.msg: ' + message.msg);
257			if (!isTrue && message.msg == "selectoutputCodeDir"){
258				flag = filePath.substring(0, filePath.length - 1);
259				let fileTempName = "out";
260		        let pos = flag.indexOf(fileTempName);
261		        flag = flag.substr(0,pos-1);
262				isTrue = true;
263			}
264			panel.webview.postMessage(result);
265			return fileUri[0].fsPath
266		}
267   });
268}
269
270function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
271	transplantDir, subsystemName, componentName, compileOptions) {
272	outputCodeDir = re.replaceAll(outputCodeDir, " ", "");
273	if ("" == outputCodeDir) {
274		vscode.window.showErrorMessage("Please enter the outputCodeDir path!");
275		return;
276	}
277	originCodeDir = re.replaceAll(originCodeDir, " ", "");
278	if ("" == originCodeDir) {
279		vscode.window.showErrorMessage("Please enter the originCodeDir path!");
280		return;
281	}
282	inputScriptDir = re.replaceAll(inputScriptDir, " ", "");
283	if ("" == inputScriptDir) {
284		vscode.window.showErrorMessage("Please enter the inputScriptDir path!");
285		return;
286	}
287	if (inputScriptDir.indexOf(".") < 0) {
288		vscode.window.showErrorMessage("Please enter the correct file path!");
289		return;
290	}
291	transplantDir = re.replaceAll(transplantDir, " ", "");
292	if ("" == transplantDir) {
293		vscode.window.showErrorMessage("Please enter the transplantDir path!");
294		return;
295	}
296	subsystemName = re.replaceAll(subsystemName, " ", "");
297	if ("" == subsystemName) {
298		vscode.window.showErrorMessage("Please enter the subsystemName!");
299		return;
300	}
301	componentName = re.replaceAll(componentName, " ", "");
302	if ("" == componentName) {
303		vscode.window.showErrorMessage("Please enter the componentName!");
304		return;
305	}
306	if (exeFileExit()) {
307		gnexecutor(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
308			transplantDir, subsystemName, componentName, compileOptions);
309	} else {
310		vscode.window.showInformationMessage("Copy executable program to " + __dirname);
311	}
312}
313
314// this method is called when your extension is deactivated
315function deactivate() { }
316
317function getWebviewContent(context, importToolChain) {
318	let data = readFile(__dirname + '/vs_plugin_view.html');
319	data = getWebViewContent(context, '/vs_plugin_view.html');
320	let content = data.toString();
321	if (importToolChain) {
322		content = content.replace('Ok', 'Next');
323	}
324	return content;
325}
326
327function getWebViewContent(context, templatePath) {
328	const reoriginCodeDir = path.join(context.extensionPath, templatePath);
329	const dirPath = path.dirname(reoriginCodeDir);
330	let html = fs.readFileSync(reoriginCodeDir, 'utf-8');
331	html = html.replace(/(<link.+?href="|<script.+?src="|<iframe.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {
332		if ($2.indexOf("https://") < 0) {
333			return $1 + globalPanel.webview.asWebviewUri(vscode.Uri.file(path.resolve(dirPath, $2))) + '"';
334		} else {
335			return $1 + $2+'"';
336		}
337	});
338	return html;
339}
340
341module.exports = {
342	activate,
343	deactivate
344}