Added the basic Monaco machinery for providing symbol definitions.

This commit is contained in:
Daan Vanden Bosch 2019-10-02 13:28:14 +02:00
parent 825f14dc90
commit 431c0545f2
4 changed files with 87 additions and 14 deletions

View File

@ -4,6 +4,7 @@ import {
AssemblyChangeInput,
AssemblySettingsChangeInput,
AssemblyWorkerOutput,
DefinitionInput,
InputMessageType,
NewAssemblyInput,
OutputMessageType,
@ -23,6 +24,7 @@ import CompletionItem = languages.CompletionItem;
import IModelContentChange = editor.IModelContentChange;
import SignatureHelp = languages.SignatureHelp;
import ParameterInformation = languages.ParameterInformation;
import LocationLink = languages.LocationLink;
const INSTRUCTION_SUGGESTIONS = OPCODES.filter(opcode => opcode != null).map(opcode => {
return ({
@ -111,24 +113,27 @@ export class AssemblyAnalyser implements Disposable {
}
async provide_signature_help(line_no: number, col: number): Promise<SignatureHelp | undefined> {
const id = this.message_id++;
return new Promise<SignatureHelp>((resolve, reject) => {
this.promises.set(id, { resolve, reject });
const message: SignatureHelpInput = {
return await this.send_and_await_response<SignatureHelpInput, SignatureHelp>(
"Signature help provision",
id => ({
type: InputMessageType.SignatureHelp,
id,
line_no,
col,
};
this.worker.postMessage(message);
}),
);
}
setTimeout(() => {
if (this.promises.delete(id)) {
reject(new Error("Signature help timed out."));
}
}, 5_000);
});
async provide_definition(line_no: number, col: number): Promise<LocationLink[]> {
return await this.send_and_await_response<DefinitionInput, LocationLink[]>(
"Definition provision",
id => ({
type: InputMessageType.Definition,
id,
line_no,
col,
}),
);
}
update_settings(changed_settings: Partial<AssemblySettings>): void {
@ -143,6 +148,25 @@ export class AssemblyAnalyser implements Disposable {
this.worker.terminate();
}
private async send_and_await_response<M, R>(
name: string,
create_request: (id: number) => M,
): Promise<R> {
const id = this.message_id++;
return new Promise<R>((resolve, reject) => {
this.promises.set(id, { resolve, reject });
const message: M = create_request(id);
this.worker.postMessage(message);
setTimeout(() => {
if (this.promises.delete(id)) {
reject(new Error(`${name} timed out.`));
}
}, 5_000);
});
}
private process_worker_message = (e: MessageEvent): void => {
const message: AssemblyWorkerOutput = e.data;
@ -158,6 +182,7 @@ export class AssemblyAnalyser implements Disposable {
this._issues.val = { warnings: message.warnings, errors: message.errors };
}
break;
case OutputMessageType.SignatureHelp:
{
const promise = this.promises.get(message.id);
@ -230,6 +255,18 @@ export class AssemblyAnalyser implements Disposable {
}
}
break;
case OutputMessageType.Definition:
{
const promise = this.promises.get(message.id);
if (promise) {
this.promises.delete(message.id);
// TODO: resolve LocationLinks
promise.resolve([]);
}
}
break;
}
};
}

View File

@ -2,6 +2,8 @@ import {
AssemblyChangeInput,
AssemblySettingsChangeInput,
AssemblyWorkerInput,
DefinitionInput,
DefinitionOutput,
InputMessageType,
NewObjectCodeOutput,
OutputMessageType,
@ -57,6 +59,9 @@ function process_messages(): void {
case InputMessageType.SignatureHelp:
signature_help(message);
break;
case InputMessageType.Definition:
definition(message);
break;
case InputMessageType.SettingsChange:
settings_change(message);
break;
@ -138,6 +143,15 @@ function signature_help(message: SignatureHelpInput): void {
ctx.postMessage(response);
}
function definition(message: DefinitionInput): void {
// TODO: provide definition
const response: DefinitionOutput = {
type: OutputMessageType.Definition,
id: message.id,
};
ctx.postMessage(response);
}
/**
* Apply changes to settings.
*/

View File

@ -6,6 +6,7 @@ export enum InputMessageType {
NewAssembly,
AssemblyChange,
SignatureHelp,
Definition,
SettingsChange,
}
@ -13,6 +14,7 @@ export type AssemblyWorkerInput =
| NewAssemblyInput
| AssemblyChangeInput
| SignatureHelpInput
| DefinitionInput
| AssemblySettingsChangeInput;
export type NewAssemblyInput = {
@ -38,6 +40,13 @@ export type SignatureHelpInput = {
readonly col: number;
};
export type DefinitionInput = {
readonly type: InputMessageType.Definition;
readonly id: number;
readonly line_no: number;
readonly col: number;
};
export type AssemblySettingsChangeInput = {
readonly type: InputMessageType.SettingsChange;
readonly settings: Partial<AssemblySettings>;
@ -46,9 +55,10 @@ export type AssemblySettingsChangeInput = {
export enum OutputMessageType {
NewObjectCode,
SignatureHelp,
Definition,
}
export type AssemblyWorkerOutput = NewObjectCodeOutput | SignatureHelpOutput;
export type AssemblyWorkerOutput = NewObjectCodeOutput | SignatureHelpOutput | DefinitionOutput;
export type NewObjectCodeOutput = {
readonly type: OutputMessageType.NewObjectCode;
@ -64,3 +74,8 @@ export type SignatureHelpOutput = {
readonly opcode?: Opcode;
readonly active_param: number;
};
export type DefinitionOutput = {
readonly type: OutputMessageType.Definition;
readonly id: number;
};

View File

@ -14,6 +14,7 @@ import ITextModel = editor.ITextModel;
import CompletionList = languages.CompletionList;
import IMarkerData = editor.IMarkerData;
import SignatureHelpResult = languages.SignatureHelpResult;
import LocationLink = languages.LocationLink;
const assembly_analyser = new AssemblyAnalyser();
@ -69,6 +70,12 @@ languages.setLanguageConfiguration("psoasm", {
},
});
languages.registerDefinitionProvider("psoasm", {
provideDefinition(_model: ITextModel, position: Position): Promise<LocationLink[]> {
return assembly_analyser.provide_definition(position.lineNumber, position.column);
},
});
export class AsmEditorStore implements Disposable {
private readonly disposer = new Disposer();
private readonly model_disposer = this.disposer.add(new Disposer());