@lvce-editor/editor-worker 1.16.0 → 2.1.0

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 (2) hide show
  1. package/dist/editorWorkerMain.js +1522 -988
  2. package/package.json +1 -1
@@ -109,6 +109,120 @@ const handleSliderPointerMove = (state, x, y) => {
109
109
  };
110
110
  };
111
111
 
112
+ const ColoredMaskIcon = 'ColoredMaskIcon';
113
+ const ColorPicker = 'ColorPicker';
114
+ const ColorPickerBackgroundColor = 'ColorPickerBackgroundColor';
115
+ const ColorPickerDark = 'ColorPickerDark';
116
+ const ColorPickerLight = 'ColorPickerLight';
117
+ const ColorPickerRectangle = 'ColorPickerRectangle';
118
+ const ColorPickerSlider = 'ColorPickerSlider';
119
+ const ColorPickerSliderThumb = 'ColorPickerSliderThumb';
120
+ const Diagnostic = 'Diagnostic';
121
+ const EditorCompletionItem = 'EditorCompletionItem';
122
+ const EditorCompletionItemDeprecated = 'EditorCompletionItemDeprecated';
123
+ const EditorCompletionItemFocused = 'EditorCompletionItemFocused';
124
+ const EditorCompletionItemHighlight = 'EditorCompletionItemHighlight';
125
+ const EditorCursor = 'EditorCursor';
126
+ const EditorRow = 'EditorRow';
127
+ const EditorSelection = 'EditorSelection';
128
+ const FileIcon = 'FileIcon';
129
+ const HoverDisplayString = 'HoverDisplayString';
130
+ const HoverDocumentation = 'HoverDocumentation';
131
+ const HoverEditorRow = 'HoverEditorRow';
132
+ const HoverProblem = 'HoverProblem';
133
+ const HoverProblemDetail = 'HoverProblemDetail';
134
+ const HoverProblemMessage = 'HoverProblemMessage';
135
+ const Label = 'Label';
136
+ const Viewlet = 'Viewlet';
137
+
138
+ const HandlePointerDown = 'handlePointerDown';
139
+ const HandleSashPointerDown = 'handleSashPointerDown';
140
+
141
+ const mergeClassNames = (...classNames) => {
142
+ return classNames.filter(Boolean).join(' ');
143
+ };
144
+
145
+ const Div = 4;
146
+ const Span = 8;
147
+ const Text = 12;
148
+ const Img = 17;
149
+
150
+ const getColorPickerVirtualDom = () => {
151
+ return [{
152
+ type: Div,
153
+ className: mergeClassNames(Viewlet, ColorPicker),
154
+ onPointerDown: HandlePointerDown,
155
+ childCount: 3
156
+ }, {
157
+ type: Div,
158
+ className: ColorPickerRectangle,
159
+ childCount: 3
160
+ }, {
161
+ type: Div,
162
+ className: ColorPickerBackgroundColor,
163
+ childCount: 0
164
+ }, {
165
+ type: Div,
166
+ className: ColorPickerLight,
167
+ childCount: 0
168
+ }, {
169
+ type: Div,
170
+ className: ColorPickerDark,
171
+ childCount: 0
172
+ }, {
173
+ type: Div,
174
+ className: ColorPickerSlider,
175
+ childCount: 0
176
+ }, {
177
+ type: Div,
178
+ className: ColorPickerSliderThumb,
179
+ childCount: 0
180
+ }];
181
+ };
182
+
183
+ const SetBounds = 'setBounds';
184
+ const SetColor = 'setColor';
185
+ const SetContentHeight = 'setContentHeight';
186
+ const SetNegativeMargin = 'setNegativeMargin';
187
+ const SetOffsetX = 'setOffsetX';
188
+ const SetScrollBar = 'setScrollBar';
189
+
190
+ const renderColor = {
191
+ isEqual(oldState, newState) {
192
+ return oldState.color === newState.color;
193
+ },
194
+ apply(oldState, newState) {
195
+ return [/* method */SetColor, /* color */newState.color];
196
+ }
197
+ };
198
+ const renderOffsetX = {
199
+ isEqual(oldState, newState) {
200
+ return oldState.offsetX === newState.offsetX;
201
+ },
202
+ apply(oldState, newState) {
203
+ return [/* method */SetOffsetX, /* offsetX */newState.offsetX];
204
+ }
205
+ };
206
+ const renderColorPickerDom = {
207
+ isEqual(oldState, newState) {
208
+ return oldState.min === newState.min && oldState.max === newState.max;
209
+ },
210
+ apply(oldState, newState) {
211
+ const dom = getColorPickerVirtualDom();
212
+ return ['Viewlet.setDom2', dom];
213
+ }
214
+ };
215
+ const render$3 = [renderColorPickerDom, renderColor, renderOffsetX];
216
+ const renderColorPicker = async (oldState, newState) => {
217
+ const commands = [];
218
+ for (const item of render$3) {
219
+ if (!item.isEqual(oldState, newState)) {
220
+ commands.push(item.apply(oldState, newState));
221
+ }
222
+ }
223
+ return commands;
224
+ };
225
+
112
226
  // TODO use numeric enum
113
227
  const CompositionUpdate = 'compositionUpdate';
114
228
  const ContentEditableInput = 'contentEditableInput';
@@ -1816,7 +1930,8 @@ const createEditor = async ({
1816
1930
  letterSpacing,
1817
1931
  charWidth,
1818
1932
  uid: id,
1819
- id
1933
+ id,
1934
+ widgets: []
1820
1935
  };
1821
1936
  // TODO avoid creating intermediate editors here
1822
1937
  const newEditor1 = setBounds(editor, x, y, width, height, 9);
@@ -2240,9 +2355,6 @@ const braceCompletion = async (editor, text) => {
2240
2355
  }
2241
2356
  };
2242
2357
 
