blob: 1da3fdabbb3b8d3dc1cf90d9a19b992a03720f29 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
import * as vscode from 'vscode'
import { getNonce } from './utilities/getNonce'
import { printChannelOutput } from './extension'
import { newTestCaseInput } from './addNewTest'
import { AppConstants } from './utilities/constants'
import { getTestCaseDisplayData } from './utilities/tdmlXmlUtils'
export class TDMLProvider implements vscode.CustomTextEditorProvider {
public static register(context: vscode.ExtensionContext): vscode.Disposable {
const provider = new TDMLProvider(context)
const providerRegistration = vscode.window.registerCustomEditorProvider(
TDMLProvider.viewType,
provider
)
printChannelOutput('TDML Editor custom editor provider registered.', true)
return providerRegistration
}
public static getDocumentUri(): vscode.Uri | undefined {
return TDMLProvider.currentUri
}
private static readonly viewType = AppConstants.viewTypeId
private registered = false
private currentPanel: vscode.WebviewPanel | undefined = undefined
private static currentUri: vscode.Uri | undefined = undefined
constructor(private readonly context: vscode.ExtensionContext) {}
public async resolveCustomTextEditor(
document: vscode.TextDocument,
webviewPanel: vscode.WebviewPanel,
_token: vscode.CancellationToken
): Promise<void> {
this.currentPanel = webviewPanel
webviewPanel.webview.options = {
enableScripts: true,
localResourceRoots: [
vscode.Uri.joinPath(this.context.extensionUri, 'src/tdmlEditor/media'),
vscode.Uri.joinPath(
this.context.extensionUri,
'dist/views/tdmlEditor/webview'
),
],
}
webviewPanel.webview.html = this._getWebviewContent(webviewPanel.webview)
webviewPanel.onDidChangeViewState((e) => {
this.currentPanel = e.webviewPanel
// Create a custom context key 'dfdl-debug.tdml-editor-active' to diplay appropriate commands on menu/editor/title bar and command pallet.
if (e.webviewPanel.active) {
TDMLProvider.currentUri = document.uri
vscode.commands.executeCommand(
'setContext',
'dfdl-debug.tdml-editor-active',
TDMLProvider.viewType
)
} else if (
TDMLProvider.currentUri?.toString() === document.uri.toString()
) {
TDMLProvider.currentUri = undefined
vscode.commands.executeCommand(
'setContext',
'dfdl-debug.tdml-editor-active',
undefined
)
}
})
if (webviewPanel.active) {
TDMLProvider.currentUri = document.uri
vscode.commands.executeCommand(
'setContext',
'dfdl-debug.tdml-editor-active',
TDMLProvider.viewType
)
}
try {
printChannelOutput(document.uri.toString(), true)
if (!this.registered) {
this.registered = true
let deleteCommand = vscode.commands.registerCommand(
AppConstants.deleteTestCommand,
() => {
this.currentPanel?.webview.postMessage({
type: 'delete',
})
}
)
let addCommand = vscode.commands.registerCommand(
AppConstants.addNewTestCommand,
() => {
// get all the inputs we need
const inputs = newTestCaseInput(this.context)
// then do something with them
inputs.then((result) => {
this.currentPanel?.webview.postMessage({
type: 'add',
testCaseName: result.testName,
testCaseModel: result.testDesc,
testCaseDescription: result.testModel,
dataDocuments: result.dfdlInfoset,
dfdlInfosets: result.dataDocs,
})
})
}
)
let openInTextEditorCommand = vscode.commands.registerCommand(
AppConstants.openInTextEditorCommand,
() => {
printChannelOutput('openInTextEditor command called', true)
vscode.commands.executeCommand(
'workbench.action.reopenTextEditor',
document?.uri
)
}
)
this.context.subscriptions.push(openInTextEditorCommand)
this.context.subscriptions.push(deleteCommand)
this.context.subscriptions.push(addCommand)
}
} catch (e) {
console.log(e)
}
async function updateWebview() {
webviewPanel.webview.postMessage({
type: 'update',
text: await getTestCaseDisplayData(document.getText()),
})
}
const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument(
(e) => {
if (e.document.uri.toString() === document.uri.toString()) {
updateWebview()
}
}
)
webviewPanel.onDidDispose(() => {
changeDocumentSubscription.dispose()
if (TDMLProvider.currentUri?.toString() === document.uri.toString()) {
TDMLProvider.currentUri = undefined
vscode.commands.executeCommand(
'setContext',
'dfdl-debug.tdml-editor-active',
undefined
)
}
})
webviewPanel.webview.onDidReceiveMessage((e) => {
switch (e.type) {
case 'update':
this.updateTextDocument(document, e.json)
return
case 'log':
printChannelOutput(e.message, true)
return
case 'error':
printChannelOutput(e.message, true)
vscode.window.showErrorMessage(e.message)
return
case 'info':
printChannelOutput(e.message, true)
vscode.window.showInformationMessage(e.message)
return
case 'add':
vscode.commands.executeCommand(AppConstants.addNewTestCommand)
return
}
})
updateWebview()
}
private async updateTextDocument(document: vscode.TextDocument, json: any) {
const edit = new vscode.WorkspaceEdit()
return vscode.workspace.applyEdit(edit)
}
private _getWebviewContent(webview: vscode.Webview) {
const webviewUri = webview.asWebviewUri(
vscode.Uri.joinPath(
this.context.extensionUri,
'dist/views/tdmlEditor/webview',
'webview.js'
)
)
const nonce = getNonce()
return /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; img-src ${webview.cspSource} https:; script-src 'nonce-${nonce}'; style-src ${webview.cspSource} 'nonce-${nonce}'; style-src-elem ${webview.cspSource} 'unsafe-inline'; font-src ${webview.cspSource};"
/>
<link rel="stylesheet" nonce="${nonce}">
</head>
<body>
<h2>TDML Test Cases</h2><br>
<vscode-data-grid id="TDML-table" aria-label="Basic" generate-header="sticky" aria-label="Sticky Header"></vscode-data-grid>
<script type="module" nonce="${nonce}" src="${webviewUri}"></script>
</body>
</html>
`
}
}