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, AssemblyChangeInput,
AssemblySettingsChangeInput, AssemblySettingsChangeInput,
AssemblyWorkerOutput, AssemblyWorkerOutput,
DefinitionInput,
InputMessageType, InputMessageType,
NewAssemblyInput, NewAssemblyInput,
OutputMessageType, OutputMessageType,
@ -23,6 +24,7 @@ import CompletionItem = languages.CompletionItem;
import IModelContentChange = editor.IModelContentChange; import IModelContentChange = editor.IModelContentChange;
import SignatureHelp = languages.SignatureHelp; import SignatureHelp = languages.SignatureHelp;
import ParameterInformation = languages.ParameterInformation; import ParameterInformation = languages.ParameterInformation;
import LocationLink = languages.LocationLink;
const INSTRUCTION_SUGGESTIONS = OPCODES.filter(opcode => opcode != null).map(opcode => { const INSTRUCTION_SUGGESTIONS = OPCODES.filter(opcode => opcode != null).map(opcode => {
return ({ return ({
@ -111,24 +113,27 @@ export class AssemblyAnalyser implements Disposable {
} }
async provide_signature_help(line_no: number, col: number): Promise<SignatureHelp | undefined> { async provide_signature_help(line_no: number, col: number): Promise<SignatureHelp | undefined> {
const id = this.message_id++; return await this.send_and_await_response<SignatureHelpInput, SignatureHelp>(
"Signature help provision",
return new Promise<SignatureHelp>((resolve, reject) => { id => ({
this.promises.set(id, { resolve, reject });
const message: SignatureHelpInput = {
type: InputMessageType.SignatureHelp, type: InputMessageType.SignatureHelp,
id, id,
line_no, line_no,
col, col,
}; }),
this.worker.postMessage(message); );
}
setTimeout(() => { async provide_definition(line_no: number, col: number): Promise<LocationLink[]> {
if (this.promises.delete(id)) { return await this.send_and_await_response<DefinitionInput, LocationLink[]>(
reject(new Error("Signature help timed out.")); "Definition provision",
} id => ({
}, 5_000); type: InputMessageType.Definition,
}); id,
line_no,
col,
}),
);
} }
update_settings(changed_settings: Partial<AssemblySettings>): void { update_settings(changed_settings: Partial<AssemblySettings>): void {
@ -143,6 +148,25 @@ export class AssemblyAnalyser implements Disposable {
this.worker.terminate(); 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 => { private process_worker_message = (e: MessageEvent): void => {
const message: AssemblyWorkerOutput = e.data; const message: AssemblyWorkerOutput = e.data;
@ -158,6 +182,7 @@ export class AssemblyAnalyser implements Disposable {
this._issues.val = { warnings: message.warnings, errors: message.errors }; this._issues.val = { warnings: message.warnings, errors: message.errors };
} }
break; break;
case OutputMessageType.SignatureHelp: case OutputMessageType.SignatureHelp:
{ {
const promise = this.promises.get(message.id); const promise = this.promises.get(message.id);
@ -230,6 +255,18 @@ export class AssemblyAnalyser implements Disposable {
} }
} }
break; 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, AssemblyChangeInput,
AssemblySettingsChangeInput, AssemblySettingsChangeInput,
AssemblyWorkerInput, AssemblyWorkerInput,
DefinitionInput,
DefinitionOutput,
InputMessageType, InputMessageType,
NewObjectCodeOutput, NewObjectCodeOutput,
OutputMessageType, OutputMessageType,
@ -57,6 +59,9 @@ function process_messages(): void {
case InputMessageType.SignatureHelp: case InputMessageType.SignatureHelp:
signature_help(message); signature_help(message);
break; break;
case InputMessageType.Definition:
definition(message);
break;
case InputMessageType.SettingsChange: case InputMessageType.SettingsChange:
settings_change(message); settings_change(message);
break; break;
@ -138,6 +143,15 @@ function signature_help(message: SignatureHelpInput): void {
ctx.postMessage(response); 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. * Apply changes to settings.
*/ */

View File

@ -6,6 +6,7 @@ export enum InputMessageType {
NewAssembly, NewAssembly,
AssemblyChange, AssemblyChange,
SignatureHelp, SignatureHelp,
Definition,
SettingsChange, SettingsChange,
} }
@ -13,6 +14,7 @@ export type AssemblyWorkerInput =
| NewAssemblyInput | NewAssemblyInput
| AssemblyChangeInput | AssemblyChangeInput
| SignatureHelpInput | SignatureHelpInput
| DefinitionInput
| AssemblySettingsChangeInput; | AssemblySettingsChangeInput;
export type NewAssemblyInput = { export type NewAssemblyInput = {
@ -38,6 +40,13 @@ export type SignatureHelpInput = {
readonly col: number; readonly col: number;
}; };
export type DefinitionInput = {
readonly type: InputMessageType.Definition;
readonly id: number;
readonly line_no: number;
readonly col: number;
};
export type AssemblySettingsChangeInput = { export type AssemblySettingsChangeInput = {
readonly type: InputMessageType.SettingsChange; readonly type: InputMessageType.SettingsChange;
readonly settings: Partial<AssemblySettings>; readonly settings: Partial<AssemblySettings>;
@ -46,9 +55,10 @@ export type AssemblySettingsChangeInput = {
export enum OutputMessageType { export enum OutputMessageType {
NewObjectCode, NewObjectCode,
SignatureHelp, SignatureHelp,
Definition,
} }
export type AssemblyWorkerOutput = NewObjectCodeOutput | SignatureHelpOutput; export type AssemblyWorkerOutput = NewObjectCodeOutput | SignatureHelpOutput | DefinitionOutput;
export type NewObjectCodeOutput = { export type NewObjectCodeOutput = {
readonly type: OutputMessageType.NewObjectCode; readonly type: OutputMessageType.NewObjectCode;
@ -64,3 +74,8 @@ export type SignatureHelpOutput = {
readonly opcode?: Opcode; readonly opcode?: Opcode;
readonly active_param: number; 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 CompletionList = languages.CompletionList;
import IMarkerData = editor.IMarkerData; import IMarkerData = editor.IMarkerData;
import SignatureHelpResult = languages.SignatureHelpResult; import SignatureHelpResult = languages.SignatureHelpResult;
import LocationLink = languages.LocationLink;
const assembly_analyser = new AssemblyAnalyser(); 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 { export class AsmEditorStore implements Disposable {
private readonly disposer = new Disposer(); private readonly disposer = new Disposer();
private readonly model_disposer = this.disposer.add(new Disposer()); private readonly model_disposer = this.disposer.add(new Disposer());