2243
- // @ts-ignore
2244
-
2245
- // @ts-ignore
2246
2358
  const cancelSelection = editor => {
2247
2359
  const selections = editor.selections;
2248
2360
  if (selections.length === 4 && selections[0] === selections[2] && selections[1] === selections[3]) {
@@ -2253,12 +2365,22 @@ const cancelSelection = editor => {
2253
2365
  return scheduleSelections(editor, newSelections);
2254
2366
  };
2255
2367
 
2256
- const closeCompletion = async editor => {
2257
- // TODO
2258
- const completionUid = editor.completionUid;
2259
- await invoke$3('Viewlet.dispose', completionUid);
2260
- editor.completionUid = 0;
2261
- return editor;
2368
+ const isCompletionWidget = widget => {
2369
+ return widget.id === 'completion';
2370
+ };
2371
+ const closeCompletion = editor => {
2372
+ const {
2373
+ widgets
2374
+ } = editor;
2375
+ const completionWidgetIndex = widgets.findIndex(isCompletionWidget);
2376
+ if (completionWidgetIndex === -1) {
2377
+ return editor;
2378
+ }
2379
+ const newWidgets = [...widgets.slice(0, completionWidgetIndex), ...widgets.slice(completionWidgetIndex + 1)];
2380
+ return {
2381
+ ...editor,
2382
+ widgets: newWidgets
2383
+ };
2262
2384
  };
2263
2385
 
2264
2386
  // @ts-ignore
@@ -3274,7 +3396,8 @@ const UiStrings = {
3274
3396
  EditorCloseColorPicker: 'Editor: Close Color Picker',
3275
3397
  EditorCopyLineDown: 'Editor: Copy Line Down',
3276
3398
  EditorCopyLineUp: 'Editor: Copy Line Up',
3277
- Replace: 'replace'
3399
+ Replace: 'replace',
3400
+ NoResults: 'No Results'
3278
3401
  };
3279
3402
  const noDefinitionFound = () => {
3280
3403
  return i18nString(UiStrings.NoDefinitionFound);
@@ -3296,6 +3419,9 @@ const noTypeDefinitionFoundFor = word => {
3296
3419
  const noTypeDefinitionFound = () => {
3297
3420
  return i18nString(UiStrings.NoTypeDefinitionFound);
3298
3421
  };
3422
+ const noResults = () => {
3423
+ return i18nString(UiStrings.NoResults);
3424
+ };
3299
3425
 
3300
3426
  // @ts-ignore
3301
3427
  const goTo = async ({
@@ -4451,71 +4577,544 @@ const moveSelectionPx = (editor, x, y) => {
4451
4577
  return editorMoveSelection(editor, position);
4452
4578
  };
4453
4579
 
4454
- const FindWidget = 'FindWidget';
4455
- const openFind = async state => {
4456
- await invoke$3('Viewlet.openWidget', FindWidget);
4457
- return state;
4580
+ const OnCompletion = 'onCompletion';
4581
+ const OnHover = 'onHover';
4582
+
4583
+ // TODO add tests for this
4584
+ const activateByEvent = async event => {
4585
+ await invoke$3('ExtensionHostManagement.activateByEvent', event);
4458
4586
  };
4459
4587
 
4460
- const getEditor = editorUid => {
4461
- const instance = get$6(editorUid);
4462
- if (!instance) {
4463
- throw new Error(`editor ${editorUid} not found`);
4464
- }
4465
- const {
4466
- newState
4467
- } = instance;
4468
- return newState;
4588
+ const execute = async ({
4589
+ editor,
4590
+ args,
4591
+ event,
4592
+ method,
4593
+ noProviderFoundMessage,
4594
+ noProviderFoundResult = undefined
4595
+ }) => {
4596
+ const fullEvent = `${event}:${editor.languageId}`;
4597
+ await activateByEvent(fullEvent);
4598
+ const result = await invoke$2(method, editor.uid, ...args);
4599
+ return result;
4469
4600
  };
4470
4601
 
4471
- const getText = editorUid => {
4472
- const editor = getEditor(editorUid);
4602
+ const combineResults = results => {
4603
+ return results[0] ?? [];
4604
+ };
4605
+ const executeCompletionProvider = (editor, offset) => {
4606
+ return execute({
4607
+ editor,
4608
+ event: OnCompletion,
4609
+ method: CompletionExecute,
4610
+ args: [offset],
4611
+ noProviderFoundMessage: 'no completion provider found',
4612
+ noProviderFoundResult: [],
4613
+ combineResults
4614
+ });
4615
+ };
4616
+ const combineResultsResolve = items => {
4617
+ return items[0] ?? undefined;
4618
+ };
4619
+ const executeResolveCompletionItem = (editor, offset, name, completionItem) => {
4620
+ return execute({
4621
+ editor,
4622
+ event: OnCompletion,
4623
+ method: CompletionResolveExecute,
4624
+ args: [offset, name, completionItem],
4625
+ noProviderFoundMessage: 'no completion provider found',
4626
+ noProviderFoundResult: [],
4627
+ combineResults: combineResultsResolve
4628
+ });
4629
+ };
4630
+
4631
+ // TODO possible to do this with events/state machine instead of promises -> enables canceling operations / concurrent calls
4632
+ const getCompletions = async editor => {
4473
4633
  const {
4474
- lines
4634
+ selections
4475
4635
  } = editor;
4476
- return lines.join('\n');
4636
+ const rowIndex = selections[0];
4637
+ const columnIndex = selections[1];
4638
+ // Editor.sync(editor)
4639
+ const offset = await offsetAt(editor, rowIndex, columnIndex);
4640
+ const completions = await executeCompletionProvider(editor, offset);
4641
+ return completions;
4477
4642
  };
4478
4643
 
4479
- const organizeImports = async editor => {
4480
- // TODO ask extension host worker directly
4481
- const edits = await invoke$3('ExtensionHostOrganizeImports.organizeImports', editor);
4482
- console.log({
4483
- edits
4484
- });
4485
- return applyDocumentEdits(editor, edits);
4644
+ // TODO don't send unnecessary parts of completion item like matches
4645
+ const resolveCompletion = async (editor, name, completionItem) => {
4646
+ try {
4647
+ object(editor);
4648
+ string(name);
4649
+ object(completionItem);
4650
+ const rowIndex = editor.selections[0];
4651
+ const columnIndex = editor.selections[1];
4652
+ const offset = await offsetAt(editor, rowIndex, columnIndex);
4653
+ // @ts-ignore
4654
+ const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
4655
+ return resolvedCompletionItem;
4656
+ } catch {
4657
+ return undefined;
4658
+ }
4486
4659
  };
4487
4660
 
4488
- // @ts-ignore
4661
+ const None$1 = 1;
4489
4662
 
4490
- // @ts-ignore
4491
- const pasteText = (editor, text) => {
4492
- const insertedLines = splitLines$2(text);
4493
- const changes = editorReplaceSelections(editor, insertedLines, EditorPasteText);
4494
- return scheduleDocumentAndCursorsSelections(editor, changes);
4663
+ const EmptyMatches = [];
4664
+
4665
+ const Diagonal = 1;
4666
+ const Left = 2;
4667
+
4668
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4669
+
4670
+ const createTable = size => {
4671
+ const table = [];
4672
+ for (let i = 0; i < size; i++) {
4673
+ const row = new Uint8Array(size);
4674
+ table.push(row);
4675
+ }
4676
+ return table;
4495
4677
  };
4496
4678
 
4497
- const paste = async editor => {
4498
- const text = await invoke$3('ClipBoard.readText');
4499
- string(text);
4500
- return pasteText(editor, text);
4679
+ const isLowerCase = char => {
4680
+ return char === char.toLowerCase();
4501
4681
  };
4502
4682
 
4503
- const getErrorMessage$1 = error => {
4504
- if (!error) {
4505
- return `Error: ${error}`;
4506
- }
4507
- let message = error.message;
4508
- while (error.cause) {
4509
- error = error.cause;
4510
- message += `: ${error}`;
4511
- }
4512
- return message;
4683
+ const isUpperCase = char => {
4684
+ return char === char.toUpperCase();
4513
4685
  };
4514
- const prepareErrorMessageWithCodeFrame = error => {
4515
- if (!error) {
4516
- return {
4517
- message: error,
4518
- stack: undefined,
4686
+
4687
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4688
+ const isGap = (columnCharBefore, columnChar) => {
4689
+ switch (columnCharBefore) {
4690
+ case Dash:
4691
+ case Underline:
4692
+ case EmptyString:
4693
+ case T:
4694
+ case Space:
4695
+ case Dot:
4696
+ return true;
4697
+ }
4698
+ if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
4699
+ return true;
4700
+ }
4701
+ return false;
4702
+ };
4703
+
4704
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4705
+ const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
4706
+ if (rowCharLow !== columnCharLow) {
4707
+ return -1;
4708
+ }
4709
+ const isMatch = rowChar === columnChar;
4710
+ if (isMatch) {
4711
+ if (isDiagonalMatch) {
4712
+ return 8;
4713
+ }
4714
+ if (isGap(columnCharBefore, columnChar)) {
4715
+ return 8;
4716
+ }
4717
+ return 5;
4718
+ }
4719
+ if (isGap(columnCharBefore, columnChar)) {
4720
+ return 8;
4721
+ }
4722
+ return 5;
4723
+ };
4724
+
4725
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4726
+
4727
+ const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
4728
+ while (patternPos < patternLen && wordPos < wordLen) {
4729
+ if (patternLow[patternPos] === wordLow[wordPos]) {
4730
+ patternPos += 1;
4731
+ }
4732
+ wordPos += 1;
4733
+ }
4734
+ return patternPos === patternLen; // pattern must be exhausted
4735
+ };
4736
+
4737
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4738
+ const traceHighlights = (table, arrows, patternLength, wordLength) => {
4739
+ let row = patternLength;
4740
+ let column = wordLength;
4741
+ const matches = [];
4742
+ while (row >= 1 && column >= 1) {
4743
+ const arrow = arrows[row][column];
4744
+ if (arrow === Left) {
4745
+ column--;
4746
+ } else if (arrow === Diagonal) {
4747
+ row--;
4748
+ column--;
4749
+ const start = column + 1;
4750
+ while (row >= 1 && column >= 1) {
4751
+ const arrow = arrows[row][column];
4752
+ if (arrow === Left) {
4753
+ break;
4754
+ }
4755
+ if (arrow === Diagonal) {
4756
+ row--;
4757
+ column--;
4758
+ }
4759
+ }
4760
+ const end = column;
4761
+ matches.unshift(end, start);
4762
+ }
4763
+ }
4764
+ matches.unshift(table[patternLength][wordLength - 1]);
4765
+ return matches;
4766
+ };
4767
+
4768
+ // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
4769
+ const gridSize = 128;
4770
+ const table = createTable(gridSize);
4771
+ const arrows = createTable(gridSize);
4772
+ // @ts-ignore
4773
+ createTable(gridSize);
4774
+ const filterCompletionItem = (pattern, word) => {
4775
+ const patternLength = Math.min(pattern.length, gridSize - 1);
4776
+ const wordLength = Math.min(word.length, gridSize - 1);
4777
+ const patternLower = pattern.toLowerCase();
4778
+ const wordLower = word.toLowerCase();
4779
+ if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
4780
+ return EmptyMatches;
4781
+ }
4782
+ let strongMatch = false;
4783
+ for (let row = 1; row < patternLength + 1; row++) {
4784
+ const rowChar = pattern[row - 1];
4785
+ const rowCharLow = patternLower[row - 1];
4786
+ for (let column = 1; column < wordLength + 1; column++) {
4787
+ const columnChar = word[column - 1];
4788
+ const columnCharLow = wordLower[column - 1];
4789
+ const columnCharBefore = word[column - 2] || '';
4790
+ const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
4791
+ const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
4792
+ if (row === 1 && score > 5) {
4793
+ strongMatch = true;
4794
+ }
4795
+ let diagonalScore = score + table[row - 1][column - 1];
4796
+ if (isDiagonalMatch && score !== -1) {
4797
+ diagonalScore += 2;
4798
+ }
4799
+ const leftScore = table[row][column - 1];
4800
+ if (leftScore > diagonalScore) {
4801
+ table[row][column] = leftScore;
4802
+ arrows[row][column] = Left;
4803
+ } else {
4804
+ table[row][column] = diagonalScore;
4805
+ arrows[row][column] = Diagonal;
4806
+ }
4807
+ }
4808
+ }
4809
+ if (!strongMatch) {
4810
+ return EmptyMatches;
4811
+ }
4812
+ // printTables(pattern, 0, word, 0)
4813
+ const highlights = traceHighlights(table, arrows, patternLength, wordLength);
4814
+ return highlights;
4815
+ };
4816
+
4817
+ const Deprecated = 1 << 0;
4818
+
4819
+ const addEmptyMatch = item => {
4820
+ return {
4821
+ ...item,
4822
+ matches: EmptyMatches
4823
+ };
4824
+ };
4825
+ const filterCompletionItems = (completionItems, word) => {
4826
+ if (word === EmptyString) {
4827
+ return completionItems.map(addEmptyMatch);
4828
+ }
4829
+ const filteredCompletions = [];
4830
+ const deprecated = [];
4831
+ for (const completionItem of completionItems) {
4832
+ const {
4833
+ label,
4834
+ flags
4835
+ } = completionItem;
4836
+ const result = filterCompletionItem(word, label);
4837
+ if (result !== EmptyMatches) {
4838
+ if (flags & Deprecated) {
4839
+ // TODO avoid mutation
4840
+ completionItem.matches = EmptyMatches;
4841
+ deprecated.push(completionItem);
4842
+ } else {
4843
+ // TODO avoid mutation
4844
+ completionItem.matches = result;
4845
+ filteredCompletions.push(completionItem);
4846
+ }
4847
+ }
4848
+ }
4849
+ if (deprecated.length > 0) {
4850
+ filteredCompletions.push(...deprecated);
4851
+ }
4852
+ return filteredCompletions;
4853
+ };
4854
+
4855
+ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
4856
+ const contentHeight = itemsLength * itemHeight;
4857
+ const finalDeltaY = Math.max(contentHeight - height, 0);
4858
+ return finalDeltaY;
4859
+ };
4860
+
4861
+ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
4862
+ number$1(itemsLength);
4863
+ number$1(itemHeight);
4864
+ number$1(maxHeight);
4865
+ if (itemsLength === 0) {
4866
+ return itemHeight;
4867
+ }
4868
+ const totalHeight = itemsLength * itemHeight;
4869
+ return Math.min(totalHeight, maxHeight);
4870
+ };
4871
+
4872
+ const getEditor = editorUid => {
4873
+ const instance = get$6(editorUid);
4874
+ if (!instance) {
4875
+ throw new Error(`editor ${editorUid} not found`);
4876
+ }
4877
+ const {
4878
+ newState
4879
+ } = instance;
4880
+ return newState;
4881
+ };
4882
+
4883
+ const RE_WORD = /[\w\-]+$/;
4884
+ const getWordAtOffset = editor => {
4885
+ const {
4886
+ lines,
4887
+ selections
4888
+ } = editor;
4889
+ const rowIndex = selections[0];
4890
+ const columnIndex = selections[1];
4891
+ const line = lines[rowIndex];
4892
+ const part = line.slice(0, columnIndex);
4893
+ const wordMatch = part.match(RE_WORD);
4894
+ if (wordMatch) {
4895
+ return wordMatch[0];
4896
+ }
4897
+ return '';
4898
+ };
4899
+ const handleEditorType = (editorUid, state, text) => {
4900
+ const editor = getEditor(editorUid);
4901
+ const {
4902
+ unfilteredItems,
4903
+ itemHeight,
4904
+ maxHeight
4905
+ } = state;
4906
+ const rowIndex = editor.selections[0];
4907
+ const columnIndex = editor.selections[1];
4908
+ const x$1 = x(editor, rowIndex, columnIndex);
4909
+ // @ts-ignore
4910
+ const y$1 = y(editor, rowIndex);
4911
+ const wordAtOffset = getWordAtOffset(editor);
4912
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
4913
+ const newMinLineY = 0;
4914
+ const newMaxLineY = Math.min(items.length, 8);
4915
+ const height = getListHeight(items.length, itemHeight, maxHeight);
4916
+ const finalDeltaY = items.length * itemHeight - height;
4917
+ return {
4918
+ ...state,
4919
+ items,
4920
+ x: x$1,
4921
+ y: y$1,
4922
+ minLineY: newMinLineY,
4923
+ maxLineY: newMaxLineY,
4924
+ leadingWord: wordAtOffset,
4925
+ height,
4926
+ finalDeltaY
4927
+ };
4928
+ };
4929
+ const handleEditorDeleteLeft = (editorUid, state) => {
4930
+ const editor = getEditor(editorUid);
4931
+ const {
4932
+ unfilteredItems,
4933
+ itemHeight,
4934
+ maxHeight
4935
+ } = state;
4936
+ const rowIndex = editor.selections[0];
4937
+ const columnIndex = editor.selections[1];
4938
+ const x$1 = x(editor, rowIndex, columnIndex);
4939
+ // @ts-ignore
4940
+ const y$1 = y(editor, rowIndex);
4941
+ const wordAtOffset = getWordAtOffset(editor);
4942
+ if (!wordAtOffset) {
4943
+ editor.completionState = None$1;
4944
+ return {
4945
+ ...state,
4946
+ disposed: true
4947
+ };
4948
+ }
4949
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
4950
+ const newMaxLineY = Math.min(items.length, 8);
4951
+ const height = getListHeight(items.length, itemHeight, maxHeight);
4952
+ return {
4953
+ ...state,
4954
+ items,
4955
+ x: x$1,
4956
+ y: y$1,
4957
+ maxLineY: newMaxLineY,
4958
+ leadingWord: wordAtOffset,
4959
+ height
4960
+ };
4961
+ };
4962
+ const dispose = state => {
4963
+ return {
4964
+ ...state,
4965
+ disposed: true
4966
+ };
4967
+ };
4968
+ const disposeWithEditor = (state, editor) => {
4969
+ editor.completionState = None$1;
4970
+ editor.completionUid = 0;
4971
+ // Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
4972
+ return dispose(state);
4973
+ };
4974
+ const handleEditorClick = disposeWithEditor;
4975
+ const handleEditorBlur = disposeWithEditor;
4976
+ const loadContent$2 = async (editorUid, state) => {
4977
+ const editor = getEditor(editorUid);
4978
+ const {
4979
+ itemHeight,
4980
+ maxHeight
4981
+ } = state;
4982
+ const unfilteredItems = await getCompletions(editor);
4983
+ const wordAtOffset = getWordAtOffset(editor);
4984
+ const items = filterCompletionItems(unfilteredItems, wordAtOffset);
4985
+ const rowIndex = editor.selections[0];
4986
+ const columnIndex = editor.selections[1];
4987
+ const x$1 = x(editor, rowIndex, columnIndex);
4988
+ // @ts-ignore
4989
+ const y$1 = y(editor, rowIndex);
4990
+ const newMaxLineY = Math.min(items.length, 8);
4991
+ editor.widgets = editor.widgets || [];
4992
+ // editor.widgets.push(ViewletModuleId.EditorCompletion)
4993
+ const itemsLength = items.length;
4994
+ const newFocusedIndex = itemsLength === 0 ? -1 : 0;
4995
+ const total = items.length;
4996
+ const height = getListHeight(items.length, itemHeight, maxHeight);
4997
+ const finalDeltaY = getFinalDeltaY(height, itemHeight, total);
4998
+ return {
4999
+ ...state,
5000
+ unfilteredItems,
5001
+ items,
5002
+ x: x$1,
5003
+ y: y$1,
5004
+ maxLineY: newMaxLineY,
5005
+ focusedIndex: newFocusedIndex,
5006
+ finalDeltaY,
5007
+ leadingWord: wordAtOffset,
5008
+ height,
5009
+ rowIndex,
5010
+ columnIndex,
5011
+ editorUid,
5012
+ width: 200
5013
+ };
5014
+ };
5015
+ const advance = (state, word) => {
5016
+ const filteredItems = filterCompletionItems(state.items, word);
5017
+ return {
5018
+ ...state,
5019
+ filteredItems
5020
+ };
5021
+ };
5022
+
5023
+ const openCompletion = async editor => {
5024
+ const {
5025
+ widgets,
5026
+ uid
5027
+ } = editor;
5028
+ const completionUid = Math.random();
5029
+ const completionWidget = {
5030
+ id: 'completion',
5031
+ oldState: {
5032
+ items: [],
5033
+ itemHeight: 20,
5034
+ maxHeight: 150,
5035
+ minLineY: 0,
5036
+ maxLineY: 0,
5037
+ uid: completionUid
5038
+ },
5039
+ newState: {
5040
+ items: [],
5041
+ itemHeight: 20,
5042
+ maxHeight: 150,
5043
+ minLineY: 0,
5044
+ maxLineY: 10,
5045
+ uid: completionUid
5046
+ }
5047
+ };
5048
+ const newWidgets = [...widgets, completionWidget];
5049
+ const newEditor = {
5050
+ ...editor,
5051
+ widgets: newWidgets
5052
+ };
5053
+ set$6(uid, editor, newEditor);
5054
+ const newCompletionWidget = await loadContent$2(uid, completionWidget.newState);
5055
+ const FocusEditorCompletions = 9;
5056
+ await invoke$3('Focus.setAdditionalFocus', FocusEditorCompletions);
5057
+ const latestEditor = getEditor(uid);
5058
+ if (!latestEditor.widgets.includes(completionWidget)) {
5059
+ return editor;
5060
+ }
5061
+ const index = latestEditor.widgets.indexOf(completionWidget);
5062
+ const latestWidgets = [...latestEditor.widgets.slice(0, index), {
5063
+ ...completionWidget,
5064
+ newState: newCompletionWidget
5065
+ }, ...latestEditor.widgets.slice(index + 1)];
5066
+ return {
5067
+ ...latestEditor,
5068
+ widgets: latestWidgets
5069
+ };
5070
+ };
5071
+
5072
+ const FindWidget = 'FindWidget';
5073
+ const openFind = async state => {
5074
+ await invoke$3('Viewlet.openWidget', FindWidget);
5075
+ return state;
5076
+ };
5077
+
5078
+ const organizeImports = async editor => {
5079
+ // TODO ask extension host worker directly
5080
+ const edits = await invoke$3('ExtensionHostOrganizeImports.organizeImports', editor);
5081
+ console.log({
5082
+ edits
5083
+ });
5084
+ return applyDocumentEdits(editor, edits);
5085
+ };
5086
+
5087
+ // @ts-ignore
5088
+
5089
+ // @ts-ignore
5090
+ const pasteText = (editor, text) => {
5091
+ const insertedLines = splitLines$2(text);
5092
+ const changes = editorReplaceSelections(editor, insertedLines, EditorPasteText);
5093
+ return scheduleDocumentAndCursorsSelections(editor, changes);
5094
+ };
5095
+
5096
+ const paste = async editor => {
5097
+ const text = await invoke$3('ClipBoard.readText');
5098
+ string(text);
5099
+ return pasteText(editor, text);
5100
+ };
5101
+
5102
+ const getErrorMessage$1 = error => {
5103
+ if (!error) {
5104
+ return `Error: ${error}`;
5105
+ }
5106
+ let message = error.message;
5107
+ while (error.cause) {
5108
+ error = error.cause;
5109
+ message += `: ${error}`;
5110
+ }
5111
+ return message;
5112
+ };
5113
+ const prepareErrorMessageWithCodeFrame = error => {
5114
+ if (!error) {
5115
+ return {
5116
+ message: error,
5117
+ stack: undefined,
4519
5118
  codeFrame: undefined,
4520
5119
  type: 'Error'
4521
5120
  };
@@ -6183,491 +6782,504 @@ const editorUnindent = editor => {
6183
6782
 
6184
6783
  // editor.lines //?
6185
6784
 
6186
- const OnCompletion = 'onCompletion';
6187
- const OnHover = 'onHover';
6188
-
6189
- // TODO add tests for this
6190
- const activateByEvent = async event => {
6191
- await invoke$3('ExtensionHostManagement.activateByEvent', event);
6785
+ const isCompletion$2 = widget => {
6786
+ return widget.id === 'completion';
6192
6787
  };
6193
-
6194
- const execute = async ({
6195
- editor,
6196
- args,
6197
- event,
6198
- method,
6199
- noProviderFoundMessage,
6200
- noProviderFoundResult = undefined
6201
- }) => {
6202
- const fullEvent = `${event}:${editor.languageId}`;
6203
- await activateByEvent(fullEvent);
6204
- const result = await invoke$2(method, editor.uid, ...args);
6205
- return result;
6788
+ const getCompletionState = editor => {
6789
+ const {
6790
+ widgets
6791
+ } = editor;
6792
+ const child = widgets.find(isCompletion$2);
6793
+ return child.newState;
6206
6794
  };
6207
6795
 
6208
- const combineResults = results => {
6209
- return results[0] ?? [];
6796
+ const isCompletion$1 = widget => {
6797
+ return widget.id === 'completion';
6210
6798
  };
6211
- const executeCompletionProvider = (editor, offset) => {
6212
- return execute({
6213
- editor,
6214
- event: OnCompletion,
6215
- method: CompletionExecute,
6216
- args: [offset],
6217
- noProviderFoundMessage: 'no completion provider found',
6218
- noProviderFoundResult: [],
6219
- combineResults
6220
- });
6799
+ const focusIndex$1 = (editor, index) => {
6800
+ const child = getCompletionState(editor);
6801
+ if (index === -1) {
6802
+ return editor;
6803
+ }
6804
+ const childIndex = editor.widgets.findIndex(isCompletion$1);
6805
+ // TODO scroll up/down if necessary
6806
+ const childWidget = editor.widgets[childIndex];
6807
+ const newWidget = {
6808
+ ...childWidget,
6809
+ newState: {
6810
+ ...child,
6811
+ focusedIndex: index,
6812
+ focused: true
6813
+ }
6814
+ };
6815
+ const newWidgets = [...editor.widgets.slice(0, childIndex), newWidget, ...editor.widgets.slice(childIndex + 1)];
6816
+ return {
6817
+ ...editor,
6818
+ widgets: newWidgets
6819
+ };
6221
6820
  };
6222
- const combineResultsResolve = items => {
6223
- return items[0] ?? undefined;
6821
+
6822
+ const focusFirst$1 = editor => {
6823
+ const firstIndex = 0;
6824
+ return focusIndex$1(editor, firstIndex);
6224
6825
  };
6225
- const executeResolveCompletionItem = (editor, offset, name, completionItem) => {
6226
- return execute({
6227
- editor,
6228
- event: OnCompletion,
6229
- method: CompletionResolveExecute,
6230
- args: [offset, name, completionItem],
6231
- noProviderFoundMessage: 'no completion provider found',
6232
- noProviderFoundResult: [],
6233
- combineResults: combineResultsResolve
6234
- });
6826
+
6827
+ const focusNext$1 = editor => {
6828
+ const child = getCompletionState(editor);
6829
+ const nextIndex = child.focusedIndex + 1;
6830
+ return focusIndex$1(editor, nextIndex);
6235
6831
  };
6236
6832
 
6237
- // TODO possible to do this with events/state machine instead of promises -> enables canceling operations / concurrent calls
6238
- const getCompletions = async editor => {
6833
+ const focusPrevious$1 = editor => {
6834
+ const child = getCompletionState(editor);
6835
+ const previousIndex = child.focusedIndex - 1;
6836
+ return focusIndex$1(editor, previousIndex);
6837
+ };
6838
+
6839
+ const getEdits = async (editor, completionItem) => {
6840
+ const child = getCompletionState(editor);
6841
+ // @ts-ignore
6842
+ const {
6843
+ leadingWord,
6844
+ uid
6845
+ } = child;
6846
+ const word = completionItem.label;
6847
+ const resolvedItem = await resolveCompletion(editor, word, completionItem);
6848
+ const inserted = resolvedItem ? resolvedItem.snippet : word;
6849
+ // TODO type and dispose commands should be sent to renderer process at the same time
6239
6850
  const {
6240
6851
  selections
6241
6852
  } = editor;
6242
- const rowIndex = selections[0];
6243
- const columnIndex = selections[1];
6244
- // Editor.sync(editor)
6245
- const offset = await offsetAt(editor, rowIndex, columnIndex);
6246
- const completions = await executeCompletionProvider(editor, offset);
6247
- return completions;
6853
+ const [startRowIndex, startColumnIndex] = selections;
6854
+ const leadingWordLength = leadingWord.length;
6855
+ const replaceRange$1 = new Uint32Array([startRowIndex, startColumnIndex - leadingWordLength, startRowIndex, startColumnIndex]);
6856
+ const changes = replaceRange(editor, replaceRange$1, [inserted], '');
6857
+ return changes;
6248
6858
  };
6249
-
6250
- // TODO don't send unnecessary parts of completion item like matches
6251
- const resolveCompletion = async (editor, name, completionItem) => {
6252
- try {
6253
- object(editor);
6254
- string(name);
6255
- object(completionItem);
6256
- const rowIndex = editor.selections[0];
6257
- const columnIndex = editor.selections[1];
6258
- const offset = await offsetAt(editor, rowIndex, columnIndex);
6259
- // @ts-ignore
6260
- const resolvedCompletionItem = await executeResolveCompletionItem(editor, offset, name, completionItem);
6261
- return resolvedCompletionItem;
6262
- } catch {
6263
- return undefined;
6859
+ const isCompletion = widget => {
6860
+ return widget.id === 'completion';
6861
+ };
6862
+ const select = async (editor, completionItem) => {
6863
+ const changes = await getEdits(editor, completionItem);
6864
+ const index = editor.widgets.indexOf
6865
+ // ViewletModuleId.EditorCompletion
6866
+ ();
6867
+ if (index !== -1) {
6868
+ editor.widgets.splice(index, 1);
6869
+ editor.completionState = None$1;
6870
+ editor.completionUid = 0;
6264
6871
  }
6872
+ // TODO dispose completion widget
6873
+ // TODO apply edit in editor worker instead of asking renderer worker
6874
+ // await RendererWorker.invoke('Viewlet.dispose', state.uid)
6875
+ const {
6876
+ widgets
6877
+ } = editor;
6878
+ const completionWidgetIndex = editor.widgets.findIndex(isCompletion);
6879
+ const newWidgets = [...widgets.slice(0, completionWidgetIndex), ...widgets.slice(completionWidgetIndex + 1)];
6880
+ const intermediateEditor = await applyEdit(editor, changes);
6881
+ return {
6882
+ ...intermediateEditor,
6883
+ widgets: newWidgets
6884
+ };
6265
6885
  };
6266
-
6267
- const None = 1;
6268
-
6269
- const EmptyMatches = [];
6270
-
6271
- const Diagonal = 1;
6272
- const Left = 2;
6273
-
6274
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6275
-
6276
- const createTable = size => {
6277
- const table = [];
6278
- for (let i = 0; i < size; i++) {
6279
- const row = new Uint8Array(size);
6280
- table.push(row);
6886
+ const selectIndex = (editor, index) => {
6887
+ const child = getCompletionState(editor);
6888
+ const {
6889
+ items
6890
+ } = child;
6891
+ if (index === -1) {
6892
+ return editor;
6281
6893
  }
6282
- return table;
6894
+ if (index > items.length) {
6895
+ throw new Error('index too large');
6896
+ }
6897
+ const actualIndex = index;
6898
+ const completionItem = items[actualIndex];
6899
+ return select(editor, completionItem);
6283
6900
  };
6284
6901
 
6285
- const isLowerCase = char => {
6286
- return char === char.toLowerCase();
6902
+ const selectCurrent = editor => {
6903
+ const child = getCompletionState(editor);
6904
+ const {
6905
+ focusedIndex
6906
+ } = child;
6907
+ return selectIndex(editor, focusedIndex);
6287
6908
  };
6288
6909
 
6289
- const isUpperCase = char => {
6290
- return char === char.toUpperCase();
6910
+ const executeHoverProvider = (editor, offset) => {
6911
+ object(editor);
6912
+ number$1(offset);
6913
+ return execute({
6914
+ event: OnHover,
6915
+ editor,
6916
+ method: HoverExecute,
6917
+ args: [offset],
6918
+ noProviderFoundMessage: 'No hover provider found'
6919
+ });
6291
6920
  };
6292
6921
 
6293
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6294
- const isGap = (columnCharBefore, columnChar) => {
6295
- switch (columnCharBefore) {
6296
- case Dash:
6297
- case Underline:
6298
- case EmptyString:
6299
- case T:
6300
- case Space:
6301
- case Dot:
6302
- return true;
6303
- }
6304
- if (isLowerCase(columnCharBefore) && isUpperCase(columnChar)) {
6305
- return true;
6306
- }
6307
- return false;
6922
+ const getHover = async (editor, offset) => {
6923
+ object(editor);
6924
+ number$1(offset);
6925
+ // TODO invoke extension host worker directly
6926
+ const hover = await executeHoverProvider(editor, offset);
6927
+ return hover;
6928
+ };
6929
+
6930
+ let _ipc;
6931
+ const listen$5 = async () => {
6932
+ const ipc = await create$1({
6933
+ method: RendererProcess
6934
+ });
6935
+ handleIpc(ipc);
6936
+ _ipc = ipc;
6937
+ };
6938
+ const invoke = async (method, ...args) => {
6939
+ return invoke$5(_ipc, method, ...args);
6308
6940
  };
6309
6941
 
6310
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6311
- const getScore = (rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch) => {
6312
- if (rowCharLow !== columnCharLow) {
6313
- return -1;
6314
- }
6315
- const isMatch = rowChar === columnChar;
6316
- if (isMatch) {
6317
- if (isDiagonalMatch) {
6318
- return 8;
6319
- }
6320
- if (isGap(columnCharBefore, columnChar)) {
6321
- return 8;
6322
- }
6323
- return 5;
6324
- }
6325
- if (isGap(columnCharBefore, columnChar)) {
6326
- return 8;
6327
- }
6328
- return 5;
6942
+ const measureTextBlockHeight = (text, fontFamily, fontSize, lineHeight, width) => {
6943
+ return invoke('MeasureTextBlockHeight.measureTextBlockHeight', text, fontSize, fontFamily, lineHeight, width);
6329
6944
  };
6330
6945
 
6331
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6946
+ const deepCopy = value => {
6947
+ return structuredClone(value);
6948
+ };
6332
6949
 
6333
- const isPatternInWord = (patternLow, patternPos, patternLen, wordLow, wordPos, wordLen) => {
6334
- while (patternPos < patternLen && wordPos < wordLen) {
6335
- if (patternLow[patternPos] === wordLow[wordPos]) {
6336
- patternPos += 1;
6337
- }
6338
- wordPos += 1;
6339
- }
6340
- return patternPos === patternLen; // pattern must be exhausted
6950
+ const getInitialLineState = initialLineState => {
6951
+ return deepCopy(initialLineState);
6341
6952
  };
6342
6953
 
6343
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6344
- const traceHighlights = (table, arrows, patternLength, wordLength) => {
6345
- let row = patternLength;
6346
- let column = wordLength;
6347
- const matches = [];
6348
- while (row >= 1 && column >= 1) {
6349
- const arrow = arrows[row][column];
6350
- if (arrow === Left) {
6351
- column--;
6352
- } else if (arrow === Diagonal) {
6353
- row--;
6354
- column--;
6355
- const start = column + 1;
6356
- while (row >= 1 && column >= 1) {
6357
- const arrow = arrows[row][column];
6358
- if (arrow === Left) {
6359
- break;
6360
- }
6361
- if (arrow === Diagonal) {
6362
- row--;
6363
- column--;
6364
- }
6365
- }
6366
- const end = column;
6367
- matches.unshift(end, start);
6368
- }
6954
+ const getLineInfo$1 = (line, tokens, TokenMap) => {
6955
+ const tokensLength = tokens.length;
6956
+ let end = 0;
6957
+ let start = 0;
6958
+ const lineInfo = [];
6959
+ for (let i = 0; i < tokensLength; i += 2) {
6960
+ const tokenType = tokens[i];
6961
+ const tokenLength = tokens[i + 1];
6962
+ end += tokenLength;
6963
+ const text = line.slice(start, end);
6964
+ const className = `Token ${TokenMap[tokenType] || 'Unknown'}`;
6965
+ const normalizedText = text;
6966
+ lineInfo.push(normalizedText, className);
6967
+ start = end;
6369
6968
  }
6370
- matches.unshift(table[patternLength][wordLength - 1]);
6371
- return matches;
6969
+ return lineInfo;
6372
6970
  };
6373
6971
 
6374
- // based on https://github.com/microsoft/vscode/blob/3059063b805ed0ac10a6d9539e213386bfcfb852/src/vs/base/common/filters.ts by Microsoft (License MIT)
6375
- const gridSize = 128;
6376
- const table = createTable(gridSize);
6377
- const arrows = createTable(gridSize);
6378
- // @ts-ignore
6379
- createTable(gridSize);
6380
- const filterCompletionItem = (pattern, word) => {
6381
- const patternLength = Math.min(pattern.length, gridSize - 1);
6382
- const wordLength = Math.min(word.length, gridSize - 1);
6383
- const patternLower = pattern.toLowerCase();
6384
- const wordLower = word.toLowerCase();
6385
- if (!isPatternInWord(patternLower, 0, patternLength, wordLower, 0, wordLength)) {
6386
- return EmptyMatches;
6972
+ const state = {
6973
+ warned: []
6974
+ };
6975
+ const flattenTokensArray = tokens => {
6976
+ const flattened = [];
6977
+ for (const token of tokens) {
6978
+ object(token);
6979
+ flattened.push(token.type, token.length);
6387
6980
  }
6388
- let strongMatch = false;
6389
- for (let row = 1; row < patternLength + 1; row++) {
6390
- const rowChar = pattern[row - 1];
6391
- const rowCharLow = patternLower[row - 1];
6392
- for (let column = 1; column < wordLength + 1; column++) {
6393
- const columnChar = word[column - 1];
6394
- const columnCharLow = wordLower[column - 1];
6395
- const columnCharBefore = word[column - 2] || '';
6396
- const isDiagonalMatch = arrows[row - 1][column - 1] === Diagonal;
6397
- const score = getScore(rowCharLow, rowChar, columnCharBefore, columnCharLow, columnChar, column, wordLength, isDiagonalMatch);
6398
- if (row === 1 && score > 5) {
6399
- strongMatch = true;
6400
- }
6401
- let diagonalScore = score + table[row - 1][column - 1];
6402
- if (isDiagonalMatch && score !== -1) {
6403
- diagonalScore += 2;
6404
- }
6405
- const leftScore = table[row][column - 1];
6406
- if (leftScore > diagonalScore) {
6407
- table[row][column] = leftScore;
6408
- arrows[row][column] = Left;
6409
- } else {
6410
- table[row][column] = diagonalScore;
6411
- arrows[row][column] = Diagonal;
6412
- }
6413
- }
6981
+ return flattened;
6982
+ };
6983
+ const warnDeprecatedArrayReturn = (languageId, fn) => {
6984
+ if (state.warned.includes(fn)) {
6985
+ return;
6414
6986
  }
6415
- if (!strongMatch) {
6416
- return EmptyMatches;
6987
+ state.warned.push(fn);
6988
+ console.warn(`tokenizers without hasArrayReturn=false are deprecated (language ${languageId})`);
6989
+ };
6990
+ const safeTokenizeLine = (languageId, tokenizeLine, line, lineStateAtStart, hasArrayReturn) => {
6991
+ try {
6992
+ const lineState = tokenizeLine(line, lineStateAtStart);
6993
+ if (!lineState || !lineState.tokens || !lineState.state) {
6994
+ throw new Error('invalid tokenization result');
6995
+ }
6996
+ if (!hasArrayReturn) {
6997
+ warnDeprecatedArrayReturn(languageId, tokenizeLine);
6998
+ // workaround for old tokenizers
6999
+ lineState.tokens = flattenTokensArray(lineState.tokens);
7000
+ }
7001
+ return lineState;
7002
+ } catch (error) {
7003
+ console.error(error);
7004
+ return {
7005
+ tokens: [/* type */0, /* length */line.length],
7006
+ lineState: lineStateAtStart
7007
+ };
6417
7008
  }
6418
- // printTables(pattern, 0, word, 0)
6419
- const highlights = traceHighlights(table, arrows, patternLength, wordLength);
6420
- return highlights;
6421
7009
  };
6422
7010
 
6423
- const Deprecated = 1 << 0;
6424
-
6425
- const addEmptyMatch = item => {
6426
- return {
6427
- ...item,
6428
- matches: EmptyMatches
6429
- };
6430
- };
6431
- const filterCompletionItems = (completionItems, word) => {
6432
- if (word === EmptyString) {
6433
- return completionItems.map(addEmptyMatch);
6434
- }
6435
- const filteredCompletions = [];
6436
- const deprecated = [];
6437
- for (const completionItem of completionItems) {
7011
+ const getLineInfos = (lines, tokenizer, languageId) => {
7012
+ const lineInfos = [];
7013
+ const {
7014
+ tokenizeLine,
7015
+ initialLineState,
7016
+ hasArrayReturn,
7017
+ TokenMap
7018
+ } = tokenizer;
7019
+ let currentLineState = getInitialLineState(initialLineState);
7020
+ for (const line of lines) {
7021
+ const result = safeTokenizeLine(languageId, tokenizeLine, line, currentLineState, hasArrayReturn);
6438
7022
  const {
6439
- label,
6440
- flags
6441
- } = completionItem;
6442
- const result = filterCompletionItem(word, label);
6443
- if (result !== EmptyMatches) {
6444
- if (flags & Deprecated) {
6445
- // TODO avoid mutation
6446
- completionItem.matches = EmptyMatches;
6447
- deprecated.push(completionItem);
6448
- } else {
6449
- // TODO avoid mutation
6450
- completionItem.matches = result;
6451
- filteredCompletions.push(completionItem);
6452
- }
6453
- }
6454
- }
6455
- if (deprecated.length > 0) {
6456
- filteredCompletions.push(...deprecated);
7023
+ tokens
7024
+ } = result;
7025
+ const lineInfo = getLineInfo$1(line, tokens, TokenMap);
7026
+ lineInfos.push(lineInfo);
7027
+ currentLineState = result;
6457
7028
  }
6458
- return filteredCompletions;
7029
+ return lineInfos;
6459
7030
  };
6460
7031
 
6461
- const getFinalDeltaY = (height, itemHeight, itemsLength) => {
6462
- const contentHeight = itemsLength * itemHeight;
6463
- const finalDeltaY = Math.max(contentHeight - height, 0);
6464
- return finalDeltaY;
7032
+ const tokenizeCodeBlock = async (codeBlock, languageId, tokenizerPath) => {
7033
+ await loadTokenizer(languageId, tokenizerPath);
7034
+ const tokenizer = getTokenizer(languageId);
7035
+ const lines = splitLines$2(codeBlock);
7036
+ const lineInfos = getLineInfos(lines, tokenizer, languageId);
7037
+ return lineInfos;
6465
7038
  };
6466
7039
 
6467
- const getListHeight = (itemsLength, itemHeight, maxHeight) => {
6468
- number$1(itemsLength);
6469
- number$1(itemHeight);
6470
- number$1(maxHeight);
6471
- if (itemsLength === 0) {
6472
- return itemHeight;
7040
+ const getHoverPosition = (position, selections) => {
7041
+ if (position) {
7042
+ return position;
6473
7043
  }
6474
- const totalHeight = itemsLength * itemHeight;
6475
- return Math.min(totalHeight, maxHeight);
6476
- };
6477
-
6478
- const RE_WORD = /[\w\-]+$/;
6479
- const getWordAtOffset = editor => {
6480
- const {
6481
- lines,
6482
- selections
6483
- } = editor;
6484
7044
  const rowIndex = selections[0];
6485
7045
  const columnIndex = selections[1];
6486
- const line = lines[rowIndex];
6487
- const part = line.slice(0, columnIndex);
6488
- const wordMatch = part.match(RE_WORD);
6489
- if (wordMatch) {
6490
- return wordMatch[0];
7046
+ return {
7047
+ rowIndex,
7048
+ columnIndex
7049
+ };
7050
+ };
7051
+ const getMatchingDiagnostics = (diagnostics, rowIndex, columnIndex) => {
7052
+ const matching = [];
7053
+ for (const diagnostic of diagnostics) {
7054
+ if (diagnostic.rowIndex === rowIndex) {
7055
+ matching.push(diagnostic);
7056
+ }
6491
7057
  }
6492
- return '';
7058
+ return matching;
6493
7059
  };
6494
- const handleEditorType = (editorUid, state, text) => {
6495
- const editor = getEditor(editorUid);
6496
- const {
6497
- unfilteredItems,
6498
- itemHeight,
6499
- maxHeight
6500
- } = state;
6501
- const rowIndex = editor.selections[0];
6502
- const columnIndex = editor.selections[1];
6503
- const x$1 = x(editor, rowIndex, columnIndex);
6504
- // @ts-ignore
6505
- const y$1 = y(editor, rowIndex);
6506
- const wordAtOffset = getWordAtOffset(editor);
6507
- const items = filterCompletionItems(unfilteredItems, wordAtOffset);
6508
- const newMinLineY = 0;
6509
- const newMaxLineY = Math.min(items.length, 8);
6510
- const height = getListHeight(items.length, itemHeight, maxHeight);
6511
- const finalDeltaY = items.length * itemHeight - height;
7060
+ const fallbackDisplayStringLanguageId = 'typescript'; // TODO remove this
7061
+
7062
+ const hoverDocumentationFontSize = 15;
7063
+ const hoverDocumentationFontFamily = 'Fira Code';
7064
+ const hoverDocumentationLineHeight = '1.33333';
7065
+ const hoverBorderLeft = 1;
7066
+ const hoverBorderRight = 1;
7067
+ const hoverPaddingLeft = 8;
7068
+ const hoverPaddingRight = 8;
7069
+ const hovverFullWidth = 400;
7070
+ const hoverDocumentationWidth = hovverFullWidth - hoverPaddingLeft - hoverPaddingRight - hoverBorderLeft - hoverBorderRight;
7071
+ const getHoverPositionXy = (editor, rowIndex, wordStart, documentationHeight) => {
7072
+ const x$1 = x(editor, rowIndex, wordStart);
7073
+ const y$1 = editor.height - y(editor, rowIndex) + editor.y + 40;
6512
7074
  return {
6513
- ...state,
6514
- items,
6515
7075
  x: x$1,
6516
- y: y$1,
6517
- minLineY: newMinLineY,
6518
- maxLineY: newMaxLineY,
6519
- leadingWord: wordAtOffset,
6520
- height,
6521
- finalDeltaY
7076
+ y: y$1
6522
7077
  };
6523
7078
  };
6524
- const handleEditorDeleteLeft = (editorUid, state) => {
6525
- const editor = getEditor(editorUid);
7079
+ const getEditorHoverInfo = async (editorUid, position) => {
7080
+ number$1(editorUid);
7081
+ const instance = get$6(editorUid);
7082
+ const editor = instance.newState;
6526
7083
  const {
6527
- unfilteredItems,
6528
- itemHeight,
6529
- maxHeight
6530
- } = state;
6531
- const rowIndex = editor.selections[0];
6532
- const columnIndex = editor.selections[1];
6533
- const x$1 = x(editor, rowIndex, columnIndex);
6534
- // @ts-ignore
6535
- const y$1 = y(editor, rowIndex);
6536
- const wordAtOffset = getWordAtOffset(editor);
6537
- if (!wordAtOffset) {
6538
- editor.completionState = None;
6539
- return {
6540
- ...state,
6541
- disposed: true
6542
- };
7084
+ selections
7085
+ } = editor;
7086
+ const {
7087
+ rowIndex,
7088
+ columnIndex
7089
+ } = getHoverPosition(position, selections);
7090
+ const offset = offsetAt(editor, rowIndex, columnIndex);
7091
+ const hover = await getHover(editor, offset);
7092
+ if (!hover) {
7093
+ return undefined;
6543
7094
  }
6544
- const items = filterCompletionItems(unfilteredItems, wordAtOffset);
6545
- const newMaxLineY = Math.min(items.length, 8);
6546
- const height = getListHeight(items.length, itemHeight, maxHeight);
7095
+ const {
7096
+ displayString,
7097
+ documentation,
7098
+ displayStringLanguageId
7099
+ } = hover;
7100
+ const tokenizerPath = '';
7101
+ const lineInfos = await tokenizeCodeBlock(displayString, displayStringLanguageId || fallbackDisplayStringLanguageId, tokenizerPath);
7102
+ const wordPart = await getWordBefore(editor, rowIndex, columnIndex);
7103
+ const wordStart = columnIndex - wordPart.length;
7104
+ await measureTextBlockHeight(documentation, hoverDocumentationFontFamily, hoverDocumentationFontSize, hoverDocumentationLineHeight, hoverDocumentationWidth);
7105
+ const {
7106
+ x,
7107
+ y
7108
+ } = getHoverPositionXy(editor, rowIndex, wordStart);
7109
+ const diagnostics = editor.diagnostics || [];
7110
+ const matchingDiagnostics = getMatchingDiagnostics(diagnostics, rowIndex);
6547
7111
  return {
6548
- ...state,
6549
- items,
6550
- x: x$1,
6551
- y: y$1,
6552
- maxLineY: newMaxLineY,
6553
- leadingWord: wordAtOffset,
6554
- height
7112
+ lineInfos,
7113
+ documentation,
7114
+ x,
7115
+ y,
7116
+ matchingDiagnostics
6555
7117
  };
6556
7118
  };
6557
- const dispose = state => {
7119
+
7120
+ const loadContent$1 = async (editorUid, state, position) => {
7121
+ const hoverInfo = await getEditorHoverInfo(editorUid, position);
7122
+ if (!hoverInfo) {
7123
+ return state;
7124
+ }
7125
+ const {
7126
+ lineInfos,
7127
+ documentation,
7128
+ x,
7129
+ y,
7130
+ matchingDiagnostics
7131
+ } = hoverInfo;
6558
7132
  return {
6559
7133
  ...state,
6560
- disposed: true
7134
+ lineInfos,
7135
+ documentation,
7136
+ x,
7137
+ y,
7138
+ diagnostics: matchingDiagnostics
6561
7139
  };
6562
7140
  };
6563
- const disposeWithEditor = (state, editor) => {
6564
- editor.completionState = None;
6565
- editor.completionUid = 0;
6566
- // Focus.removeAdditionalFocus(FocusKey.EditorCompletion)
6567
- return dispose(state);
7141
+ const handleSashPointerDown = (state, eventX, eventY) => {
7142
+ return state;
6568
7143
  };
6569
- const handleEditorClick = disposeWithEditor;
6570
- const handleEditorBlur = disposeWithEditor;
6571
- const loadContent$2 = async (editorUid, state) => {
6572
- const editor = getEditor(editorUid);
7144
+ const handleSashPointerMove = (state, eventX, eventY) => {
7145
+ // @ts-ignore
6573
7146
  const {
6574
- itemHeight,
6575
- maxHeight
7147
+ x,
7148
+ y
6576
7149
  } = state;
6577
- const unfilteredItems = await getCompletions(editor);
6578
- const wordAtOffset = getWordAtOffset(editor);
6579
- const items = filterCompletionItems(unfilteredItems, wordAtOffset);
6580
- const rowIndex = editor.selections[0];
6581
- const columnIndex = editor.selections[1];
6582
- const x$1 = x(editor, rowIndex, columnIndex);
6583
- // @ts-ignore
6584
- const y$1 = y(editor, rowIndex);
6585
- const newMaxLineY = Math.min(items.length, 8);
6586
- editor.widgets = editor.widgets || [];
6587
- // editor.widgets.push(ViewletModuleId.EditorCompletion)
6588
- const itemsLength = items.length;
6589
- const newFocusedIndex = itemsLength === 0 ? -1 : 0;
6590
- const total = items.length;
6591
- const height = getListHeight(items.length, itemHeight, maxHeight);
6592
- const finalDeltaY = getFinalDeltaY(height, itemHeight, total);
7150
+ const minWidth = 100;
7151
+ const newWidth = Math.max(eventX - x, minWidth);
6593
7152
  return {
6594
7153
  ...state,
6595
- unfilteredItems,
6596
- items,
6597
- x: x$1,
6598
- y: y$1,
6599
- maxLineY: newMaxLineY,
6600
- focusedIndex: newFocusedIndex,
6601
- finalDeltaY,
6602
- leadingWord: wordAtOffset,
6603
- height,
6604
- rowIndex,
6605
- columnIndex,
6606
- editorUid
7154
+ resizedWidth: newWidth
6607
7155
  };
6608
7156
  };
6609
- const advance = (state, word) => {
6610
- const filteredItems = filterCompletionItems(state.items, word);
7157
+ const handleSashPointerUp = (state, eventX, eventY) => {
7158
+ return state;
7159
+ };
7160
+
7161
+ const text = data => {
6611
7162
  return {
6612
- ...state,
6613
- filteredItems
7163
+ type: Text,
7164
+ text: data,
7165
+ childCount: 0
6614
7166
  };
6615
7167
  };
6616
7168
 
6617
- const getEdits = async (state, editor, completionItem) => {
6618
- // @ts-ignore
6619
- const {
6620
- leadingWord,
6621
- uid
6622
- } = state;
6623
- const word = completionItem.label;
6624
- const resolvedItem = await resolveCompletion(editor, word, completionItem);
6625
- const inserted = resolvedItem ? resolvedItem.snippet : word;
6626
- // TODO type and dispose commands should be sent to renderer process at the same time
6627
- const {
6628
- selections
6629
- } = editor;
6630
- const [startRowIndex, startColumnIndex] = selections;
6631
- const leadingWordLength = leadingWord.length;
6632
- const replaceRange$1 = new Uint32Array([startRowIndex, startColumnIndex - leadingWordLength, startRowIndex, startColumnIndex]);
6633
- const changes = replaceRange(editor, replaceRange$1, [inserted], '');
6634
- return changes;
6635
- };
6636
- const select = async (state, editor, completionItem) => {
6637
- const changes = await getEdits(state, editor, completionItem);
6638
- const index = editor.widgets.indexOf
6639
- // ViewletModuleId.EditorCompletion
6640
- ();
6641
- if (index !== -1) {
6642
- editor.widgets.splice(index, 1);
6643
- editor.completionState = None;
6644
- editor.completionUid = 0;
7169
+ const getLineInfoVirtualDom = lineInfo => {
7170
+ const dom = [{
7171
+ type: Div,
7172
+ className: HoverEditorRow,
7173
+ childCount: lineInfo.length / 2
7174
+ }];
7175
+ for (let i = 0; i < lineInfo.length; i += 2) {
7176
+ const tokenText = lineInfo[i];
7177
+ const tokenClass = lineInfo[i + 1];
7178
+ dom.push({
7179
+ type: Span,
7180
+ className: tokenClass,
7181
+ childCount: 1
7182
+ },
7183
+ // @ts-ignore
7184
+ text(tokenText));
7185
+ }
7186
+ return dom;
7187
+ };
7188
+ const getLineInfosVirtualDom = lineInfos => {
7189
+ const dom = lineInfos.flatMap(getLineInfoVirtualDom);
7190
+ return dom;
7191
+ };
7192
+
7193
+ const hoverProblemMessage = {
7194
+ type: Span,
7195
+ className: HoverProblemMessage,
7196
+ childCount: 1
7197
+ };
7198
+ const hoverProblemDetail = {
7199
+ type: Span,
7200
+ className: HoverProblemDetail,
7201
+ childCount: 1
7202
+ };
7203
+ const getChildCount = (lineInfos, documentation, diagnostics) => {
7204
+ return lineInfos.length + documentation ? 1 : 0 + (diagnostics && diagnostics.length > 0) ? 1 : 0;
7205
+ };
7206
+ const getHoverVirtualDom = (lineInfos, documentation, diagnostics) => {
7207
+ const dom = [];
7208
+ dom.push({
7209
+ type: Div,
7210
+ className: 'Viewlet EditorHover',
7211
+ childCount: getChildCount(lineInfos, documentation, diagnostics) + 1
7212
+ });
7213
+ if (diagnostics && diagnostics.length > 0) {
7214
+ dom.push({
7215
+ type: Div,
7216
+ className: `${HoverDisplayString} ${HoverProblem}`,
7217
+ childCount: diagnostics.length * 2
7218
+ });
7219
+ for (const diagnostic of diagnostics) {
7220
+ dom.push(hoverProblemMessage, text(diagnostic.message), hoverProblemDetail, text(`${diagnostic.source} (${diagnostic.code})`));
7221
+ }
7222
+ }
7223
+ if (lineInfos.length > 0) {
7224
+ const lineInfosDom = getLineInfosVirtualDom(lineInfos);
7225
+ dom.push({
7226
+ type: Div,
7227
+ className: HoverDisplayString,
7228
+ childCount: lineInfos.length
7229
+ }, ...lineInfosDom);
7230
+ }
7231
+ if (documentation) {
7232
+ dom.push({
7233
+ type: Div,
7234
+ className: HoverDocumentation,
7235
+ childCount: 1
7236
+ }, text(documentation));
7237
+ }
7238
+ dom.push({
7239
+ type: Div,
7240
+ className: 'Sash SashVertical SashResize',
7241
+ childCount: 0,
7242
+ onPointerDown: HandleSashPointerDown
7243
+ });
7244
+ return dom;
7245
+ };
7246
+
7247
+ const renderHoverDom = {
7248
+ isEqual(oldState, newState) {
7249
+ return oldState.lineInfos === newState.lineInfos && oldState.documentation === newState.documentation && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.diagnostics === newState.diagnostics;
7250
+ },
7251
+ apply(oldState, newState) {
7252
+ const dom = getHoverVirtualDom(newState.lineInfos, newState.documentation, newState.diagnostics);
7253
+ return [/* method */'Viewlet.setDom2', dom];
6645
7254
  }
6646
- await invoke$3('Editor.applyEdit', changes);
6647
- await invoke$3('Viewlet.dispose', state.uid);
6648
- return state;
6649
7255
  };
6650
- const selectIndex = (editorUid, state, index) => {
6651
- const editor = getEditor(editorUid);
6652
- const {
6653
- items
6654
- } = state;
6655
- if (index === -1) {
6656
- return state;
6657
- }
6658
- if (index > items.length) {
6659
- throw new Error('index too large');
7256
+ const renderBounds$1 = {
7257
+ isEqual(oldState, newState) {
7258
+ return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
7259
+ },
7260
+ apply(oldState, newState) {
7261
+ // @ts-ignore
7262
+ const {
7263
+ x,
7264
+ y,
7265
+ width,
7266
+ height,
7267
+ resizedWidth,
7268
+ uid
7269
+ } = newState;
7270
+ console.log('apply');
7271
+ return [SetBounds, x, y, resizedWidth, height];
6660
7272
  }
6661
- const actualIndex = index;
6662
- const completionItem = items[actualIndex];
6663
- return select(state, editor, completionItem);
6664
7273
  };
6665
-
6666
- const selectCurrent = (editorUid, state) => {
6667
- const {
6668
- focusedIndex
6669
- } = state;
6670
- return selectIndex(editorUid, state, focusedIndex);
7274
+ const render$2 = [renderHoverDom, renderBounds$1];
7275
+ const renderHover = async (oldState, newState) => {
7276
+ const commands = [];
7277
+ for (const item of render$2) {
7278
+ if (!item.isEqual(oldState, newState)) {
7279
+ commands.push(item.apply(oldState, newState));
7280
+ }
7281
+ }
7282
+ return commands;
6671
7283
  };
6672
7284
 
6673
7285
  // copied from https://github.com/microsoft/vscode/tree/main/src/vs/base/common/strings.ts by Microsoft (License MIT)
@@ -6714,7 +7326,7 @@ const getMatchCount = matches => {
6714
7326
  return matches.length / 2;
6715
7327
  };
6716
7328
 
6717
- const loadContent$1 = editorId => {
7329
+ const loadContent = editorId => {
6718
7330
  const editor = getEditor(editorId);
6719
7331
  const {
6720
7332
  selections,
@@ -6842,251 +7454,49 @@ const loadFont = async (fontName, fontUrl) => {
6842
7454
  string(fontName);
6843
7455
  string(fontUrl);
6844
7456
  if (fontName.startsWith("'")) {
6845
- throw new Error('font name is not allowed start with quotes');
6846
- }
6847
- const fontFace = new FontFace(fontName, fontUrl, {});
6848
- await fontFace.load();
6849
- const fonts = getFonts();
6850
- // @ts-ignore
6851
- fonts.add(fontFace);
6852
- } catch (error) {
6853
- throw new VError$1(error, `Failed to load font ${fontName}`);
6854
- }
6855
- };
6856
-
6857
- const load = async (fontName, fontUrl) => {
6858
- return loadFont(fontName, fontUrl);
6859
- };
6860
- const ensure = async (fontName, fontUrl) => {
6861
- if (isLoaded(fontName)) {
6862
- return;
6863
- }
6864
- if (hasPending(fontName)) {
6865
- return getPending(fontName);
6866
- }
6867
- const promise = load(fontName, fontUrl);
6868
- setPending(fontName, promise);
6869
- await promise;
6870
- removePending(fontName);
6871
- setLoaded(fontName);
6872
- };
6873
-
6874
- const getSelections = editorUid => {
6875
- const editor = getEditor(editorUid);
6876
- const {
6877
- selections
6878
- } = editor;
6879
- return selections;
6880
- };
6881
-
6882
- const executeHoverProvider = (editor, offset) => {
6883
- object(editor);
6884
- number$1(offset);
6885
- return execute({
6886
- event: OnHover,
6887
- editor,
6888
- method: HoverExecute,
6889
- args: [offset],
6890
- noProviderFoundMessage: 'No hover provider found'
6891
- });
6892
- };
6893
-
6894
- const getHover = async (editor, offset) => {
6895
- object(editor);
6896
- number$1(offset);
6897
- // TODO invoke extension host worker directly
6898
- const hover = await executeHoverProvider(editor, offset);
6899
- return hover;
6900
- };
6901
-
6902
- let _ipc;
6903
- const listen$5 = async () => {
6904
- const ipc = await create$1({
6905
- method: RendererProcess
6906
- });
6907
- handleIpc(ipc);
6908
- _ipc = ipc;
6909
- };
6910
- const invoke = async (method, ...args) => {
6911
- return invoke$5(_ipc, method, ...args);
6912
- };
6913
-
6914
- const measureTextBlockHeight = (text, fontFamily, fontSize, lineHeight, width) => {
6915
- return invoke('MeasureTextBlockHeight.measureTextBlockHeight', text, fontSize, fontFamily, lineHeight, width);
6916
- };
6917
-
6918
- const deepCopy = value => {
6919
- return structuredClone(value);
6920
- };
6921
-
6922
- const getInitialLineState = initialLineState => {
6923
- return deepCopy(initialLineState);
6924
- };
6925
-
6926
- const getLineInfo$1 = (line, tokens, TokenMap) => {
6927
- const tokensLength = tokens.length;
6928
- let end = 0;
6929
- let start = 0;
6930
- const lineInfo = [];
6931
- for (let i = 0; i < tokensLength; i += 2) {
6932
- const tokenType = tokens[i];
6933
- const tokenLength = tokens[i + 1];
6934
- end += tokenLength;
6935
- const text = line.slice(start, end);
6936
- const className = `Token ${TokenMap[tokenType] || 'Unknown'}`;
6937
- const normalizedText = text;
6938
- lineInfo.push(normalizedText, className);
6939
- start = end;
6940
- }
6941
- return lineInfo;
6942
- };
6943
-
6944
- const state = {
6945
- warned: []
6946
- };
6947
- const flattenTokensArray = tokens => {
6948
- const flattened = [];
6949
- for (const token of tokens) {
6950
- object(token);
6951
- flattened.push(token.type, token.length);
6952
- }
6953
- return flattened;
6954
- };
6955
- const warnDeprecatedArrayReturn = (languageId, fn) => {
6956
- if (state.warned.includes(fn)) {
6957
- return;
6958
- }
6959
- state.warned.push(fn);
6960
- console.warn(`tokenizers without hasArrayReturn=false are deprecated (language ${languageId})`);
6961
- };
6962
- const safeTokenizeLine = (languageId, tokenizeLine, line, lineStateAtStart, hasArrayReturn) => {
6963
- try {
6964
- const lineState = tokenizeLine(line, lineStateAtStart);
6965
- if (!lineState || !lineState.tokens || !lineState.state) {
6966
- throw new Error('invalid tokenization result');
6967
- }
6968
- if (!hasArrayReturn) {
6969
- warnDeprecatedArrayReturn(languageId, tokenizeLine);
6970
- // workaround for old tokenizers
6971
- lineState.tokens = flattenTokensArray(lineState.tokens);
6972
- }
6973
- return lineState;
6974
- } catch (error) {
6975
- console.error(error);
6976
- return {
6977
- tokens: [/* type */0, /* length */line.length],
6978
- lineState: lineStateAtStart
6979
- };
6980
- }
6981
- };
6982
-
6983
- const getLineInfos = (lines, tokenizer, languageId) => {
6984
- const lineInfos = [];
6985
- const {
6986
- tokenizeLine,
6987
- initialLineState,
6988
- hasArrayReturn,
6989
- TokenMap
6990
- } = tokenizer;
6991
- let currentLineState = getInitialLineState(initialLineState);
6992
- for (const line of lines) {
6993
- const result = safeTokenizeLine(languageId, tokenizeLine, line, currentLineState, hasArrayReturn);
6994
- const {
6995
- tokens
6996
- } = result;
6997
- const lineInfo = getLineInfo$1(line, tokens, TokenMap);
6998
- lineInfos.push(lineInfo);
6999
- currentLineState = result;
7000
- }
7001
- return lineInfos;
7002
- };
7003
-
7004
- const tokenizeCodeBlock = async (codeBlock, languageId, tokenizerPath) => {
7005
- await loadTokenizer(languageId, tokenizerPath);
7006
- const tokenizer = getTokenizer(languageId);
7007
- const lines = splitLines$2(codeBlock);
7008
- const lineInfos = getLineInfos(lines, tokenizer, languageId);
7009
- return lineInfos;
7010
- };
7011
-
7012
- const getHoverPosition = (position, selections) => {
7013
- if (position) {
7014
- return position;
7015
- }
7016
- const rowIndex = selections[0];
7017
- const columnIndex = selections[1];
7018
- return {
7019
- rowIndex,
7020
- columnIndex
7021
- };
7022
- };
7023
- const getMatchingDiagnostics = (diagnostics, rowIndex, columnIndex) => {
7024
- const matching = [];
7025
- for (const diagnostic of diagnostics) {
7026
- if (diagnostic.rowIndex === rowIndex) {
7027
- matching.push(diagnostic);
7457
+ throw new Error('font name is not allowed start with quotes');
7028
7458
  }
7459
+ const fontFace = new FontFace(fontName, fontUrl, {});
7460
+ await fontFace.load();
7461
+ const fonts = getFonts();
7462
+ // @ts-ignore
7463
+ fonts.add(fontFace);
7464
+ } catch (error) {
7465
+ throw new VError$1(error, `Failed to load font ${fontName}`);
7029
7466
  }
7030
- return matching;
7031
7467
  };
7032
- const fallbackDisplayStringLanguageId = 'typescript'; // TODO remove this
7033
7468
 
7034
- const hoverDocumentationFontSize = 15;
7035
- const hoverDocumentationFontFamily = 'Fira Code';
7036
- const hoverDocumentationLineHeight = '1.33333';
7037
- const hoverBorderLeft = 1;
7038
- const hoverBorderRight = 1;
7039
- const hoverPaddingLeft = 8;
7040
- const hoverPaddingRight = 8;
7041
- const hovverFullWidth = 400;
7042
- const hoverDocumentationWidth = hovverFullWidth - hoverPaddingLeft - hoverPaddingRight - hoverBorderLeft - hoverBorderRight;
7043
- const getHoverPositionXy = (editor, rowIndex, wordStart, documentationHeight) => {
7044
- const x$1 = x(editor, rowIndex, wordStart);
7045
- const y$1 = editor.height - y(editor, rowIndex) + editor.y + 40;
7046
- return {
7047
- x: x$1,
7048
- y: y$1
7049
- };
7469
+ const load = async (fontName, fontUrl) => {
7470
+ return loadFont(fontName, fontUrl);
7050
7471
  };
7051
- const getEditorHoverInfo = async (editorUid, position) => {
7052
- number$1(editorUid);
7053
- const instance = get$6(editorUid);
7054
- const editor = instance.newState;
7472
+ const ensure = async (fontName, fontUrl) => {
7473
+ if (isLoaded(fontName)) {
7474
+ return;
7475
+ }
7476
+ if (hasPending(fontName)) {
7477
+ return getPending(fontName);
7478
+ }
7479
+ const promise = load(fontName, fontUrl);
7480
+ setPending(fontName, promise);
7481
+ await promise;
7482
+ removePending(fontName);
7483
+ setLoaded(fontName);
7484
+ };
7485
+
7486
+ const getSelections = editorUid => {
7487
+ const editor = getEditor(editorUid);
7055
7488
  const {
7056
7489
  selections
7057
7490
  } = editor;
7491
+ return selections;
7492
+ };
7493
+
7494
+ const getText = editorUid => {
7495
+ const editor = getEditor(editorUid);
7058
7496
  const {
7059
- rowIndex,
7060
- columnIndex
7061
- } = getHoverPosition(position, selections);
7062
- const offset = offsetAt(editor, rowIndex, columnIndex);
7063
- const hover = await getHover(editor, offset);
7064
- if (!hover) {
7065
- return undefined;
7066
- }
7067
- const {
7068
- displayString,
7069
- documentation,
7070
- displayStringLanguageId
7071
- } = hover;
7072
- const tokenizerPath = '';
7073
- const lineInfos = await tokenizeCodeBlock(displayString, displayStringLanguageId || fallbackDisplayStringLanguageId, tokenizerPath);
7074
- const wordPart = await getWordBefore(editor, rowIndex, columnIndex);
7075
- const wordStart = columnIndex - wordPart.length;
7076
- await measureTextBlockHeight(documentation, hoverDocumentationFontFamily, hoverDocumentationFontSize, hoverDocumentationLineHeight, hoverDocumentationWidth);
7077
- const {
7078
- x,
7079
- y
7080
- } = getHoverPositionXy(editor, rowIndex, wordStart);
7081
- const diagnostics = editor.diagnostics || [];
7082
- const matchingDiagnostics = getMatchingDiagnostics(diagnostics, rowIndex);
7083
- return {
7084
- lineInfos,
7085
- documentation,
7086
- x,
7087
- y,
7088
- matchingDiagnostics
7089
- };
7497
+ lines
7498
+ } = editor;
7499
+ return lines.join('\n');
7090
7500
  };
7091
7501
 
7092
7502
  const InsertText = 'insertText';
@@ -7170,7 +7580,7 @@ const moveLineUp = editor => {
7170
7580
  };
7171
7581
 
7172
7582
  const Link$1 = 'Link';
7173
- const Function = 'Function';
7583
+ const Function$1 = 'Function';
7174
7584
  const Parameter = 'Parameter';
7175
7585
  const Type = 'Type';
7176
7586
  const VariableName = 'VariableName';
@@ -7229,7 +7639,7 @@ const getDecorationClassName = type => {
7229
7639
  case Ts3073:
7230
7640
  case Ts3077:
7231
7641
  case Ts3088:
7232
- return Function;
7642
+ return Function$1;
7233
7643
  case Ts1792:
7234
7644
  case Ts1793:
7235
7645
  return Parameter;
@@ -7655,29 +8065,6 @@ const getVisible = async (editor, syncIncremental) => {
7655
8065
  };
7656
8066
  };
7657
8067
 
7658
- const Div = 4;
7659
- const Span = 8;
7660
- const Text = 12;
7661
-
7662
- const ColorPicker = 'ColorPicker';
7663
- const ColorPickerBackgroundColor = 'ColorPickerBackgroundColor';
7664
- const ColorPickerDark = 'ColorPickerDark';
7665
- const ColorPickerLight = 'ColorPickerLight';
7666
- const ColorPickerRectangle = 'ColorPickerRectangle';
7667
- const ColorPickerSlider = 'ColorPickerSlider';
7668
- const ColorPickerSliderThumb = 'ColorPickerSliderThumb';
7669
- const Diagnostic = 'Diagnostic';
7670
- const EditorCursor = 'EditorCursor';
7671
- const EditorRow = 'EditorRow';
7672
- const EditorSelection = 'EditorSelection';
7673
- const HoverDisplayString = 'HoverDisplayString';
7674
- const HoverDocumentation = 'HoverDocumentation';
7675
- const HoverEditorRow = 'HoverEditorRow';
7676
- const HoverProblem = 'HoverProblem';
7677
- const HoverProblemDetail = 'HoverProblemDetail';
7678
- const HoverProblemMessage = 'HoverProblemMessage';
7679
- const Viewlet = 'Viewlet';
7680
-
7681
8068
  const getCursorsVirtualDom = cursors => {
7682
8069
  const dom = [];
7683
8070
  for (const translate of cursors) {
@@ -7729,14 +8116,6 @@ const getDiagnosticsVirtualDom = diagnostics => {
7729
8116
  return dom;
7730
8117
  };
7731
8118
 
7732
- const text = data => {
7733
- return {
7734
- type: Text,
7735
- text: data,
7736
- childCount: 0
7737
- };
7738
- };
7739
-
7740
8119
  const getGutterInfoVirtualDom = gutterInfo => {
7741
8120
  return [{
7742
8121
  type: Span,
@@ -7813,6 +8192,322 @@ const getSelectionsVirtualDom = selections => {
7813
8192
  return dom;
7814
8193
  };
7815
8194
 
8195
+ const None = 'none';
8196
+ const Option = 'option';
8197
+
8198
+ const getFileIconVirtualDom = icon => {
8199
+ return {
8200
+ type: Img,
8201
+ className: FileIcon,
8202
+ src: icon,
8203
+ role: None,
8204
+ childCount: 0
8205
+ };
8206
+ };
8207
+
8208
+ const getIconDom = (fileIcon, symbolName) => {
8209
+ if (fileIcon) {
8210
+ return getFileIconVirtualDom(fileIcon);
8211
+ }
8212
+ return {
8213
+ type: Div,
8214
+ className: `${ColoredMaskIcon} ${symbolName}`,
8215
+ childCount: 0
8216
+ };
8217
+ };
8218
+
8219
+ const label1 = {
8220
+ type: Div,
8221
+ className: Label,
8222
+ childCount: 1
8223
+ };
8224
+ const completionHighlight = {
8225
+ type: Span,
8226
+ className: EditorCompletionItemHighlight,
8227
+ childCount: 1
8228
+ };
8229
+ const getHighlightedLabelDom = (label, highlights) => {
8230
+ if (highlights.length === 0) {
8231
+ return [label1, text(label)];
8232
+ }
8233
+ const dom = [];
8234
+ const labelDom = {
8235
+ type: Div,
8236
+ className: Label,
8237
+ childCount: 0
8238
+ };
8239
+ dom.push(labelDom);
8240
+ let position = 0;
8241
+ for (let i = 0; i < highlights.length; i += 2) {
8242
+ const highlightStart = highlights[i];
8243
+ const highlightEnd = highlights[i + 1];
8244
+ if (position < highlightStart) {
8245
+ const beforeText = label.slice(position, highlightStart);
8246
+ labelDom.childCount++;
8247
+ dom.push(text(beforeText));
8248
+ }
8249
+ const highlightText = label.slice(highlightStart, highlightEnd);
8250
+ labelDom.childCount++;
8251
+ dom.push(completionHighlight, text(highlightText));
8252
+ position = highlightEnd;
8253
+ }
8254
+ if (position < label.length) {
8255
+ const afterText = label.slice(position);
8256
+ labelDom.childCount++;
8257
+ dom.push(text(afterText));
8258
+ }
8259
+ return dom;
8260
+ };
8261
+
8262
+ const getCompletionItemVirtualDom = visibleItem => {
8263
+ const {
8264
+ top,
8265
+ label,
8266
+ symbolName,
8267
+ highlights,
8268
+ focused,
8269
+ deprecated,
8270
+ fileIcon
8271
+ } = visibleItem;
8272
+ let className = EditorCompletionItem;
8273
+ if (focused) {
8274
+ className += ' ' + EditorCompletionItemFocused;
8275
+ }
8276
+ if (deprecated) {
8277
+ className += ' ' + EditorCompletionItemDeprecated;
8278
+ }
8279
+ return [{
8280
+ type: Div,
8281
+ role: Option,
8282
+ className,
8283
+ top,
8284
+ childCount: 2
8285
+ }, getIconDom(fileIcon, symbolName), ...getHighlightedLabelDom(label, highlights)];
8286
+ };
8287
+
8288
+ const getCompletionItemsVirtualDom = visibleItems => {
8289
+ if (visibleItems.length === 0) {
8290
+ return [{
8291
+ type: Div,
8292
+ childCount: 1
8293
+ }, text(noResults())];
8294
+ }
8295
+ const root = {
8296
+ type: Div,
8297
+ childCount: visibleItems.length
8298
+ };
8299
+ const dom = [root, ...visibleItems.flatMap(getCompletionItemVirtualDom)];
8300
+ return dom;
8301
+ };
8302
+
8303
+ const Property = 1;
8304
+ const Value = 2;
8305
+ const Function = 3;
8306
+ const Variable = 4;
8307
+ const Keyword = 5;
8308
+ const Folder = 6;
8309
+ const File = 7;
8310
+ const Field = 8;
8311
+
8312
+ const SymbolProperty = 'SymbolProperty';
8313
+ const SymbolValue = 'SymbolValue';
8314
+ const SymbolFunction = 'SymbolFunction';
8315
+ const SymbolVariable = 'SymbolVariable';
8316
+ const SymbolKeyword = 'SymbolKeyword';
8317
+ const SymbolDefault = 'SymbolDefault';
8318
+ const SymbolField = 'SymbolField';
8319
+ const SymbolNone = '';
8320
+
8321
+ const getSymbolName = item => {
8322
+ switch (item.kind) {
8323
+ case Property:
8324
+ return SymbolProperty;
8325
+ case Value:
8326
+ return SymbolValue;
8327
+ case Function:
8328
+ return SymbolFunction;
8329
+ case Variable:
8330
+ return SymbolVariable;
8331
+ case Keyword:
8332
+ return SymbolKeyword;
8333
+ case Field:
8334
+ return SymbolField;
8335
+ case File:
8336
+ return SymbolNone;
8337
+ default:
8338
+ return SymbolDefault;
8339
+ }
8340
+ };
8341
+
8342
+ const getHighlights = (item, leadingWord) => {
8343
+ const {
8344
+ matches
8345
+ } = item;
8346
+ return matches.slice(1);
8347
+ };
8348
+
8349
+ // import * as IconTheme from '../IconTheme/IconTheme.ts'
8350
+
8351
+ const getLabel = item => {
8352
+ return item.label;
8353
+ };
8354
+ const getFileIcon = item => {
8355
+ switch (item.kind) {
8356
+ case File:
8357
+ // TODO IconTheme.getFileNameIcon(item.label)
8358
+ return '';
8359
+ case Folder:
8360
+ // TODO IconTheme.getFolderNameIcon(item.label)
8361
+ return '';
8362
+ default:
8363
+ return '';
8364
+ }
8365
+ };
8366
+ const getVisibleIem = (item, itemHeight, leadingWord, i, focusedIndex) => {
8367
+ return {
8368
+ label: getLabel(item),
8369
+ symbolName: getSymbolName(item),
8370
+ top: i * itemHeight,
8371
+ highlights: getHighlights(item),
8372
+ focused: i === focusedIndex,
8373
+ deprecated: item.flags & Deprecated,
8374
+ fileIcon: getFileIcon(item)
8375
+ };
8376
+ };
8377
+
8378
+ const getVisibleItems = (filteredItems, itemHeight, leadingWord, minLineY, maxLineY, focusedIndex) => {
8379
+ const visibleItems = [];
8380
+ for (let i = minLineY; i < maxLineY; i++) {
8381
+ const filteredItem = filteredItems[i];
8382
+ visibleItems.push(getVisibleIem(filteredItem, itemHeight, leadingWord, i, focusedIndex));
8383
+ }
8384
+ return visibleItems;
8385
+ };
8386
+
8387
+ const renderItems = {
8388
+ isEqual(oldState, newState) {
8389
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex;
8390
+ },
8391
+ apply(oldState, newState) {
8392
+ const visibleItems = getVisibleItems(newState.items, newState.itemHeight, newState.leadingWord, newState.minLineY, newState.maxLineY, newState.focusedIndex);
8393
+ const dom = getCompletionItemsVirtualDom(visibleItems);
8394
+ return ['setDom', dom];
8395
+ }
8396
+ };
8397
+ const renderBounds = {
8398
+ isEqual(oldState, newState) {
8399
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.x === newState.x && oldState.y === newState.y;
8400
+ },
8401
+ apply(oldState, newState) {
8402
+ const {
8403
+ x,
8404
+ y,
8405
+ width,
8406
+ height
8407
+ } = newState;
8408
+ return [/* method */SetBounds, /* x */x, /* y */y, /* width */width, /* height */height];
8409
+ }
8410
+ };
8411
+ const renderHeight = {
8412
+ isEqual(oldState, newState) {
8413
+ return oldState.items.length === newState.items.length;
8414
+ },
8415
+ apply(oldState, newState) {
8416
+ const {
8417
+ itemHeight
8418
+ } = newState;
8419
+ const contentHeight = newState.items.length * itemHeight;
8420
+ return [/* method */SetContentHeight, /* contentHeight */contentHeight];
8421
+ }
8422
+ };
8423
+ const renderNegativeMargin = {
8424
+ isEqual(oldState, newState) {
8425
+ return oldState.deltaY === newState.deltaY;
8426
+ },
8427
+ apply(oldState, newState) {
8428
+ return [/* method */SetNegativeMargin, /* negativeMargin */-newState.deltaY];
8429
+ }
8430
+ };
8431
+ const renderScrollBar = {
8432
+ isEqual(oldState, newState) {
8433
+ return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length;
8434
+ },
8435
+ apply(oldState, newState) {
8436
+ const total = newState.items.length;
8437
+ const contentHeight = total * newState.itemHeight;
8438
+ const scrollBarHeight = getScrollBarSize(newState.height, contentHeight, newState.minimumSliderSize);
8439
+ const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
8440
+ return [/* method */SetScrollBar, /* scrollBarY */scrollBarY, /* scrollBarHeight */scrollBarHeight];
8441
+ }
8442
+ };
8443
+ const render$1 = [renderItems, renderBounds, renderHeight, renderNegativeMargin, renderScrollBar];
8444
+ const renderCompletion$1 = (oldState, newState) => {
8445
+ const commands = [];
8446
+ for (const item of render$1) {
8447
+ if (!item.isEqual(oldState, newState)) {
8448
+ commands.push(item.apply(oldState, newState));
8449
+ }
8450
+ }
8451
+ return commands;
8452
+ };
8453
+
8454
+ const renderCompletion = (oldState, newState) => {
8455
+ const commands = renderCompletion$1(oldState, newState);
8456
+ const wrappedCommands = [];
8457
+ const uid = newState.uid;
8458
+ for (const command of commands) {
8459
+ wrappedCommands.push(['Viewlet.send', uid, ...command]);
8460
+ }
8461
+ return wrappedCommands;
8462
+ };
8463
+ const addWidgetCompletion = widget => {
8464
+ const commands = renderCompletion(widget.oldState, widget.newState);
8465
+ const id = 'EditorCompletion';
8466
+ // TODO how to generate a unique integer id
8467
+ // that doesn't collide with ids created in renderer worker?
8468
+ const uid = widget.newState.uid;
8469
+ const allCommands = [];
8470
+ allCommands.push(['Viewlet.create', id, uid]);
8471
+ allCommands.push(...commands);
8472
+ return allCommands;
8473
+ };
8474
+ const addWidget = widget => {
8475
+ const {
8476
+ id
8477
+ } = widget;
8478
+ switch (id) {
8479
+ case 'completion':
8480
+ return addWidgetCompletion(widget);
8481
+ default:
8482
+ throw new Error('unsupported widget');
8483
+ }
8484
+ };
8485
+ const renderWidget = widget => {
8486
+ const {
8487
+ id
8488
+ } = widget;
8489
+ switch (id) {
8490
+ case 'completion':
8491
+ return renderCompletion(widget.oldState, widget.newState);
8492
+ default:
8493
+ throw new Error(`unsupported widget`);
8494
+ }
8495
+ };
8496
+ const removeCompletion = widget => {
8497
+ return [['Viewlet.send', widget.newState.uid, 'dispose']];
8498
+ };
8499
+ const removeWidget = widget => {
8500
+ const {
8501
+ id
8502
+ } = widget;
8503
+ switch (id) {
8504
+ case 'completion':
8505
+ return removeCompletion(widget);
8506
+ default:
8507
+ throw new Error('unsupported widget');
8508
+ }
8509
+ };
8510
+
7816
8511
  const renderLines = {
7817
8512
  isEqual(oldState, newState) {
7818
8513
  return oldState.lines === newState.lines && oldState.tokenizerId === newState.tokenizerId && oldState.minLineY === newState.minLineY && oldState.decorations === newState.decorations && oldState.embeds === newState.embeds && oldState.deltaX === newState.deltaX && oldState.width === newState.width;
@@ -7905,11 +8600,67 @@ const renderGutterInfo = {
7905
8600
  gutterInfos.push(i + 1);
7906
8601
  }
7907
8602
  }
7908
- const dom = getEditorGutterVirtualDom(gutterInfos);
7909
- return ['renderGutter', dom];
7910
- }
8603
+ const dom = getEditorGutterVirtualDom(gutterInfos);
8604
+ return ['renderGutter', dom];
8605
+ }
8606
+ };
8607
+ const renderWidgets = {
8608
+ isEqual(oldState, newState) {
8609
+ return oldState.widgets === newState.widgets;
8610
+ },
8611
+ apply(oldState, newState) {
8612
+ const addedWidgets = [];
8613
+ const changedWidgets = [];
8614
+ const removedWidgets = [];
8615
+ const oldWidgets = oldState.widgets || [];
8616
+ const newWidgets = newState.widgets || [];
8617
+ const oldWidgetMap = Object.create(null);
8618
+ const newWidgetMap = Object.create(null);
8619
+ for (const oldWidget of oldWidgets) {
8620
+ oldWidgetMap[oldWidget.id] = oldWidget;
8621
+ }
8622
+ for (const newWidget of newWidgets) {
8623
+ newWidgetMap[newWidget.id] = newWidget;
8624
+ }
8625
+ for (const oldWidget of oldWidgets) {
8626
+ if (oldWidget.id in newWidgetMap) {
8627
+ changedWidgets.push(newWidgetMap[oldWidget.id]);
8628
+ } else {
8629
+ removedWidgets.push(oldWidget);
8630
+ }
8631
+ }
8632
+ for (const newWidget of newWidgets) {
8633
+ if (newWidget.id in oldWidgetMap) ; else {
8634
+ addedWidgets.push(newWidget);
8635
+ }
8636
+ }
8637
+ const addCommands = [];
8638
+ for (const addedWidget of addedWidgets) {
8639
+ const childCommands = addWidget(addedWidget);
8640
+ if (childCommands.length > 0) {
8641
+ addCommands.push(...childCommands);
8642
+ }
8643
+ }
8644
+ const changeCommands = [];
8645
+ for (const changedWidget of changedWidgets) {
8646
+ const childCommands = renderWidget(changedWidget);
8647
+ if (childCommands.length > 0) {
8648
+ changeCommands.push(...childCommands);
8649
+ }
8650
+ }
8651
+ const removeCommands = [];
8652
+ for (const removedWidget of removedWidgets) {
8653
+ const childCommands = removeWidget(removedWidget);
8654
+ if (childCommands.length > 0) {
8655
+ removeCommands.push(...childCommands);
8656
+ }
8657
+ }
8658
+ const allCommands = [...addCommands, ...changeCommands, ...removeCommands];
8659
+ return allCommands;
8660
+ },
8661
+ multiple: true
7911
8662
  };
7912
- const render$2 = [renderLines, renderSelections, renderScrollBarX, renderScrollBarY, renderFocus, renderDecorations, renderGutterInfo];
8663
+ const render = [renderLines, renderSelections, renderScrollBarX, renderScrollBarY, renderFocus, renderDecorations, renderGutterInfo, renderWidgets];
7913
8664
  const renderEditor = async id => {
7914
8665
  const instance = get$6(id);
7915
8666
  if (!instance) {
@@ -7921,15 +8672,30 @@ const renderEditor = async id => {
7921
8672
  } = instance;
7922
8673
  const commands = [];
7923
8674
  set$6(id, newState, newState);
7924
- for (const item of render$2) {
8675
+ for (const item of render) {
7925
8676
  if (!item.isEqual(oldState, newState)) {
7926
- commands.push(await item.apply(oldState, newState));
8677
+ const result = await item.apply(oldState, newState);
8678
+ // @ts-ignore
8679
+ if (item.multiple) {
8680
+ commands.push(...result);
8681
+ } else if (result.length > 0) {
8682
+ commands.push(result);
8683
+ }
7927
8684
  }
7928
8685
  }
7929
8686
  return commands;
7930
8687
  };
7931
8688
 
7932
- const keep = ['ColorPicker.handleSliderPointerDown', 'ColorPicker.handleSliderPointerMove', 'ColorPicker.loadContent', 'Editor.create', 'Editor.getWordAt', 'Editor.getWordBefore', 'Editor.offsetAt', 'Editor.render', 'ColorPicker.render', 'Editor.getText', 'Editor.getSelections', 'EditorCompletion.advance', 'EditorCompletion.handleEditorBlur', 'EditorCompletion.handleEditorClick', 'EditorCompletion.handleEditorDeleteLeft', 'EditorCompletion.handleEditorType', 'EditorCompletion.loadContent', 'EditorCompletion.selectCurrent', 'EditorCompletion.selectIndex', 'FindWidget.focusFirst', 'FindWidget.focusIndex', 'FindWidget.focusLast', 'FindWidget.focusNext', 'FindWidget.focusPrevious', 'FindWidget.handleInput', 'FindWidget.loadContent', 'Font.ensure', 'Hover.getHoverInfo', 'Hover.handleSashPointerDown', 'Hover.handleSashPointerMove', 'Hover.handleSashPointerUp', 'Hover.loadContent', 'Hover.render', 'Initialize.initialize'];
8689
+ const keep = ['ColorPicker.handleSliderPointerDown', 'ColorPicker.handleSliderPointerMove', 'ColorPicker.loadContent', 'Editor.create', 'Editor.getWordAt', 'Editor.getWordBefore', 'Editor.offsetAt', 'Editor.render', 'ColorPicker.render', 'Editor.getText', 'Editor.getSelections',
8690
+ // 'EditorCompletion.advance',
8691
+ // 'EditorCompletion.handleEditorBlur',
8692
+ // 'EditorCompletion.handleEditorClick',
8693
+ // 'EditorCompletion.handleEditorDeleteLeft',
8694
+ // 'EditorCompletion.handleEditorType',
8695
+ // 'EditorCompletion.loadContent',
8696
+ // 'EditorCompletion.selectCurrent',
8697
+ // 'EditorCompletion.selectIndex',
8698
+ 'FindWidget.focusFirst', 'FindWidget.focusIndex', 'FindWidget.focusLast', 'FindWidget.focusNext', 'FindWidget.focusPrevious', 'FindWidget.handleInput', 'FindWidget.loadContent', 'Font.ensure', 'Hover.getHoverInfo', 'Hover.handleSashPointerDown', 'Hover.handleSashPointerMove', 'Hover.handleSashPointerUp', 'Hover.loadContent', 'Hover.render', 'Initialize.initialize'];
7933
8699
 
7934
8700
  // TODO wrap commands globally, not per editor
7935
8701
  // TODO only store editor state in editor worker, not in renderer worker also
@@ -7951,243 +8717,6 @@ const wrapCommands = commands => {
7951
8717
  }
7952
8718
  };
7953
8719
 
7954
- const HandlePointerDown = 'handlePointerDown';
7955
- const HandleSashPointerDown = 'handleSashPointerDown';
7956
-
7957
- const mergeClassNames = (...classNames) => {
7958
- return classNames.filter(Boolean).join(' ');
7959
- };
7960
-
7961
- const getColorPickerVirtualDom = () => {
7962
- return [{
7963
- type: Div,
7964
- className: mergeClassNames(Viewlet, ColorPicker),
7965
- onPointerDown: HandlePointerDown,
7966
- childCount: 3
7967
- }, {
7968
- type: Div,
7969
- className: ColorPickerRectangle,
7970
- childCount: 3
7971
- }, {
7972
- type: Div,
7973
- className: ColorPickerBackgroundColor,
7974
- childCount: 0
7975
- }, {
7976
- type: Div,
7977
- className: ColorPickerLight,
7978
- childCount: 0
7979
- }, {
7980
- type: Div,
7981
- className: ColorPickerDark,
7982
- childCount: 0
7983
- }, {
7984
- type: Div,
7985
- className: ColorPickerSlider,
7986
- childCount: 0
7987
- }, {
7988
- type: Div,
7989
- className: ColorPickerSliderThumb,
7990
- childCount: 0
7991
- }];
7992
- };
7993
-
7994
- const SetBounds = 'setBounds';
7995
- const SetColor = 'setColor';
7996
- const SetOffsetX = 'setOffsetX';
7997
-
7998
- const renderColor = {
7999
- isEqual(oldState, newState) {
8000
- return oldState.color === newState.color;
8001
- },
8002
- apply(oldState, newState) {
8003
- return [/* method */SetColor, /* color */newState.color];
8004
- }
8005
- };
8006
- const renderOffsetX = {
8007
- isEqual(oldState, newState) {
8008
- return oldState.offsetX === newState.offsetX;
8009
- },
8010
- apply(oldState, newState) {
8011
- return [/* method */SetOffsetX, /* offsetX */newState.offsetX];
8012
- }
8013
- };
8014
- const renderColorPickerDom = {
8015
- isEqual(oldState, newState) {
8016
- return oldState.min === newState.min && oldState.max === newState.max;
8017
- },
8018
- apply(oldState, newState) {
8019
- const dom = getColorPickerVirtualDom();
8020
- return ['Viewlet.setDom2', dom];
8021
- }
8022
- };
8023
- const render$1 = [renderColorPickerDom, renderColor, renderOffsetX];
8024
- const renderColorPicker = async (oldState, newState) => {
8025
- const commands = [];
8026
- for (const item of render$1) {
8027
- if (!item.isEqual(oldState, newState)) {
8028
- commands.push(item.apply(oldState, newState));
8029
- }
8030
- }
8031
- return commands;
8032
- };
8033
-
8034
- const loadContent = async (editorUid, state, position) => {
8035
- const hoverInfo = await getEditorHoverInfo(editorUid, position);
8036
- if (!hoverInfo) {
8037
- return state;
8038
- }
8039
- const {
8040
- lineInfos,
8041
- documentation,
8042
- x,
8043
- y,
8044
- matchingDiagnostics
8045
- } = hoverInfo;
8046
- return {
8047
- ...state,
8048
- lineInfos,
8049
- documentation,
8050
- x,
8051
- y,
8052
- diagnostics: matchingDiagnostics
8053
- };
8054
- };
8055
- const handleSashPointerDown = (state, eventX, eventY) => {
8056
- return state;
8057
- };
8058
- const handleSashPointerMove = (state, eventX, eventY) => {
8059
- // @ts-ignore
8060
- const {
8061
- x,
8062
- y
8063
- } = state;
8064
- const minWidth = 100;
8065
- const newWidth = Math.max(eventX - x, minWidth);
8066
- return {
8067
- ...state,
8068
- resizedWidth: newWidth
8069
- };
8070
- };
8071
- const handleSashPointerUp = (state, eventX, eventY) => {
8072
- return state;
8073
- };
8074
-
8075
- const getLineInfoVirtualDom = lineInfo => {
8076
- const dom = [{
8077
- type: Div,
8078
- className: HoverEditorRow,
8079
- childCount: lineInfo.length / 2
8080
- }];
8081
- for (let i = 0; i < lineInfo.length; i += 2) {
8082
- const tokenText = lineInfo[i];
8083
- const tokenClass = lineInfo[i + 1];
8084
- dom.push({
8085
- type: Span,
8086
- className: tokenClass,
8087
- childCount: 1
8088
- },
8089
- // @ts-ignore
8090
- text(tokenText));
8091
- }
8092
- return dom;
8093
- };
8094
- const getLineInfosVirtualDom = lineInfos => {
8095
- const dom = lineInfos.flatMap(getLineInfoVirtualDom);
8096
- return dom;
8097
- };
8098
-
8099
- const hoverProblemMessage = {
8100
- type: Span,
8101
- className: HoverProblemMessage,
8102
- childCount: 1
8103
- };
8104
- const hoverProblemDetail = {
8105
- type: Span,
8106
- className: HoverProblemDetail,
8107
- childCount: 1
8108
- };
8109
- const getChildCount = (lineInfos, documentation, diagnostics) => {
8110
- return lineInfos.length + documentation ? 1 : 0 + (diagnostics && diagnostics.length > 0) ? 1 : 0;
8111
- };
8112
- const getHoverVirtualDom = (lineInfos, documentation, diagnostics) => {
8113
- const dom = [];
8114
- dom.push({
8115
- type: Div,
8116
- className: 'Viewlet EditorHover',
8117
- childCount: getChildCount(lineInfos, documentation, diagnostics) + 1
8118
- });
8119
- if (diagnostics && diagnostics.length > 0) {
8120
- dom.push({
8121
- type: Div,
8122
- className: `${HoverDisplayString} ${HoverProblem}`,
8123
- childCount: diagnostics.length * 2
8124
- });
8125
- for (const diagnostic of diagnostics) {
8126
- dom.push(hoverProblemMessage, text(diagnostic.message), hoverProblemDetail, text(`${diagnostic.source} (${diagnostic.code})`));
8127
- }
8128
- }
8129
- if (lineInfos.length > 0) {
8130
- const lineInfosDom = getLineInfosVirtualDom(lineInfos);
8131
- dom.push({
8132
- type: Div,
8133
- className: HoverDisplayString,
8134
- childCount: lineInfos.length
8135
- }, ...lineInfosDom);
8136
- }
8137
- if (documentation) {
8138
- dom.push({
8139
- type: Div,
8140
- className: HoverDocumentation,
8141
- childCount: 1
8142
- }, text(documentation));
8143
- }
8144
- dom.push({
8145
- type: Div,
8146
- className: 'Sash SashVertical SashResize',
8147
- childCount: 0,
8148
- onPointerDown: HandleSashPointerDown
8149
- });
8150
- return dom;
8151
- };
8152
-
8153
- const renderHoverDom = {
8154
- isEqual(oldState, newState) {
8155
- return oldState.lineInfos === newState.lineInfos && oldState.documentation === newState.documentation && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.diagnostics === newState.diagnostics;
8156
- },
8157
- apply(oldState, newState) {
8158
- const dom = getHoverVirtualDom(newState.lineInfos, newState.documentation, newState.diagnostics);
8159
- return [/* method */'Viewlet.setDom2', dom];
8160
- }
8161
- };
8162
- const renderBounds = {
8163
- isEqual(oldState, newState) {
8164
- return oldState.x === newState.x && oldState.y === newState.y && oldState.resizedWidth === newState.resizedWidth;
8165
- },
8166
- apply(oldState, newState) {
8167
- // @ts-ignore
8168
- const {
8169
- x,
8170
- y,
8171
- width,
8172
- height,
8173
- resizedWidth,
8174
- uid
8175
- } = newState;
8176
- console.log('apply');
8177
- return [SetBounds, x, y, resizedWidth, height];
8178
- }
8179
- };
8180
- const render = [renderHoverDom, renderBounds];
8181
- const renderHover = async (oldState, newState) => {
8182
- const commands = [];
8183
- for (const item of render) {
8184
- if (!item.isEqual(oldState, newState)) {
8185
- commands.push(item.apply(oldState, newState));
8186
- }
8187
- }
8188
- return commands;
8189
- };
8190
-
8191
8720
  const commandMap = {
8192
8721
  'ColorPicker.handleSliderPointerDown': handleSliderPointerDown,
8193
8722
  'ColorPicker.handleSliderPointerMove': handleSliderPointerMove,
@@ -8234,8 +8763,9 @@ const commandMap = {
8234
8763
  'Editor.deleteWordRight': deleteWordRight,
8235
8764
  'Editor.findAllReferences': findAllReferences,
8236
8765
  'Editor.format': format,
8237
- 'Editor.getWordAt': getWordAt,
8766
+ 'Editor.getSelections': getSelections,
8238
8767
  'Editor.getText': getText,
8768
+ 'Editor.getWordAt': getWordAt,
8239
8769
  'Editor.getWordBefore': getWordBefore,
8240
8770
  'Editor.goToDefinition': goToDefinition,
8241
8771
  'Editor.goToTypeDefinition': goToTypeDefinition,
@@ -8273,6 +8803,7 @@ const commandMap = {
8273
8803
  'Editor.moveSelection': editorMoveSelection,
8274
8804
  'Editor.moveSelectionPx': moveSelectionPx,
8275
8805
  'Editor.offsetAt': offsetAt,
8806
+ 'Editor.openCompletion': openCompletion,
8276
8807
  'Editor.openFind': openFind,
8277
8808
  'Editor.organizeImports': organizeImports,
8278
8809
  'Editor.paste': paste,
@@ -8312,8 +8843,11 @@ const commandMap = {
8312
8843
  'Editor.typeWithAutoClosing': typeWithAutoClosing,
8313
8844
  'Editor.undo': undo,
8314
8845
  'Editor.unIndent': editorUnindent,
8315
- 'Editor.getSelections': getSelections,
8316
8846
  'EditorCompletion.advance': advance,
8847
+ 'EditorCompletion.focusFirst': focusFirst$1,
8848
+ 'EditorCompletion.focusIndex': focusIndex$1,
8849
+ 'EditorCompletion.focusNext': focusNext$1,
8850
+ 'EditorCompletion.focusPrevious': focusPrevious$1,
8317
8851
  'EditorCompletion.handleEditorBlur': handleEditorBlur,
8318
8852
  'EditorCompletion.handleEditorClick': handleEditorClick,
8319
8853
  'EditorCompletion.handleEditorDeleteLeft': handleEditorDeleteLeft,
@@ -8327,14 +8861,14 @@ const commandMap = {
8327
8861
  'FindWidget.focusNext': focusNext,
8328
8862
  'FindWidget.focusPrevious': focusPrevious,
8329
8863
  'FindWidget.handleInput': handleInput,
8330
- 'FindWidget.loadContent': loadContent$1,
8864
+ 'FindWidget.loadContent': loadContent,
8331
8865
  'Font.ensure': ensure,
8332
8866
  'Hover.getHoverInfo': getEditorHoverInfo,
8333
8867
  'Hover.handleSashPointerDown': handleSashPointerDown,
8334
8868
  'Hover.handleSashPointerMove': handleSashPointerMove,
8335
8869
  'Hover.handleSashPointerUp': handleSashPointerUp,
8870
+ 'Hover.loadContent': loadContent$1,
8336
8871
  'Hover.render': renderHover,
8337
- 'Hover.loadContent': loadContent,
8338
8872
  'Initialize.initialize': intialize
8339
8873
  };
8340
8874
  wrapCommands(commandMap);