@difizen/libro-language-client 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/es/common/codeConverter.d.ts +15 -1
  2. package/es/common/codeConverter.d.ts.map +1 -1
  3. package/es/common/codeConverter.js +122 -8
  4. package/es/common/protocolConverter.d.ts +3 -1
  5. package/es/common/protocolConverter.d.ts.map +1 -1
  6. package/es/common/protocolConverter.js +85 -2
  7. package/es/common/vscodeAdaptor/convertor.d.ts.map +1 -1
  8. package/es/common/vscodeAdaptor/convertor.js +5 -4
  9. package/es/common/vscodeAdaptor/libroWorkspace.d.ts +3 -2
  10. package/es/common/vscodeAdaptor/libroWorkspace.d.ts.map +1 -1
  11. package/es/common/vscodeAdaptor/libroWorkspace.js +21 -5
  12. package/es/common/vscodeAdaptor/monacoLanguages.d.ts +3 -0
  13. package/es/common/vscodeAdaptor/monacoLanguages.d.ts.map +1 -1
  14. package/es/common/vscodeAdaptor/monacoLanguages.js +256 -68
  15. package/es/index.d.ts +1 -0
  16. package/es/index.d.ts.map +1 -1
  17. package/es/index.js +2 -1
  18. package/es/libro-language-client-contribution.d.ts +4 -0
  19. package/es/libro-language-client-contribution.d.ts.map +1 -1
  20. package/es/libro-language-client-contribution.js +108 -30
  21. package/es/libro-language-client-manager.d.ts +4 -0
  22. package/es/libro-language-client-manager.d.ts.map +1 -1
  23. package/es/libro-language-client-manager.js +24 -11
  24. package/es/util.d.ts +9 -0
  25. package/es/util.d.ts.map +1 -0
  26. package/es/util.js +32 -0
  27. package/package.json +7 -6
  28. package/src/common/codeConverter.ts +133 -1
  29. package/src/common/protocolConverter.ts +66 -0
  30. package/src/common/vscodeAdaptor/convertor.ts +5 -4
  31. package/src/common/vscodeAdaptor/libroWorkspace.ts +16 -4
  32. package/src/common/vscodeAdaptor/monacoLanguages.ts +114 -6
  33. package/src/index.ts +1 -0
  34. package/src/libro-language-client-contribution.ts +88 -6
  35. package/src/libro-language-client-manager.ts +9 -1
  36. package/src/util.ts +43 -0
@@ -34,6 +34,8 @@ import type {
34
34
  TextDocument,
35
35
  MarkdownString as VMarkdownString,
36
36
  SemanticTokens as VSemanticTokens,
37
+ SignatureHelpContext,
38
+ CodeActionContext,
37
39
  } from 'vscode';
38
40
  import { URI } from 'vscode-uri';
39
41
 
@@ -82,6 +84,8 @@ import {
82
84
  MarkdownString,
83
85
  SemanticTokens,
84
86
  LinkedEditingRanges,
87
+ SignatureHelpTriggerKind,
88
+ CodeActionTriggerKind,
85
89
  } from './vscodeAdaptor/vscodeAdaptor.js';
