@theia/plugin-ext 1.32.0-next.8 → 1.32.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 (78) hide show
  1. package/lib/common/plugin-api-rpc-model.d.ts +3 -3
  2. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc.d.ts +3 -3
  4. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  5. package/lib/common/plugin-api-rpc.js +3 -3
  6. package/lib/common/plugin-api-rpc.js.map +1 -1
  7. package/lib/hosted/node/hosted-plugin-localization-service.d.ts +2 -2
  8. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  9. package/lib/hosted/node/hosted-plugin-localization-service.js +4 -4
  10. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  11. package/lib/main/browser/authentication-main.js +2 -2
  12. package/lib/main/browser/authentication-main.js.map +1 -1
  13. package/lib/main/browser/languages-main.d.ts +5 -2
  14. package/lib/main/browser/languages-main.d.ts.map +1 -1
  15. package/lib/main/browser/languages-main.js +20 -11
  16. package/lib/main/browser/languages-main.js.map +1 -1
  17. package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -1
  18. package/lib/main/browser/menus/plugin-menu-command-adapter.js +3 -1
  19. package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -1
  20. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  21. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  22. package/lib/main/browser/text-editor-main.d.ts.map +1 -1
  23. package/lib/main/browser/text-editor-main.js +3 -2
  24. package/lib/main/browser/text-editor-main.js.map +1 -1
  25. package/lib/main/browser/theme-icon-override.js +31 -0
  26. package/lib/main/browser/theme-icon-override.js.map +1 -1
  27. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js +1 -1
  28. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js.map +1 -1
  29. package/lib/main/browser/view/tree-view-widget.d.ts +3 -5
  30. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  31. package/lib/main/browser/view/tree-view-widget.js +59 -35
  32. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  33. package/lib/main/browser/view/tree-views-main.d.ts.map +1 -1
  34. package/lib/main/browser/view/tree-views-main.js +0 -7
  35. package/lib/main/browser/view/tree-views-main.js.map +1 -1
  36. package/lib/plugin/languages.d.ts.map +1 -1
  37. package/lib/plugin/languages.js.map +1 -1
  38. package/lib/plugin/plugin-context.d.ts +2 -5
  39. package/lib/plugin/plugin-context.d.ts.map +1 -1
  40. package/lib/plugin/plugin-context.js +26 -8
  41. package/lib/plugin/plugin-context.js.map +1 -1
  42. package/lib/plugin/preference-registry.d.ts.map +1 -1
  43. package/lib/plugin/preference-registry.js +3 -3
  44. package/lib/plugin/preference-registry.js.map +1 -1
  45. package/lib/plugin/quick-open.d.ts.map +1 -1
  46. package/lib/plugin/quick-open.js +15 -10
  47. package/lib/plugin/quick-open.js.map +1 -1
  48. package/lib/plugin/terminal-ext.d.ts +1 -1
  49. package/lib/plugin/terminal-ext.d.ts.map +1 -1
  50. package/lib/plugin/terminal-ext.js.map +1 -1
  51. package/lib/plugin/type-converters.d.ts.map +1 -1
  52. package/lib/plugin/type-converters.js +14 -2
  53. package/lib/plugin/type-converters.js.map +1 -1
  54. package/lib/plugin/types-impl.d.ts +4 -0
  55. package/lib/plugin/types-impl.d.ts.map +1 -1
  56. package/lib/plugin/types-impl.js +8 -3
  57. package/lib/plugin/types-impl.js.map +1 -1
  58. package/package.json +28 -28
  59. package/src/common/plugin-api-rpc-model.ts +3 -3
  60. package/src/common/plugin-api-rpc.ts +6 -6
  61. package/src/hosted/node/hosted-plugin-localization-service.ts +5 -5
  62. package/src/main/browser/authentication-main.ts +2 -2
  63. package/src/main/browser/languages-main.ts +46 -28
  64. package/src/main/browser/menus/plugin-menu-command-adapter.ts +3 -1
  65. package/src/main/browser/plugin-contribution-handler.ts +2 -1
  66. package/src/main/browser/style/index.css +11 -6
  67. package/src/main/browser/text-editor-main.ts +3 -2
  68. package/src/main/browser/theme-icon-override.ts +31 -0
  69. package/src/main/browser/view/plugin-tree-view-node-label-provider.ts +1 -1
  70. package/src/main/browser/view/tree-view-widget.tsx +63 -42
  71. package/src/main/browser/view/tree-views-main.ts +0 -7
  72. package/src/plugin/languages.ts +2 -1
  73. package/src/plugin/plugin-context.ts +32 -13
  74. package/src/plugin/preference-registry.ts +11 -3
  75. package/src/plugin/quick-open.ts +15 -9
  76. package/src/plugin/terminal-ext.ts +4 -1
  77. package/src/plugin/type-converters.ts +14 -2
  78. package/src/plugin/types-impl.ts +5 -0
