* Implements languageId support

* Implements typing of helper functions
* Shift+F1 opens a new debug visualizer window if none is opened yet
This commit is contained in:
Henning Dieterichs
2020-03-29 15:16:46 +02:00
parent 213f4cda8f
commit 42e58ce9cf
14 changed files with 158 additions and 50 deletions

View File

@@ -20,7 +20,7 @@ export class ClientConnection {
private readonly client: typeof debugVisualizerUIContract["TClientInterface"];
constructor(
dataSource: EvaluationWatchService,
evaluationWatchService: EvaluationWatchService,
stream: WebSocketStream,
server: Server,
config: Config,
@@ -65,9 +65,12 @@ export class ClientConnection {
this.dispose.untrack(this.watcher).dispose();
}
this.watcher = this.dispose.track(
dataSource.createEvaluationWatcher(newExpression, {
preferredDataExtractor: oldPreferredDataExtractor,
})
evaluationWatchService.createEvaluationWatcher(
newExpression,
{
preferredDataExtractor: oldPreferredDataExtractor,
}
)
);
},
openInBrowser: async ({}) => {
@@ -98,7 +101,7 @@ export class ClientConnection {
getCompletions: async ({ text, column }) => {
throwIfNotAuthenticated();
const completions = await dataSource.getCompletions(
const completions = await evaluationWatchService.getCompletions(
text,
column
);
@@ -111,7 +114,7 @@ export class ClientConnection {
this.client = client;
this.dispose.track(
this.dispose.track([
Disposable.create(
autorun(() => {
if (this.watcher) {
@@ -120,8 +123,15 @@ export class ClientConnection {
});
}
})
)
);
),
Disposable.create(
autorun(() => {
client.updateLanguageId({
languageId: evaluationWatchService.languageId || null,
});
})
),
]);
stream.onClosed.then(() => {
this.dispose();

View File

@@ -16,6 +16,11 @@ export interface Evaluator {
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: FormattedMessage }
>;
/**
* The language that expressions must be written in.
*/
readonly languageId: string | undefined;
}
export interface EvaluationArgs {

View File

@@ -22,6 +22,8 @@ export class GenericEvaluationEngine implements EvaluationEngine {
}
export class GenericEvaluator implements Evaluator {
public readonly languageId = "text";
constructor(private readonly session: VsCodeDebugSession) {}
public async evaluate({

View File

@@ -33,6 +33,8 @@ export class JsEvaluationEngine implements EvaluationEngine {
}
class JsEvaluator implements Evaluator {
public readonly languageId = "javascript";
constructor(private readonly session: VsCodeDebugSession) {}
public async evaluate({

View File

@@ -8,6 +8,13 @@ export interface EvaluationWatchService {
): EvaluationWatcher;
getCompletions(text: string, column: number): Promise<CompletionItem[]>;
/**
* The language the expressions must be written in.
* `undefined`, if unknown.
* This field is observable.
*/
readonly languageId: string | undefined;
}
export interface EvaluationWatcherOptions {

View File

@@ -18,7 +18,7 @@ export class EvaluationWatchServiceImpl implements EvaluationWatchService {
constructor(
private readonly vsCodeDebuggerView: VsCodeDebuggerView,
private readonly dataExtractionProviderFactory: EvaluationEngine
private readonly evaluationEngine: EvaluationEngine
) {
this.dispose.track({
dispose: autorun(() => {
@@ -48,6 +48,21 @@ export class EvaluationWatchServiceImpl implements EvaluationWatchService {
this.watchers.delete(w);
}
private lastLanguageId: string | undefined = undefined;
get languageId(): string | undefined {
const session = this.vsCodeDebuggerView.activeDebugSession;
if (!session) {
return this.lastLanguageId;
}
const evaluator = this.evaluationEngine.createEvaluator(session);
if (!evaluator) {
return this.lastLanguageId;
}
this.lastLanguageId = evaluator.languageId;
return evaluator.languageId;
}
public async refresh(w: ObservableEvaluationWatcher): Promise<void> {
const session = this.vsCodeDebuggerView.activeDebugSession;
if (!session) {
@@ -59,10 +74,8 @@ export class EvaluationWatchServiceImpl implements EvaluationWatchService {
w._state = { kind: "loading" };
const extractionProvider = this.dataExtractionProviderFactory.createEvaluator(
session
);
if (!extractionProvider) {
const evaluator = this.evaluationEngine.createEvaluator(session);
if (!evaluator) {
w._state = {
kind: "error",
message: `The debug adapter "${session.session.type}" is not supported.`,
@@ -70,7 +83,7 @@ export class EvaluationWatchServiceImpl implements EvaluationWatchService {
return;
}
const result = await extractionProvider.evaluate({
const result = await evaluator.evaluate({
expression: w.expression,
frameId,
preferredExtractorId: w.preferredDataExtractor,

View File

@@ -27,7 +27,7 @@ export class WebViews {
});
}
public createNew() {
public createNew(expression: string | undefined = undefined) {
const panel = window.createWebviewPanel(
debugVisualizer,
"Debug Visualizer",
@@ -35,15 +35,18 @@ export class WebViews {
{ enableScripts: true }
);
this.setupView(panel);
this.setupView(panel, expression);
}
public restore(webviewPanel: WebviewPanel) {
this.setupView(webviewPanel);
}
private setupView(webviewPanel: WebviewPanel) {
webviewPanel.webview.html = getHtml(this.server);
private setupView(
webviewPanel: WebviewPanel,
expression: string | undefined = undefined
) {
webviewPanel.webview.html = getHtml(this.server, expression);
const view = new WebView(webviewPanel);
this.debugVisualizations.set(webviewPanel, view);
webviewPanel.onDidDispose(() => {
@@ -56,7 +59,10 @@ export class WebView {
constructor(private readonly webviewPanel: WebviewPanel) {}
}
export function getHtml(server: Server) {
export function getHtml(
server: Server,
expression: string | undefined = undefined
) {
const isDev = !!process.env.USE_DEV_UI;
return `
<html>
@@ -75,6 +81,7 @@ export function getHtml(server: Server) {
serverSecret: server.secret,
serverPort: server.port,
publicPath: server.publicPath,
expression,
})};
const api = window.VsCodeApi = acquireVsCodeApi();
window.addEventListener('message', event => {
@@ -94,7 +101,7 @@ export function getHtml(server: Server) {
${
isDev
? `<iframe sandbox="allow-top-navigation allow-scripts allow-same-origin allow-popups allow-pointer-lock allow-forms" src="${server.getIndexUrl(
{ mode: "webViewIFrame" }
{ mode: "webViewIFrame", expression }
)}"></iframe>`
: `<script type="text/javascript" src="${server.mainBundleUrl}"></script>`
}

View File

@@ -100,6 +100,11 @@ export const debugVisualizerUIContract = contract({
newState: unchecked<DataExtractionState>(),
}),
}),
updateLanguageId: notificationContract({
params: types.type({
languageId: types.union([types.null, types.string]),
}),
}),
setExpression: requestContract({
params: types.type({
expression: types.string,

View File

@@ -85,8 +85,7 @@ export class Extension {
latestConnection.setExpression(selectedText);
} else {
// TODO pass expression
// this.views.createNew();
this.views.createNew(selectedText);
}
}
)