86
90
  import {
87
91
  DiagnosticRelatedInformation,
@@ -603,6 +607,14 @@ export interface Converter {
603
607
  // new
604
608
 
605
609
  asTextDcouemnt(value: ls.TextDocumentIdentifier): TextDocument;
610
+ asSignatureHelpContext(
611
+ context: ls.SignatureHelpContext,
612
+ ): Promise<SignatureHelpContext>;
613
+
614
+ asCodeActionContext(
615
+ context: ls.CodeActionContext,
616
+ diagnostics: ls.Diagnostic[],
617
+ ): Promise<CodeActionContext>;
606
618
  }
607
619
 
608
620
  export interface URIConverter {
@@ -2545,6 +2557,58 @@ export function createConverter(
2545
2557
  } as TextDocument;
2546
2558
  }
2547
2559
 
2560
+ function asSignatureHelpTriggerKind(
2561
+ triggerKind: ls.SignatureHelpTriggerKind,
2562
+ ): SignatureHelpTriggerKind {
2563
+ switch (triggerKind) {
2564
+ case ls.SignatureHelpTriggerKind.ContentChange:
2565
+ return SignatureHelpTriggerKind.ContentChange;
2566
+ case ls.SignatureHelpTriggerKind.TriggerCharacter:
2567
+ return SignatureHelpTriggerKind.TriggerCharacter;
2568
+ default:
2569
+ return SignatureHelpTriggerKind.Invoke;
2570
+ }
2571
+ }
2572
+
2573
+ async function asSignatureHelpContext(
2574
+ context: ls.SignatureHelpContext,
2575
+ ): Promise<SignatureHelpContext> {
2576
+ const active = await asSignatureHelp(context.activeSignatureHelp);
2577
+ return {
2578
+ triggerKind: asSignatureHelpTriggerKind(context.triggerKind),
2579
+ triggerCharacter: context.triggerCharacter,
2580
+ isRetrigger: context.isRetrigger,
2581
+ activeSignatureHelp: active,
2582
+ };
2583
+ }
2584
+
2585
+ function asCodeActionTriggerKind(
2586
+ trigger?: ls.CodeActionTriggerKind,
2587
+ ): CodeActionTriggerKind {
2588
+ switch (trigger) {
2589
+ case ls.CodeActionTriggerKind.Automatic:
2590
+ return CodeActionTriggerKind.Automatic;
2591
+ case ls.CodeActionTriggerKind.Invoked:
2592
+ return CodeActionTriggerKind.Invoke;
2593
+ default:
2594
+ return CodeActionTriggerKind.Invoke;
2595
+ }
2596
+ }
2597
+
2598
+ async function asCodeActionContext(
2599
+ context: ls.CodeActionContext,
2600
+ diagnostics: ls.Diagnostic[],
2601
+ ): Promise<CodeActionContext> {
2602
+ if (context === void 0 || context === null) {
2603
+ return context;
2604
+ }
2605
+ return {
2606
+ diagnostics: await asDiagnostics(diagnostics),
2607
+ only: context.only?.[0] ? asCodeActionKind(context.only[0]) : undefined,
2608
+ triggerKind: asCodeActionTriggerKind(context.triggerKind),
2609
+ };
2610
+ }
2611
+
2548
2612
  return {
2549
2613
  asUri,
2550
2614
  asDocumentSelector,
@@ -2623,5 +2687,7 @@ export function createConverter(
2623
2687
  asInlineCompletionItem,
2624
2688
  // new
2625
2689
  asTextDcouemnt,
2690
+ asSignatureHelpContext,
2691
+ asCodeActionContext,
2626
2692
  };
2627
2693
  }
@@ -1,4 +1,5 @@
1
1
  import type { CellView, LibroView } from '@difizen/libro-core';
2
+ import { ExecutableNotebookModel } from '@difizen/libro-kernel';
2
3
  import type { NotebookCell, NotebookDocument, NotebookRange } from 'vscode';
3
4
 
4
5
  import { NotebookDocumentSyncFeature } from '../notebook.js';
@@ -9,14 +10,14 @@ import { EndOfLine, NotebookCellKind, Uri } from './vscodeAdaptor.js';
9
10
  export const l2c = {
10
11
  asNotebookDocument(libroView: LibroView): NotebookDocument {
11
12
  const model = libroView.model as any;
12
- if (model.filePath === undefined) {
13
- throw new Error('no filePath: invalid libro jupyter model');
13
+ if (!ExecutableNotebookModel.is(model)) {
14
+ throw new Error('invalid libro jupyter model');
14
15
  }
15
16
  const filePath = model.filePath as string;
16
17
  return {
17
18
  uri: Uri.parse(filePath),
18
19
  notebookType: 'jupyter',
19
- version: 0,
20
+ version: libroView.model.version,
20
21
  isDirty: libroView.model.dirty,
21
22
  isUntitled: false,
22
23
  isClosed: false,
@@ -49,7 +50,7 @@ export const l2c = {
49
50
  fileName: filePath,
50
51
  isUntitled: false,
51
52
  languageId: 'python',
52
- version: 0,
53
+ version: cell.model.version,
53
54
  isDirty: false,
54
55
  isClosed: false,
55
56
  save: unsupported,
@@ -1,7 +1,9 @@
1
1
  import type { LibroView } from '@difizen/libro-core';
2
- import { LibroService } from '@difizen/libro-core';
2
+ import { LibroService, ILibroWorkspaceService } from '@difizen/libro-core';
3
+ import { ExecutableNotebookModel } from '@difizen/libro-kernel';
3
4
  import { inject, noop, singleton } from '@difizen/mana-app';
4
5
  import type {
6
+ Uri,
5
7
  NotebookDocument,
6
8
  WorkspaceFolder,
7
9
  Event,
@@ -22,10 +24,10 @@ import type {
22
24
  FileWillCreateEvent,
23
25
  GlobPattern,
24
26
  FileSystemWatcher,
25
- Uri,
26
27
  TextDocument,
27
28
  FileSystem,
28
29
  } from 'vscode';
30
+ import { URI } from 'vscode-uri';
29
31
 
30
32
  import { l2c } from './convertor.js';
31
33
  import { Range } from './extHostTypes.js';
@@ -37,15 +39,25 @@ import { unsupported } from './util.js';
37
39
  @singleton({ token: ILibroWorkspace })
38
40
  export class LibroWorkspace implements ILibroWorkspace {
39
41
  @inject(LibroService) private readonly libroService: LibroService;
42
+ @inject(ILibroWorkspaceService)
43
+ private readonly libroWorkspaceService: ILibroWorkspaceService;
40
44
 
41
45
  isValidNotebook(view: LibroView): boolean {
42
- if ((view.model as any).lspEnabled === true) {
46
+ if (ExecutableNotebookModel.is(view.model)) {
43
47
  return true;
44
48
  }
45
49
  return false;
46
50
  }
47
51
 
48
- workspaceFolders: WorkspaceFolder[] | undefined = [];
52
+ get workspaceFolders(): WorkspaceFolder[] | undefined {
53
+ return [
54
+ {
55
+ index: 0,
56
+ uri: URI.parse(this.libroWorkspaceService.workspaceRoot.toString()),
57
+ name: '',
58
+ },
59
+ ];
60
+ }
49
61
  getWorkspaceFolder(uri: Uri): WorkspaceFolder | undefined {
50
62
  return;
51
63
  }
@@ -95,12 +95,62 @@ export class MonacoLanguages implements IMonacoLanguages {
95
95
  provider: CodeActionProvider,
96
96
  metadata?: CodeActionProviderMetadata,
97
97
  ): Disposable {
98
+ const codeActionProvider = this.createCodeActionProvider(provider);
99
+ return monaco.languages.registerCodeActionProvider(selector, codeActionProvider);
100
+ }
101
+
102
+ protected createCodeActionProvider(
103
+ provider: CodeActionProvider,
104
+ ): monaco.languages.CodeActionProvider {
98
105
  return {
99
- dispose: () => {
100
- return;
106
+ provideCodeActions: async (model, range, context, token) => {
107
+ /**
108
+ * This few lines of code are greatly inspired from https://github.com/microsoft/vscode/blob/e9393b096d90a5ac49b1528d1ec60483fc6b993e/src/vs/workbench/api/common/extHostLanguageFeatures.ts#L400
109
+ */
110
+ // const allDiagnostics: Diagnostic[] = [];
111
+ // for (const diagnostic of this.extHostDiagnostics.getDiagnostics(
112
+ // model.uri.toString(),
113
+ // )) {
114
+ // if (range.intersectRanges(this.p2m.asRange(diagnostic.range))) {
115
+ // const newLen = allDiagnostics.push(diagnostic);
116
+ // if (newLen > MonacoLanguages._maxCodeActionsPerFile) {
117
+ // break;
118
+ // }
119
+ // }
120
+ // }
121
+
122
+ const params = this.m2p.asCodeActionParams(model, range, context, []);
123
+ const result = await provider.provideCodeActions(
124
+ this.p2c.asTextDcouemnt(params.textDocument),
125
+ this.p2c.asRange(params.range),
126
+ await this.p2c.asCodeActionContext(
127
+ this.m2p.asCodeActionContext(context, []),
128
+ [],
129
+ ),
130
+ token,
131
+ );
132
+ return (
133
+ result && this.p2m.asCodeActionList(await this.c2p.asCodeActionList(result))
134
+ );
101
135
  },
136
+ resolveCodeAction: provider.resolveCodeAction
137
+ ? async (codeAction, token) => {
138
+ const params = await this.p2c.asCodeAction(
139
+ this.m2p.asCodeAction(codeAction),
140
+ );
141
+ const result = await provider.resolveCodeAction?.(params, token);
142
+ if (result) {
143
+ const resolvedCodeAction = this.p2m.asCodeAction(
144
+ await this.c2p.asCodeAction(result),
145
+ );
146
+ overrideWithResolvedValue(codeAction, resolvedCodeAction);
147
+ }
148
+ return codeAction;
149
+ }
150
+ : undefined,
102
151
  };
103
152
  }
153
+
104
154
  registerCodeLensProvider(
105
155
  selector: DocumentSelector,
106
156
  provider: CodeLensProvider,
@@ -115,9 +165,25 @@ export class MonacoLanguages implements IMonacoLanguages {
115
165
  selector: DocumentSelector,
116
166
  provider: DefinitionProvider,
117
167
  ): Disposable {
168
+ return monaco.languages.registerDefinitionProvider(
169
+ selector,
170
+ this.createDefinitionProvider(provider),
171
+ );
172
+ }
173
+ protected createDefinitionProvider(
174
+ provider: DefinitionProvider,
175
+ ): monaco.languages.DefinitionProvider {
118
176
  return {
119
- dispose: () => {
120
- return;
177
+ provideDefinition: async (model, position, token) => {
178
+ const params = this.m2p.asTextDocumentPositionParams(model, position);
179
+ const result = await provider.provideDefinition(
180
+ { uri: model.uri } as any,
181
+ this.p2c.asPosition(params.position),
182
+ token,
183
+ );
184
+ return (
185
+ result && this.p2m.asDefinitionResult(this.c2p.asDefinitionResult(result))
186
+ );
121
187
  },
122
188
  };
123
189
  }
@@ -332,12 +398,54 @@ export class MonacoLanguages implements IMonacoLanguages {
332
398
  firstItem?: string | SignatureHelpProviderMetadata,
333
399
  ...remaining: string[]
334
400
  ): Disposable {
401
+ const signatureHelpProvider = this.createSignatureHelpProvider(
402
+ provider,
403
+ firstItem,
404
+ ...remaining,
405
+ );
406
+ return monaco.languages.registerSignatureHelpProvider(
407
+ selector,
408
+ signatureHelpProvider,
409
+ );
410
+ }
411
+
412
+ protected createSignatureHelpProvider(
413
+ provider: SignatureHelpProvider,
414
+ firstItem?: string | SignatureHelpProviderMetadata,
415
+ ...remaining: string[]
416
+ ): monaco.languages.SignatureHelpProvider {
417
+ let triggerCharacters: string[] = [];
418
+ let retriggerCharacters: string[] = [];
419
+ if (typeof firstItem === 'string') {
420
+ triggerCharacters = [firstItem, ...remaining];
421
+ } else {
422
+ retriggerCharacters = [...(firstItem?.retriggerCharacters ?? [])];
423
+ triggerCharacters = [...(firstItem?.triggerCharacters ?? [])];
424
+ }
425
+ // const signatureHelpTriggerCharacters = [
426
+ // ...(provider.triggerCharacters || triggerCharacters || []),
427
+ // ];
335
428
  return {
336
- dispose: () => {
337
- return;
429
+ signatureHelpTriggerCharacters: triggerCharacters,
430
+ signatureHelpRetriggerCharacters: retriggerCharacters,
431
+ provideSignatureHelp: async (model, position, token, context) => {
432
+ const params = this.m2p.asTextDocumentPositionParams(model, position);
433
+ const signatureHelp = await provider.provideSignatureHelp(
434
+ this.p2c.asTextDcouemnt(params.textDocument),
435
+ this.p2c.asPosition(params.position),
436
+ token,
437
+ await this.p2c.asSignatureHelpContext(
438
+ this.m2p.asSignatureHelpContext(context),
439
+ ),
440
+ );
441
+ return (
442
+ signatureHelp &&
443
+ this.p2m.asSignatureHelpResult(this.c2p.asSignatureHelpResult(signatureHelp))
444
+ );
338
445
  },
339
446
  };
340
447
  }
448
+
341
449
  registerCompletionItemProvider(
342
450
  selector: DocumentSelector,
343
451
  provider: CompletionItemProvider,
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@ export * from './libro-language-client.js';
3
3
  export * from './module.js';
4
4
  export * from './common/api.js';
5
5
  export * from './constants.js';
6
+ export * from './util.js';
@@ -1,24 +1,41 @@
1
+ import {
2
+ EditorCellView,
3
+ ILibroWorkspaceService,
4
+ LibroService,
5
+ } from '@difizen/libro-core';
6
+ import { ExecutableNotebookModel } from '@difizen/libro-kernel';
1
7
  import { ApplicationContribution, inject, singleton } from '@difizen/mana-app';
8
+ import * as monaco from '@difizen/monaco-editor-core';
9
+ import { URI } from 'vscode-uri';
2
10
 
3
11
  import { CloseAction, ErrorAction } from './common/api.js';
4
12
  import { LSPEnv } from './common/vscodeAdaptor/lspEnv.js';
5
13
  import { workspace } from './common/vscodeAdaptor/vscodeAdaptor.js';
6
14
  import { LibroLanguageClientManager } from './libro-language-client-manager.js';
15
+ import { getCellURI, toEditorRange, toMonacoPosition } from './util.js';
7
16
 
8
17
  @singleton({ contrib: [ApplicationContribution] })
9
18
  export class LibroLanguageClientContribution implements ApplicationContribution {
19
+ @inject(ILibroWorkspaceService)
20
+ protected readonly libroWorkspaceService: ILibroWorkspaceService;
10
21
  @inject(LibroLanguageClientManager)
11
22
  protected readonly libroLanguageClientManager: LibroLanguageClientManager;
12
23
 
13
24
  @inject(LSPEnv)
14
25
  protected readonly lspEnv: LSPEnv;
15
26
 
27
+ @inject(LibroService)
28
+ protected readonly libroService: LibroService;
29
+
16
30
  async onViewStart() {
17
31
  // not block
18
32
  this.startLanguageClients();
33
+ this.setupEditorOpener();
19
34
  }
20
35
 
21
36
  async startLanguageClients() {
37
+ // wait for workspaceFolder
38
+ await this.libroWorkspaceService.ready;
22
39
  await this.lspEnv.ready;
23
40
  const serverIds = await this.libroLanguageClientManager.getServers();
24
41
 
@@ -33,17 +50,82 @@ export class LibroLanguageClientContribution implements ApplicationContribution
33
50
  error: () => ({ action: ErrorAction.Continue }),
34
51
  closed: () => ({ action: CloseAction.DoNotRestart }),
35
52
  },
36
- // pyright requires a workspace folder to be present, otherwise it will not work
37
- // workspaceFolder: {
38
- // index: 0,
39
- // name: 'workspace',
40
- // uri: URI.parse('/examples'), // abs path
41
- // },
42
53
  synchronize: {
43
54
  fileEvents: [workspace.createFileSystemWatcher('**', false)],
44
55
  },
45
56
  },
46
57
  });
47
58
  }
59
+
60
+ this.libroLanguageClientManager
61
+ .getFeatureStatus('textDocument/formatting')
62
+ .then((status) => {
63
+ this.libroService.hasFormatter = status;
64
+ return;
65
+ })
66
+ .catch(() => {
67
+ return;
68
+ });
69
+ }
70
+
71
+ setupEditorOpener() {
72
+ monaco.editor.registerEditorOpener({
73
+ openCodeEditor: (source, resource, selectionOrPosition) => {
74
+ // simulate openening a new browser tab for our own type (open definition of alert)
75
+ const model = monaco.editor.getModel(resource);
76
+ if (model?.id === source.getModel()?.id) {
77
+ return true;
78
+ }
79
+ const libroView = Array.from(this.libroService.getViewCache().values()).find(
80
+ (item) => {
81
+ return (
82
+ ExecutableNotebookModel.is(item.model) &&
83
+ URI.parse(item.model.filePath).path === resource.path
84
+ );
85
+ },
86
+ );
87
+
88
+ if (!libroView) {
89
+ return false;
90
+ }
91
+
92
+ const cell = libroView.model.cells.find((item) => {
93
+ return (
94
+ ExecutableNotebookModel.is(libroView.model) &&
95
+ getCellURI(libroView.model, item.model).toString() ===
96
+ decodeURIComponent(resource.toString())
97
+ );
98
+ });
99
+
100
+ if (EditorCellView.is(cell)) {
101
+ libroView.selectCell(cell);
102
+ cell.editor?.focus();
103
+ let line = 0;
104
+ if (monaco.Range.isIRange(selectionOrPosition)) {
105
+ cell.editor?.revealSelection(toEditorRange(selectionOrPosition));
106
+ cell.editor?.setCursorPosition(toEditorRange(selectionOrPosition).start);
107
+ line = toEditorRange(selectionOrPosition).start.line;
108
+ } else {
109
+ cell.editor?.setCursorPosition(toMonacoPosition(selectionOrPosition));
110
+ line = toMonacoPosition(selectionOrPosition).line;
111
+ }
112
+ libroView.model.scrollToView(cell, (line ?? 0) * 20);
113
+ return false;
114
+ }
115
+
116
+ // alternatively set model directly in the editor if you have your own tab/navigation implementation
117
+ // const model = monaco.editor.getModel(resource);
118
+ // editor.setModel(model);
119
+ // if (monaco.Range.isIRange(selectionOrPosition)) {
120
+ // editor.revealRangeInCenterIfOutsideViewport(selectionOrPosition);
121
+ // editor.setSelection(selectionOrPosition);
122
+ // } else {
123
+ // editor.revealPositionInCenterIfOutsideViewport(selectionOrPosition);
124
+ // editor.setPosition(selectionOrPosition);
125
+ // }
126
+
127
+ return false;
128
+ },
129
+ });
48
130
  }
49
131
  }
@@ -24,6 +24,11 @@ export class LibroLanguageClientManager {
24
24
 
25
25
  protected clientMap = new Map<string, IConnectionData>();
26
26
 
27
+ /**
28
+ * lsp server that support notebook
29
+ */
30
+ protected supportedLSPServer: string[] = ['libro-analyzer', 'ruff-lsp', 'pylance'];
31
+
27
32
  @postConstruct()
28
33
  init() {
29
34
  this.languageServerManager = this.languageServerManagerFactory({});
@@ -39,7 +44,7 @@ export class LibroLanguageClientManager {
39
44
  const serverIds = this.languageServerManager.getMatchingServers({
40
45
  language,
41
46
  });
42
- return serverIds;
47
+ return serverIds.filter((item) => this.supportedLSPServer.includes(item));
43
48
  }
44
49
 
45
50
  async getServerSpecs(language = 'python') {
@@ -72,6 +77,9 @@ export class LibroLanguageClientManager {
72
77
  languageServerId: string,
73
78
  options: LibroLanguageClientOptions,
74
79
  ) {
80
+ if (!this.supportedLSPServer.includes(languageServerId)) {
81
+ return;
82
+ }
75
83
  if (this.clientMap.has(languageServerId)) {
76
84
  return this.clientMap.get(languageServerId);
77
85
  }
package/src/util.ts ADDED
@@ -0,0 +1,43 @@
1
+ import type { IPosition, IRange } from '@difizen/libro-code-editor';
2
+ import type { CellModel } from '@difizen/libro-core';
3
+ import type { ExecutableNotebookModel } from '@difizen/libro-kernel';
4
+ import { URI } from '@difizen/mana-app';
5
+ import type * as monaco from '@difizen/monaco-editor-core';
6
+
7
+ import { LibroCellURIScheme } from './constants.js';
8
+
9
+ export const getCellURI = (
10
+ libroModel: ExecutableNotebookModel,
11
+ cellModel: CellModel,
12
+ ): URI => {
13
+ let uri = new URI(libroModel.filePath);
14
+ uri = URI.withScheme(uri, LibroCellURIScheme);
15
+ uri = URI.withQuery(uri, `cellid=${cellModel.id}`);
16
+ return uri;
17
+ };
18
+
19
+ export const toEditorRange = (range: monaco.IRange): IRange => {
20
+ return {
21
+ start: {
22
+ line: range.startLineNumber - 1,
23
+ column: range.startColumn - 1,
24
+ },
25
+ end: {
26
+ line: range.endLineNumber - 1,
27
+ column: range.endColumn - 1,
28
+ },
29
+ };
30
+ };
31
+
32
+ export const toMonacoPosition = (position: monaco.IPosition | undefined): IPosition => {
33
+ if (!position) {
34
+ return {
35
+ column: 0,
36
+ line: 0,
37
+ };
38
+ }
39
+ return {
40
+ column: position?.column - 1,
41
+ line: position?.lineNumber - 1,
42
+ };
43
+ };