• 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 } = require('./gen/tools/VsPluginTool');
23const path = require('path');
24let exeFilePath = null;
25const dirCache = {};
26let globalPanel = null;
27
28let importToolChain = false;
29let extensionIds = [];
30let 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	let 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 || genDir === undefined) {
57		genDir = name;
58	}
59	let command = exeFilePath + ' -d ' + name + ' -o ' + genDir;
60	let 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 !== undefined) ?
65        error : '') + stdout);
66			return VsPluginLog.logError('VsPlugin:' + error + stdout);
67		}
68		vscode.window.showInformationMessage('Api Scan Successfully');
69		return '';
70	});
71}
72
73function exeFileExit() {
74	if (fs.existsSync(exeFilePath)) {
75		return true;
76	}
77	return false;
78}
79
80function register(context, command) {
81	let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) {
82		// The code you place here will be executed every time your command is executed
83		// Display a message box to the user
84		globalPanel = vscode.window.createWebviewPanel(
85			'api_scan', // Identifies the type of WebView
86			'Api Scan', // Title of the panel displayed to the user
87			vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor
88			{
89				enableScripts: true, // Enable or disable JS, default is Enable
90				retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
91			}
92		);
93
94		checkBoolval(boolValue, items);
95
96		globalPanel.webview.html = getWebviewContent(context, importToolChain);
97		let msg;
98		globalPanel.webview.onDidReceiveMessage(message => {
99			msg = message.msg;
100			if (msg === 'cancel') {
101				globalPanel.dispose();
102			}
103			else if (msg === 'api_scan') {
104				checkReceiveMsg(message);
105			} else {
106				selectPath(globalPanel, message);
107			}
108		}, undefined, context.subscriptions);
109    // 路径有效性判断
110    if (uri.fsPath !== undefined) {
111      let fn = re.getFileInPath(uri.fsPath);
112      let tt = re.match('[a-zA-Z_0-9]', fn);
113      let result = {
114        msg: 'selectASFilePath',
115        path: tt ? uri.fsPath : ''
116      };
117      globalPanel.webview.postMessage(result);
118    }
119	});
120	return disposable;
121}
122
123function checkBoolval(boolValue, items) {
124  if (typeof (boolValue) === 'boolean' && Array.isArray(items)) {
125    if (boolValue === true) {
126      //遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理
127      getNextPlugin(items, boolValue);
128    }
129  }
130}
131
132function getNextPlugin(items, boolValue) {
133  let myExtensionId = 'kaihong.ApiScan';
134  for (let i = 0; i < items.length; i++) {
135    if (myExtensionId === items[i] && (i === items.length - 1)) {
136      importToolChain = false;
137    } else if (myExtensionId === items[i] && (i !== items.length - 1)) {
138      importToolChain = boolValue;
139      nextPluginId = items[i + 1];
140    }
141    extensionIds.push(items[i]);
142  }
143}
144
145function checkReceiveMsg(message) {
146	let name = message.fileNames;
147	let genDir = message.genDir;
148	let buttonName = message.buttonName;
149	name = re.replaceAll(name, ' ', '');
150	if ('' === name) {
151		vscode.window.showErrorMessage('Please enter the path!');
152		return;
153	}
154	if (exeFileExit()) {
155		executorApiscan(name, genDir);
156		if (buttonName === 'Next') {
157			startNextPlugin();
158		}
159	} else {
160		vscode.window.showInformationMessage('Copy executable program to ' + __dirname);
161	}
162}
163
164/**
165* 获取插件执行命令
166*/
167function nextPluginExeCommand(nextPluginId) {
168    if (nextPluginId === 'kaihong.ApiScan') {
169		return 'api_scan';
170	} else if (nextPluginId === 'kaihong.gn-gen') {
171		return 'generate_gn';
172	} else if (nextPluginId === 'kaihong.service-gen') {
173		return 'generate_service';
174	} else if (nextPluginId === 'kaihong.ts-gen') {
175		return 'generate_ts';
176	} else if (nextPluginId === 'kaihong.napi-gen') {
177		return 'generate_napi';
178	} else {
179		return null;
180	}
181}
182
183/**
184* 执行完毕后开启工具链中下一个插件
185*/
186function startNextPlugin() {
187	const extension = vscode.extensions.getExtension(nextPluginId);
188	if (extension) {
189		let startNextPlugin = nextPluginExeCommand(nextPluginId);
190		try {
191			vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds);
192		} catch (error) {
193			console.error(error);
194		}
195	}
196}
197
198/**
199* 选择本地目录/文件夹
200*/
201function selectPath(panel, message) {
202	const options = {
203		canSelectMany: false, //是否可以选择多个
204		canSelectFolders: true, //是否选择文件夹
205		defaultUri:vscode.Uri.file(message.filePath)//默认打开本地路径
206	};
207
208	return vscode.window.showOpenDialog(options).then(fileUri => {
209	   if (fileUri && fileUri[0]) {
210		   console.log('Selected file: ' + fileUri[0].fsPath);
211		   let filePath = '';
212		   for (let index = 0; index < fileUri.length; index++) {
213				filePath += fileUri[index].fsPath.concat(',');
214		   }
215		   let result = {
216				msg: message.msg,
217				path: filePath.length > 0 ? filePath.substring(0, filePath.length - 1) : filePath
218				};
219		   panel.webview.postMessage(result);
220		   return fileUri[0].fsPath;
221	   } else {
222	   	return '';
223	   }
224   });
225}
226
227// this method is called when your extension is deactivated
228function deactivate() { }
229
230function getWebviewContent(context, importToolChain) {
231	let data = readFile(__dirname + '/vs_plugin_view.html');
232	data = getWebViewContent(context, '/vs_plugin_view.html');
233  let content = data.toString();
234	if (importToolChain) {
235		content = content.replace('Ok', 'Next');
236	}
237	return content;
238}
239
240function getWebViewContent(context, templatePath) {
241	const resourcePath = path.join(context.extensionPath, templatePath);
242	const dirPath = path.dirname(resourcePath);
243	let html = fs.readFileSync(resourcePath, 'utf-8');
244	html = html.replace(/(<link.+?href="|<script.+?src="|<iframe.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {
245        if ($2.indexOf('https://') < 0) {
246            return $1 + globalPanel.webview.asWebviewUri(vscode.Uri.file(path.resolve(dirPath, $2))) + '"';
247        } else {
248            return $1 + $2 + '"';
249        }
250	});
251	return html;
252}
253
254module.exports = {
255	activate,
256	deactivate
257};
258