@@ -1407,8 +1407,8 @@ export interface WorkspaceEditMetadataDto {
1407
1407
  }
1408
1408
 
1409
1409
  export interface WorkspaceFileEditDto {
1410
- oldUri?: UriComponents;
1411
- newUri?: UriComponents;
1410
+ oldResource?: UriComponents;
1411
+ newResource?: UriComponents;
1412
1412
  options?: FileOperationOptions;
1413
1413
  metadata?: WorkspaceEditMetadataDto;
1414
1414
  }
@@ -1416,7 +1416,7 @@ export interface WorkspaceFileEditDto {
1416
1416
  export interface WorkspaceTextEditDto {
1417
1417
  resource: UriComponents;
1418
1418
  modelVersionId?: number;
1419
- edit: TextEdit;
1419
+ textEdit: TextEdit;
1420
1420
  metadata?: WorkspaceEditMetadataDto;
1421
1421
 
1422
1422
  }
@@ -1424,9 +1424,9 @@ export namespace WorkspaceTextEditDto {
1424
1424
  export function is(arg: WorkspaceTextEditDto | WorkspaceFileEditDto): arg is WorkspaceTextEditDto {
1425
1425
  return !!arg
1426
1426
  && 'resource' in arg
1427
- && 'edit' in arg
1428
- && arg.edit !== null
1429
- && typeof arg.edit === 'object';
1427
+ && 'textEdit' in arg
1428
+ && arg.textEdit !== null
1429
+ && typeof arg.textEdit === 'object';
1430
1430
  }
1431
1431
  }
1432
1432
 
@@ -23,7 +23,7 @@ import { DeployedPlugin, Localization as PluginLocalization, PluginIdentifiers }
23
23
  import { URI } from '@theia/core/shared/vscode-uri';
24
24
  import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
25
25
  import { BackendApplicationContribution } from '@theia/core/lib/node';
26
- import { Disposable } from '@theia/core';
26
+ import { Disposable, MaybePromise } from '@theia/core';
27
27
  import { Deferred } from '@theia/core/lib/common/promise-util';
28
28
 
29
29
  export interface VSCodeNlsConfig {
@@ -56,10 +56,10 @@ export class HostedPluginLocalizationService implements BackendApplicationContri
56
56
  */
57
57
  ready = this._ready.promise;
58
58
 
59
- async initialize(): Promise<void> {
60
- const cacheDir = await this.getLocalizationCacheDir();
61
- await fs.emptyDir(cacheDir);
62
- this._ready.resolve();
59
+ initialize(): MaybePromise<void> {
60
+ this.getLocalizationCacheDir()
61
+ .then(cacheDir => fs.emptyDir(cacheDir))
62
+ .then(() => this._ready.resolve());
63
63
  }
64
64
 
65
65
  deployLocalizations(plugin: DeployedPlugin): void {
@@ -289,9 +289,9 @@ export class AuthenticationProviderImpl implements AuthenticationProvider {
289
289
  const accountUsages = await readAccountUsages(this.storageService, this.id, accountName);
290
290
  const sessionsForAccount = this.accounts.get(accountName);
291
291
  const result = await this.messageService.info(accountUsages.length
292
- ? nls.localizeByDefault('The account {0} has been used by: \n\n{1}\n\n Sign out of these features?', accountName,
292
+ ? nls.localizeByDefault("The account '{0}' has been used by: \n\n{1}\n\n Sign out from these extensions?", accountName,
293
293
  accountUsages.map(usage => usage.extensionName).join(', '))
294
- : nls.localizeByDefault('Sign out of {0}?', accountName),
294
+ : nls.localizeByDefault("Sign out of '{0}'?", accountName),
295
295
  nls.localizeByDefault('Sign Out'),
296
296
  Dialog.CANCEL);
297
297
 
@@ -39,7 +39,7 @@ import {
39
39
  import { injectable, inject } from '@theia/core/shared/inversify';
40
40
  import {
41
41
  SerializedDocumentFilter, MarkerData, Range, RelatedInformation,
42
- MarkerSeverity, DocumentLink, WorkspaceSymbolParams, CodeAction, CompletionDto, CodeActionProviderDocumentation, InlayHint, InlayHintLabelPart
42
+ MarkerSeverity, DocumentLink, WorkspaceSymbolParams, CodeAction, CompletionDto, CodeActionProviderDocumentation, InlayHint, InlayHintLabelPart, CodeActionContext
43
43
  } from '../../common/plugin-api-rpc-model';
44
44
  import { RPCProtocol } from '../../common/rpc-protocol';
45
45
  import { MonacoLanguages, WorkspaceSymbolProvider } from '@theia/monaco/lib/browser/monaco-languages';
@@ -868,37 +868,36 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
868
868
  }
869
869
  }
870
870
 
871
- $registerQuickFixProvider(handle: number, pluginInfo: PluginInfo, selector: SerializedDocumentFilter[], providedCodeActionKinds?: string[],
872
- documentation?: CodeActionProviderDocumentation): void {
873
-
871
+ $registerQuickFixProvider(
872
+ handle: number,
873
+ pluginInfo: PluginInfo,
874
+ selector: SerializedDocumentFilter[],
875
+ providedCodeActionKinds?: string[],
876
+ documentation?: CodeActionProviderDocumentation
877
+ ): void {
874
878
  const languageSelector = this.toLanguageSelector(selector);
875
- const quickFixProvider = {
876
- provideCodeActions: (model: monaco.editor.ITextModel, range: monaco.Range,
877
- context: monaco.languages.CodeActionContext, token: monaco.CancellationToken): monaco.languages.CodeActionList | Promise<monaco.languages.CodeActionList> => {
879
+ const quickFixProvider: monaco.languages.CodeActionProvider = {
880
+ provideCodeActions: (model, range, context, token) => {
878
881
  const markers = StandaloneServices.get(IMarkerService)
879
882
  .read({ resource: model.uri })
880
883
  .filter(m => monaco.Range.areIntersectingOrTouching(m, range)) as monaco.editor.IMarkerData[];
881
- return this.provideCodeActions(handle, model, range, { markers, only: context.only }, token);
884
+ return this.provideCodeActions(handle, model, range, { ...context, markers }, token);
882
885
  },
883
- resolveCodeAction: (codeAction: monaco.languages.CodeAction, token: monaco.CancellationToken): Promise<monaco.languages.CodeAction> =>
884
- this.resolveCodeAction(handle, codeAction, token),
885
- providedCodeActionKinds,
886
- documentation
886
+ resolveCodeAction: (codeAction, token) => this.resolveCodeAction(handle, codeAction, token)
887
887
  };
888
888
  this.register(handle, (monaco.languages.registerCodeActionProvider as RegistrationFunction<monaco.languages.CodeActionProvider>)(languageSelector, quickFixProvider));
889
889
  }
890
890
 
891
- protected async provideCodeActions(handle: number, model: monaco.editor.ITextModel,
892
- rangeOrSelection: Range, context: monaco.languages.CodeActionContext,
893
- token: monaco.CancellationToken): Promise<monaco.languages.CodeActionList | monaco.languages.CodeActionList> {
894
- const actions = await this.proxy.$provideCodeActions(handle, model.uri, rangeOrSelection, {
895
- ...context,
896
- // @monaco-uplift
897
- // the current version of monaco.languages.CodeActionContext has no CodeActionTriggerKind
898
- trigger: CodeActionTriggerKind.Automatic
899
- }, token);
891
+ protected async provideCodeActions(
892
+ handle: number,
893
+ model: monaco.editor.ITextModel,
894
+ rangeOrSelection: Range,
895
+ context: monaco.languages.CodeActionContext,
896
+ token: monaco.CancellationToken
897
+ ): Promise<monaco.languages.CodeActionList | undefined> {
898
+ const actions = await this.proxy.$provideCodeActions(handle, model.uri, rangeOrSelection, this.toModelCodeActionContext(context), token);
900
899
  if (!actions) {
901
- return undefined!;
900
+ return undefined;
902
901
  }
903
902
  return {
904
903
  actions: actions.map(a => toMonacoAction(a)),
@@ -906,6 +905,22 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
906
905
  };
907
906
  }
908
907
 
908
+ protected toModelCodeActionContext(context: monaco.languages.CodeActionContext): CodeActionContext {
909
+ return {
910
+ ...context,
911
+ trigger: this.toCodeActionTriggerKind(context.trigger)
912
+ };
913
+ }
914
+
915
+ toCodeActionTriggerKind(type: monaco.languages.CodeActionTriggerType): CodeActionTriggerKind {
916
+ switch (type) {
917
+ case monaco.languages.CodeActionTriggerType.Auto:
918
+ return CodeActionTriggerKind.Automatic;
919
+ case monaco.languages.CodeActionTriggerType.Invoke:
920
+ return CodeActionTriggerKind.Invoke;
921
+ }
922
+ }
923
+
909
924
  protected async resolveCodeAction(handle: number, codeAction: monaco.languages.CodeAction, token: monaco.CancellationToken): Promise<monaco.languages.CodeAction> {
910
925
  // The cacheId is kept in toMonacoAction when converting a received CodeAction DTO to a monaco code action
911
926
  const cacheId = (codeAction as CodeAction).cacheId;
@@ -1283,7 +1298,7 @@ function reviveOnEnterRules(onEnterRules?: SerializedOnEnterRule[]): monaco.lang
1283
1298
  return onEnterRules.map(reviveOnEnterRule);
1284
1299
  }
1285
1300
 
1286
- function reviveInlayLabel(label: string | InlayHintLabelPart[]): string | monaco.languages.InlayHintLabelPart[] {
1301
+ function reviveInlayLabel(label: string | InlayHintLabelPart[]): string | monaco.languages.InlayHintLabelPart[] {
1287
1302
  let monacoLabel: string | monaco.languages.InlayHintLabelPart[];
1288
1303
  if (typeof label === 'string') {
1289
1304
  monacoLabel = label;
@@ -1337,14 +1352,17 @@ export function toMonacoWorkspaceEdit(data: WorkspaceEditDto | undefined): monac
1337
1352
  return {
1338
1353
  edits: (data && data.edits || []).map(edit => {
1339
1354
  if (WorkspaceTextEditDto.is(edit)) {
1340
- return <monaco.languages.WorkspaceTextEdit>{
1355
+ return <monaco.languages.IWorkspaceTextEdit>{
1341
1356
  resource: monaco.Uri.revive(edit.resource),
1342
- edit: edit.edit, metadata: edit.metadata
1357
+ textEdit: edit.textEdit,
1358
+ metadata: edit.metadata
1343
1359
  };
1344
1360
  } else {
1345
- return <monaco.languages.WorkspaceFileEdit>{
1346
- newUri: monaco.Uri.revive(edit.newUri), oldUri: monaco.Uri.revive(edit.oldUri),
1347
- options: edit.options, metadata: edit.metadata
1361
+ return <monaco.languages.IWorkspaceFileEdit>{
1362
+ newResource: monaco.Uri.revive(edit.newResource),
1363
+ oldResource: monaco.Uri.revive(edit.oldResource),
1364
+ options: edit.options,
1365
+ metadata: edit.metadata
1348
1366
  };
1349
1367
  }
1350
1368
  })
@@ -247,9 +247,11 @@ export class PluginMenuCommandAdapter implements MenuCommandAdapter {
247
247
 
248
248
  protected getSelectedResources(): [CodeUri | TreeViewSelection | undefined, CodeUri[] | undefined] {
249
249
  const selection = this.selectionService.selection;
250
+ const resourceKey = this.resourceContextKey.get();
251
+ const resourceUri = resourceKey ? CodeUri.parse(resourceKey) : undefined;
250
252
  const firstMember = TreeWidgetSelection.is(selection) && selection.source instanceof TreeViewWidget && selection[0]
251
253
  ? selection.source.toTreeViewSelection(selection[0])
252
- : (UriSelection.getUri(selection) ?? this.resourceContextKey.get())?.['codeUri'];
254
+ : UriSelection.getUri(selection)?.['codeUri'] ?? resourceUri;
253
255
  const secondMember = TreeWidgetSelection.is(selection)
254
256
  ? UriSelection.getUris(selection).map(uri => uri['codeUri'])
255
257
  : undefined;
@@ -15,7 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { injectable, inject, named } from '@theia/core/shared/inversify';
18
- import { ITokenTypeMap, IEmbeddedLanguagesMap, StandardTokenType } from 'vscode-textmate';
18
+ import { ITokenTypeMap, IEmbeddedLanguagesMap } from 'vscode-textmate';
19
+ import { StandardTokenType } from 'vscode-textmate/release/encodedTokenAttributes';
19
20
  import { TextmateRegistry, getEncodedLanguageId, MonacoTextmateService, GrammarDefinition } from '@theia/monaco/lib/browser/textmate';
20
21
  import { MenusContributionPointHandler } from './menus/menus-contribution-handler';
21
22
  import { PluginViewRegistry } from './view/plugin-view-registry';
@@ -35,8 +35,13 @@
35
35
  }
36
36
 
37
37
  .theia-plugin-view-container {
38
- -webkit-mask: url('');
39
- mask: url('');
38
+ /*
39
+ It might take a second or two until the real plugin mask is loaded
40
+ To prevent flickering on the icon, we set a transparent mask instead
41
+ Since masks only support images, svg or gradients, we create a transparent gradient here
42
+ */
43
+ -webkit-mask: linear-gradient(transparent, transparent);
44
+ mask: linear-gradient(transparent, transparent);
40
45
  background-color: var(--theia-activityBar-inactiveForeground);
41
46
  }
42
47
 
@@ -51,10 +56,10 @@
51
56
  .theia-plugin-root-folder-expanded-icon,
52
57
  .theia-plugin-root-folder-expanded-icon::before {
53
58
  padding-right: var(--theia-ui-padding);
54
- width: var(--theia-icon-size);
55
- height: var(--theia-content-line-height);
56
- line-height: inherit !important;
57
- display: inline-block;
59
+ width: var(--theia-icon-size);
60
+ height: var(--theia-content-line-height);
61
+ line-height: inherit !important;
62
+ display: inline-block;
58
63
  }
59
64
 
60
65
  .p-TabBar.theia-app-sides .theia-plugin-file-icon,
@@ -282,7 +282,8 @@ export class TextEditorMain implements Disposable {
282
282
  if (!this.editor) {
283
283
  return;
284
284
  }
285
- (this.editor.getControl() as unknown as StandaloneCodeEditor).setDecorations('Plugin decorations', key, ranges.map(option => Object.assign(option, { color: undefined })));
285
+ (this.editor.getControl() as unknown as StandaloneCodeEditor)
286
+ .setDecorationsByType('Plugin decorations', key, ranges.map(option => Object.assign(option, { color: undefined })));
286
287
  }
287
288
 
288
289
  setDecorationsFast(key: string, _ranges: number[]): void {
@@ -294,7 +295,7 @@ export class TextEditorMain implements Disposable {
294
295
  for (let i = 0; i < len; i++) {
295
296
  ranges[i] = new monaco.Range(_ranges[4 * i], _ranges[4 * i + 1], _ranges[4 * i + 2], _ranges[4 * i + 3]);
296
297
  }
297
- (this.editor.getControl() as unknown as StandaloneCodeEditor).setDecorationsFast(key, ranges);
298
+ (this.editor.getControl() as unknown as StandaloneCodeEditor).setDecorationsByTypeFast(key, ranges);
298
299
  }
299
300
 
300
301
  private static toMonacoSelections(selection: Selection): monaco.Selection {
@@ -28,13 +28,44 @@ const codeIconMap: Record<string, string> = {
28
28
  'callstack-view-icon': 'debug-alt',
29
29
  'callstack-view-session': 'bug',
30
30
  'comments-view-icon': 'comment-discussion',
31
+ 'debug-breakpoint': 'debug-breakpoint',
32
+ 'debug-breakpoint-conditional': 'debug-breakpoint-conditional',
33
+ 'debug-breakpoint-conditional-disabled': 'debug-breakpoint-conditional-disabled',
34
+ 'debug-breakpoint-conditional-verified': 'debug-breakpoint-conditional-unverified',
35
+ 'debug-breakpoint-data': 'debug-breakpoint-data',
36
+ 'debug-breakpoint-data-disabled': 'debug-breakpoint-data-disabled',
37
+ 'debug-breakpoint-data-unverified': 'debug-breakpoint-data-unverified',
38
+ 'debug-breakpoint-disabled': 'debug-breakpoint-disabled',
39
+ 'debug-breakpoint-function': 'debug-breakpoint-function',
40
+ 'debug-breakpoint-function-disabled': 'debug-breakpoint-function-disabled',
41
+ 'debug-breakpoint-function-unverified': 'debug-breakpoint-function-unverified',
42
+ 'debug-breakpoint-log': 'debug-breakpoint-log',
43
+ 'debug-breakpoint-log-disabled': 'debug-breakpoint-log-disabled',
44
+ 'debug-breakpoint-log-unverified': 'debug-breakpoint-log-unverified',
45
+ 'debug-breakpoint-unsupported': 'debug-breakpoint-unsupported',
46
+ 'debug-breakpoint-unverified': 'debug-breakpoint-unverified',
31
47
  'debug-collapse-all': 'collapse-all',
32
48
  'debug-configure': 'gear',
33
49
  'debug-console-clear-all': 'clear-all',
34
50
  'debug-console-evaluation-input': 'arrow-small-right',
35
51
  'debug-console-evaluation-prompt': 'chevron-right',
36
52
  'debug-console-view-icon': 'debug-console',
53
+ 'debug-continue': 'debug-continue',
54
+ 'debug-disconnect': 'debug-disconnect',
37
55
  'debug-gripper': 'gripper',
56
+ 'debug-hint': 'debug-hint',
57
+ 'debug-pause': 'debug-pause',
58
+ 'debug-restart': 'debug-restart',
59
+ 'debug-restart-frame': 'debug-restart-frame',
60
+ 'debug-reverse-continue': 'debug-reverse-continue',
61
+ 'debug-stackframe': 'debug-stackframe',
62
+ 'debug-stackframe-focused': 'debug-stackframe-focused',
63
+ 'debug-start': 'debug-start',
64
+ 'debug-step-back': 'debug-step-back',
65
+ 'debug-step-into': 'debug-step-into',
66
+ 'debug-step-out': 'debug-step-out',
67
+ 'debug-step-over': 'debug-step-over',
68
+ 'debug-stop': 'debug-stop',
38
69
  'default-view-icon': 'window',
39
70
  'diff-editor-next-change': 'arrow-down',
40
71
  'diff-editor-previous-change': 'arrow-up',
@@ -34,7 +34,7 @@ export class PluginTreeViewNodeLabelProvider implements LabelProviderContributio
34
34
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
35
  canHandle(element: TreeViewNode | any): number {
36
36
  if (TreeNode.is(element) && ('resourceUri' in element || 'themeIcon' in element)) {
37
- return this.treeLabelProvider.canHandle(element) + 1;
37
+ return Number.MAX_SAFE_INTEGER - 512;
38
38
  }
39
39
  return 0;
40
40
  }
@@ -30,19 +30,19 @@ import {
30
30
  TREE_NODE_TAIL_CLASS,
31
31
  TreeModelImpl,
32
32
  TreeViewWelcomeWidget,
33
- TooltipService,
34
- TooltipAttributes
33
+ TooltipAttributes,
34
+ TreeSelection,
35
+ HoverService
35
36
  } from '@theia/core/lib/browser';
36
37
  import { MenuPath, MenuModelRegistry, ActionMenuNode } from '@theia/core/lib/common/menu';
37
38
  import * as React from '@theia/core/shared/react';
38
39
  import { PluginSharedStyle } from '../plugin-shared-style';
39
- import { ACTION_ITEM, codicon, Widget } from '@theia/core/lib/browser/widgets/widget';
40
+ import { ACTION_ITEM, Widget } from '@theia/core/lib/browser/widgets/widget';
40
41
  import { Emitter, Event } from '@theia/core/lib/common/event';
41
42
  import { MessageService } from '@theia/core/lib/common/message-service';
42
43
  import { View } from '../../../common/plugin-protocol';
43
44
  import CoreURI from '@theia/core/lib/common/uri';
44
45
  import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
45
- import * as markdownit from '@theia/core/shared/markdown-it';
46
46
  import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
47
47
  import { LabelParser } from '@theia/core/lib/browser/label-parser';
48
48
  import { AccessibilityInformation } from '@theia/plugin';
@@ -408,8 +408,8 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
408
408
  @inject(ContextKeyService)
409
409
  protected readonly contextKeyService: ContextKeyService;
410
410
 
411
- @inject(TooltipService)
412
- protected readonly tooltipService: TooltipService;
411
+ @inject(HoverService)
412
+ protected readonly hoverService: HoverService;
413
413
 
414
414
  @inject(LabelParser)
415
415
  protected readonly labelParser: LabelParser;
@@ -417,33 +417,18 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
417
417
  @inject(ColorRegistry)
418
418
  protected readonly colorRegistry: ColorRegistry;
419
419
 
420
- protected readonly markdownIt = markdownit();
421
-
422
420
  @postConstruct()
423
421
  protected override init(): void {
424
422
  super.init();
425
423
  this.id = this.identifier.id;
426
424
  this.addClass('theia-tree-view');
427
425
  this.node.style.height = '100%';
428
- this.markdownItPlugin();
429
426
  this.model.onDidChangeWelcomeState(this.update, this);
430
427
  this.toDispose.push(this.model.onDidChangeWelcomeState(this.update, this));
431
428
  this.toDispose.push(this.onDidChangeVisibilityEmitter);
432
429
  this.toDispose.push(this.contextKeyService.onDidChange(() => this.update()));
433
430
  }
434
431
 
435
- protected markdownItPlugin(): void {
436
- this.markdownIt.renderer.rules.text = (tokens, idx) => {
437
- const content = tokens[idx].content;
438
- return this.labelParser.parse(content).map(chunk => {
439
- if (typeof chunk === 'string') {
440
- return chunk;
441
- }
442
- return `<i class="${codicon(chunk.name)} ${chunk.animation ? `fa-${chunk.animation}` : ''} icon-inline"></i>`;
443
- }).join('');
444
- };
445
- }
446
-
447
432
  protected override renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
448
433
  const icon = this.toNodeIcon(node);
449
434
  if (icon) {
@@ -480,16 +465,21 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
480
465
  };
481
466
  }
482
467
 
483
- const elementRef = React.createRef<HTMLDivElement & Partial<TooltipAttributes>>();
484
468
  if (!node.tooltip && node instanceof ResolvableTreeViewNode) {
485
469
  let configuredTip = false;
486
470
  let source: CancellationTokenSource | undefined;
487
471
  attrs = {
488
472
  ...attrs,
489
- 'data-for': this.tooltipService.tooltipId,
490
473
  onMouseLeave: () => source?.cancel(),
491
- onMouseEnter: async () => {
474
+ onMouseEnter: async event => {
492
475
  if (configuredTip) {
476
+ if (MarkdownString.is(node.tooltip)) {
477
+ this.hoverService.requestHover({
478
+ content: node.tooltip,
479
+ target: event.target as HTMLElement,
480
+ position: 'right'
481
+ });
482
+ }
493
483
  return;
494
484
  }
495
485
  if (!node.resolved) {
@@ -500,27 +490,31 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
500
490
  return;
501
491
  }
502
492
  }
503
- if (elementRef.current) {
504
- // Set the resolved tooltip. After an HTML element was created data-* properties must be accessed via the dataset
505
- elementRef.current.dataset.tip = MarkdownString.is(node.tooltip) ? this.markdownIt.render(node.tooltip.value) : node.tooltip;
506
- this.tooltipService.update();
507
- configuredTip = true;
508
- // Manually fire another mouseenter event to get react-tooltip to update the tooltip content.
509
- // Without this, the resolved tooltip is only shown after re-entering the tree item with the mouse.
510
- elementRef.current.dispatchEvent(new MouseEvent('mouseenter'));
493
+ if (MarkdownString.is(node.tooltip)) {
494
+ this.hoverService.requestHover({
495
+ content: node.tooltip,
496
+ target: event.target as HTMLElement,
497
+ position: 'right'
498
+ });
511
499
  } else {
512
- console.error(`Could not set resolved tooltip for tree node '${node.id}' because its React Ref was not set.`);
500
+ const title = node.tooltip ||
501
+ (node.resourceUri && this.labelProvider.getLongName(new CoreURI(node.resourceUri)))
502
+ || this.toNodeName(node);
503
+ event.currentTarget.title = title;
513
504
  }
505
+ configuredTip = true;
514
506
  }
515
507
  };
516
508
  } else if (MarkdownString.is(node.tooltip)) {
517
- // Render markdown in custom tooltip
518
- const tooltip = this.markdownIt.render(node.tooltip.value);
519
-
520
509
  attrs = {
521
510
  ...attrs,
522
- 'data-tip': tooltip,
523
- 'data-for': this.tooltipService.tooltipId
511
+ onMouseEnter: event => {
512
+ this.hoverService.requestHover({
513
+ content: node.tooltip!,
514
+ target: event.target as HTMLElement,
515
+ position: 'right'
516
+ });
517
+ }
524
518
  };
525
519
  } else {
526
520
  const title = node.tooltip ||
@@ -549,7 +543,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
549
543
  if (description) {
550
544
  children.push(<span className='theia-tree-view-description'>{description}</span>);
551
545
  }
552
- return <div {...attrs} ref={elementRef}>{...children}</div>;
546
+ return <div {...attrs}>{...children}</div>;
553
547
  }
554
548
 
555
549
  protected override renderTailDecorations(node: TreeViewNode, props: NodeProps): React.ReactNode {
@@ -666,9 +660,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
666
660
  }
667
661
 
668
662
  protected override render(): React.ReactNode {
669
- const node = React.createElement('div', this.createContainerAttributes(), this.renderSearchInfo(), this.renderTree(this.model));
670
- this.tooltipService.update();
671
- return node;
663
+ return React.createElement('div', this.createContainerAttributes(), this.renderSearchInfo(), this.renderTree(this.model));
672
664
  }
673
665
 
674
666
  protected renderSearchInfo(): React.ReactNode {
@@ -681,4 +673,33 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
681
673
  override shouldShowWelcomeView(): boolean {
682
674
  return (this.model.proxy === undefined || this.model.isTreeEmpty) && this.message === undefined;
683
675
  }
676
+
677
+ protected override handleContextMenuEvent(node: TreeNode | undefined, event: React.MouseEvent<HTMLElement, MouseEvent>): void {
678
+ if (SelectableTreeNode.is(node)) {
679
+ // Keep the selection for the context menu, if the widget support multi-selection and the right click happens on an already selected node.
680
+ if (!this.props.multiSelect || !node.selected) {
681
+ const type = !!this.props.multiSelect && this.hasCtrlCmdMask(event) ? TreeSelection.SelectionType.TOGGLE : TreeSelection.SelectionType.DEFAULT;
682
+ this.model.addSelection({ node, type });
683
+ }
684
+ this.focusService.setFocus(node);
685
+ const contextMenuPath = this.props.contextMenuPath;
686
+ if (contextMenuPath) {
687
+ const { x, y } = event.nativeEvent;
688
+ const args = this.toContextMenuArgs(node);
689
+ const contextKeyService = this.contextKeyService.createOverlay([
690
+ ['viewItem', (TreeViewNode.is(node) && node.contextValue) || undefined],
691
+ ['view', this.identifier.id]
692
+ ]);
693
+ setTimeout(() => this.contextMenuRenderer.render({
694
+ menuPath: contextMenuPath,
695
+ anchor: { x, y },
696
+ args,
697
+ contextKeyService,
698
+ onHide: () => contextKeyService.dispose(),
699
+ }), 10);
700
+ }
701
+ }
702
+ event.stopPropagation();
703
+ event.preventDefault();
704
+ }
684
705
  }
@@ -163,14 +163,7 @@ export class TreeViewsMainImpl implements TreeViewsMain, Disposable {
163
163
  }));
164
164
 
165
165
  this.toDispose.push(treeViewWidget.model.onSelectionChanged(event => {
166
- if (event.length === 1) {
167
- const { contextValue } = event[0] as TreeViewNode;
168
- this.contextKeys.viewItem.set(contextValue);
169
- } else {
170
- this.contextKeys.viewItem.set('');
171
- }
172
166
  this.contextKeys.view.set(treeViewId);
173
-
174
167
  this.proxy.$setSelection(treeViewId, event.map((node: TreeViewNode) => node.id));
175
168
  }));
176
169
 
@@ -520,7 +520,8 @@ export class LanguagesExtImpl implements LanguagesExt {
520
520
  return this.createDisposable(callId, disposables?.dispose);
521
521
  }
522
522
 
523
- $provideCodeActions(handle: number,
523
+ $provideCodeActions(
524
+ handle: number,
524
525
  resource: UriComponents,
525
526
  rangeOrSelection: Range | Selection,
526
527
  context: CodeActionContext,