diff --git a/src/quest_editor/scripting/AssemblyAnalyser.ts b/src/quest_editor/scripting/AssemblyAnalyser.ts index 1f6f7d36..09f73854 100644 --- a/src/quest_editor/scripting/AssemblyAnalyser.ts +++ b/src/quest_editor/scripting/AssemblyAnalyser.ts @@ -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 { - const id = this.message_id++; - - return new Promise((resolve, reject) => { - this.promises.set(id, { resolve, reject }); - const message: SignatureHelpInput = { + return await this.send_and_await_response( + "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 { + return await this.send_and_await_response( + "Definition provision", + id => ({ + type: InputMessageType.Definition, + id, + line_no, + col, + }), + ); } update_settings(changed_settings: Partial): void { @@ -143,6 +148,25 @@ export class AssemblyAnalyser implements Disposable { this.worker.terminate(); } + private async send_and_await_response( + name: string, + create_request: (id: number) => M, + ): Promise { + const id = this.message_id++; + + return new Promise((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; } }; } diff --git a/src/quest_editor/scripting/assembly_worker.ts b/src/quest_editor/scripting/assembly_worker.ts index 2428e94f..49fd1ab1 100644 --- a/src/quest_editor/scripting/assembly_worker.ts +++ b/src/quest_editor/scripting/assembly_worker.ts @@ -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. */ diff --git a/src/quest_editor/scripting/assembly_worker_messages.ts b/src/quest_editor/scripting/assembly_worker_messages.ts index bb6936dd..04ed52f9 100644 --- a/src/quest_editor/scripting/assembly_worker_messages.ts +++ b/src/quest_editor/scripting/assembly_worker_messages.ts @@ -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; @@ -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; +}; diff --git a/src/quest_editor/stores/AsmEditorStore.ts b/src/quest_editor/stores/AsmEditorStore.ts index 60b51dda..8643196b 100644 --- a/src/quest_editor/stores/AsmEditorStore.ts +++ b/src/quest_editor/stores/AsmEditorStore.ts @@ -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 { + 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());