From 2895b2cfe3b6694a9079d11045cd58fa8e0e3543 Mon Sep 17 00:00:00 2001 From: Sohee Kwon <122425990+hohee-hee@users.noreply.github.com> Date: Wed, 4 Oct 2023 10:44:12 +0900 Subject: [PATCH] [EdgeTPU] Introduce EdgeTPUCfgEditorPanel This commit creates EdgeTPUCfgEditorPanel.ts that is a panel for .edgetpucfg. - Create EdgetpuCfgEditorPanel.ts : Cfg Editor Panel for edgetpu cfg editor - Add register in extension.ts - Map a new view type with a new file extension - .edgetpucfg - Error fix : Duplication of setDefaultValues causes error so changed the command name to "setDefaultEdgetpuValues". - Add objects about setDefaultEdgetpuValues in Commands and Keybindings in package.json ONE-vscode-DCO-1.0-Signed-off-by: hohee-hee Co-authored-by: Bumsoo Ko Co-authored-by: Hyeon-Uk --- package.json | 20 ++ src/CfgEditor/EdgeTPUCfgEditorPanel.ts | 294 +++++++++++++++++++++++++ src/extension.ts | 3 + 3 files changed, 317 insertions(+) create mode 100644 src/CfgEditor/EdgeTPUCfgEditorPanel.ts diff --git a/package.json b/package.json index fca3025a2..51a433d4d 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,16 @@ ], "priority": "option" }, + { + "viewType": "one.editor.edgetpucfg", + "displayName": "Edge TPU Configuration Editor", + "selector": [ + { + "filenamePattern": "*.edgetpucfg" + } + ], + "priority": "option" + }, { "viewType": "one.viewer.mondrian", "displayName": "Mondrian", @@ -287,6 +297,11 @@ "title": "ONE: Set Default Values", "category": "ONE" }, + { + "command": "one.editor.edgetpucfg.setDefaultValues", + "title": "ONE: Set Default EdgeTPU Compiler Values", + "category": "ONE" + }, { "command": "one.editor.mpq.createFromDefaultExplorer", "title": "ONE: Create Mixed Precision Quantization Configuration", @@ -309,6 +324,11 @@ "key": "ctrl+shift+/", "when": "activeCustomEditorId == one.editor.cfg" }, + { + "command": "one.cfgEditor.setDefaultEdgetpuValues", + "key": "ctrl+shift+/", + "when": "activeCustomEditorId == one.editor.edgetpucfg" + }, { "command": "one.explorer.deleteOnShortcut", "key": "delete", diff --git a/src/CfgEditor/EdgeTPUCfgEditorPanel.ts b/src/CfgEditor/EdgeTPUCfgEditorPanel.ts new file mode 100644 index 000000000..b96e9b2bb --- /dev/null +++ b/src/CfgEditor/EdgeTPUCfgEditorPanel.ts @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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. + */ +/* + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* +Some part of this code refers to +https://github.com/microsoft/vscode-extension-samples/blob/2556c82cb333cf65d372bd01ac30c35ea1898a0e/custom-editor-sample/src/catScratchEditor.ts +*/ + +import * as path from "path"; +import * as vscode from "vscode"; + +import { getNonce } from "../Utils/external/Nonce"; +import { getUri } from "../Utils/external/Uri"; + +import { EdgeTPUCfgData } from "./EdgeTPUCfgData"; + +/* istanbul ignore next */ +export class EdgeTPUCfgEditorPanel implements vscode.CustomTextEditorProvider { + private _disposables: vscode.Disposable[] = []; + private _oneConfigMap: any = {}; + private _activeDocument: vscode.TextDocument | undefined; + private _activeWebviewPanel: vscode.WebviewPanel | undefined; + + public static readonly viewType = "one.editor.edgetpucfg"; + + public static register(context: vscode.ExtensionContext): void { + const provider = new EdgeTPUCfgEditorPanel(context); + + const registrations = [ + vscode.window.registerCustomEditorProvider( + EdgeTPUCfgEditorPanel.viewType, + provider, + { + webviewOptions: { + retainContextWhenHidden: true, + }, + } + ), + // Add command registration here + vscode.commands.registerCommand( + "one.cfgEditor.setDefaultEdgetpuValues", + () => { + if (!provider._activeWebviewPanel || !provider._activeDocument) { + return; + } + + const cfgName = path.parse(provider._activeDocument!.fileName).name; + + provider._activeWebviewPanel!.webview.postMessage({ + type: "setDefaultEdgetpuValues", + name: cfgName, + }); + } + ), + ]; + + registrations.forEach((disposable) => + context.subscriptions.push(disposable) + ); + } + + constructor(private readonly context: vscode.ExtensionContext) {} + + async resolveCustomTextEditor( + document: vscode.TextDocument, + webviewPanel: vscode.WebviewPanel, + _token: vscode.CancellationToken + ): Promise { + this._activeWebviewPanel = webviewPanel; + this._activeDocument = document; + this._oneConfigMap[document.uri.toString()] = new EdgeTPUCfgData(); + await this.initWebview(document, webviewPanel.webview); + this.initWebviewPanel(document, webviewPanel); + this.updateWebview(document, webviewPanel.webview); + } + + async initWebview( + document: vscode.TextDocument, + webview: vscode.Webview + ): Promise { + webview.options = { + enableScripts: true, + }; + + const nonce = getNonce(); + const toolkitUri = getUri(webview, this.context.extensionUri, [ + "node_modules", + "@vscode", + "webview-ui-toolkit", + "dist", + "toolkit.js", + ]); + + const codiconUri = getUri(webview, this.context.extensionUri, [ + "node_modules", + "@vscode", + "codicons", + "dist", + "codicon.css", + ]); + + const jsUri = getUri(webview, this.context.extensionUri, [ + "media", + "EdgeTPUCfgEditor", + "index.js", + ]); + + const cssUri = getUri(webview, this.context.extensionUri, [ + "media", + "EdgeTPUCfgEditor", + "cfgeditor.css", + ]); + + const htmlUri = vscode.Uri.joinPath( + this.context.extensionUri, + "media/EdgeTPUCfgEditor/cfgeditor.html" + ); + + let html = Buffer.from( + await vscode.workspace.fs.readFile(htmlUri) + ).toString(); + html = html.replace(/\${nonce}/g, `${nonce}`); + html = html.replace(/\${webview.cspSource}/g, `${webview.cspSource}`); + html = html.replace(/\${toolkitUri}/g, `${toolkitUri}`); + html = html.replace(/\${codiconUri}/g, `${codiconUri}`); + html = html.replace(/\${jsUri}/g, `${jsUri}`); + html = html.replace(/\${cssUri}/g, `${cssUri}`); + webview.html = html; + + // Receive message from the webview. + webview.onDidReceiveMessage((e) => { + switch (e.type) { + case "requestDisplayCfg": + this.updateWebview(document, webview); + break; + case "setParam": + this._oneConfigMap[document.uri.toString()].updateSectionWithKeyValue( + e.section, + e.param, + e.value + ); + break; + case "setSection": + this._oneConfigMap[document.uri.toString()].updateSectionWithValue( + e.section, + e.param + ); + break; + case "updateDocument": + if ( + this._oneConfigMap[document.uri.toString()].isSame( + document.getText() + ) === false + ) { + this._oneConfigMap[document.uri.toString()].sort(); + + // TODO Optimize this to modify only changed lines + const edit = new vscode.WorkspaceEdit(); + edit.replace( + document.uri, + new vscode.Range(0, 0, document.lineCount, 0), + this._oneConfigMap[document.uri.toString()].getAsString() + ); + vscode.workspace.applyEdit(edit); + } + break; + case "getPathByDialog": { + const dialogOptions = { + canSelectMany: false, + canSelectFolders: e.isFolder, + openLabel: "Open", + filters: { "target files": e.ext, "all files": ["*"] }, + }; + let newPath = e.oldPath; + vscode.window.showOpenDialog(dialogOptions).then((fileUri) => { + if (fileUri && fileUri[0]) { + newPath = fileUri[0].fsPath.toString(); + webview.postMessage({ + type: "applyDialogPath", + step: e.postStep, + elemID: e.postElemID, + path: newPath, + }); + } + }); + break; + } + default: + break; + } + }); + } + + initWebviewPanel( + document: vscode.TextDocument, + webviewPanel: vscode.WebviewPanel + ): void { + vscode.commands.executeCommand( + "setContext", + EdgeTPUCfgEditorPanel.viewType, + true + ); + + const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument( + (e) => { + if ( + e.contentChanges.length > 0 && + e.document.uri.toString() === document.uri.toString() + ) { + this.updateWebview(document, webviewPanel.webview); + } + } + ); + + webviewPanel.onDidChangeViewState( + () => { + if (webviewPanel.visible) { + this._activeWebviewPanel = webviewPanel; + this._activeDocument = document; + vscode.commands.executeCommand( + "one.explorer.revealInOneExplorer", + document.fileName + ); + } + vscode.commands.executeCommand( + "setContext", + EdgeTPUCfgEditorPanel.viewType, + webviewPanel.visible + ); + }, + null, + this._disposables + ); + + webviewPanel.onDidDispose(() => { + changeDocumentSubscription.dispose(); + while (this._disposables.length) { + const x = this._disposables.pop(); + if (x) { + x.dispose(); + } + } + vscode.commands.executeCommand( + "setContext", + EdgeTPUCfgEditorPanel.viewType, + false + ); + }); + } + + updateWebview(document: vscode.TextDocument, webview: vscode.Webview): void { + this._oneConfigMap[document.uri.toString()].setWithString( + document.getText() + ); + webview.postMessage({ + type: "displayCfgToEditor", + text: this._oneConfigMap[document.uri.toString()].getAsConfig(), + }); + } +} diff --git a/src/extension.ts b/src/extension.ts index 28220ecda..80e8a6e9b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,6 +19,7 @@ import * as vscode from "vscode"; import { API } from "./Backend/API"; import { OneToolchain } from "./Backend/One/OneToolchain"; import { CfgEditorPanel } from "./CfgEditor/CfgEditorPanel"; +import { EdgeTPUCfgEditorPanel } from "./CfgEditor/EdgeTPUCfgEditorPanel"; import { CircleEditorProvider } from "./CircleEditor/CircleEditorProvider"; import { CircleViewerProvider } from "./CircleGraph/CircleViewer"; import { DeviceViewProvider } from "./Execute/DeviceViewProvider"; @@ -65,6 +66,8 @@ export function activate(context: vscode.ExtensionContext) { CfgEditorPanel.register(context); + EdgeTPUCfgEditorPanel.register(context); + JsonTracerViewerPanel.register(context); MondrianEditorProvider.register(context);