@theia/preferences 1.65.0-next.6 → 1.65.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 (160) hide show
  1. package/lib/browser/folder-preference-provider.d.ts +4 -2
  2. package/lib/browser/folder-preference-provider.d.ts.map +1 -1
  3. package/lib/browser/folder-preference-provider.js +9 -4
  4. package/lib/browser/folder-preference-provider.js.map +1 -1
  5. package/lib/browser/folders-preferences-provider.d.ts +2 -3
  6. package/lib/browser/folders-preferences-provider.d.ts.map +1 -1
  7. package/lib/browser/folders-preferences-provider.js +7 -8
  8. package/lib/browser/folders-preferences-provider.js.map +1 -1
  9. package/lib/browser/frontend-preference-storage.d.ts +20 -0
  10. package/lib/browser/frontend-preference-storage.d.ts.map +1 -0
  11. package/lib/browser/frontend-preference-storage.js +63 -0
  12. package/lib/browser/frontend-preference-storage.js.map +1 -0
  13. package/lib/browser/index.d.ts +0 -3
  14. package/lib/browser/index.d.ts.map +1 -1
  15. package/lib/browser/index.js +0 -3
  16. package/lib/browser/index.js.map +1 -1
  17. package/lib/browser/monaco-jsonc-editor.js +2 -2
  18. package/lib/browser/monaco-jsonc-editor.js.map +1 -1
  19. package/lib/browser/preference-bindings.d.ts +0 -1
  20. package/lib/browser/preference-bindings.d.ts.map +1 -1
  21. package/lib/browser/preference-bindings.js +13 -28
  22. package/lib/browser/preference-bindings.js.map +1 -1
  23. package/lib/browser/preference-frontend-contribution.d.ts +1 -1
  24. package/lib/browser/preference-frontend-contribution.d.ts.map +1 -1
  25. package/lib/browser/preference-frontend-contribution.js +3 -3
  26. package/lib/browser/preference-frontend-contribution.js.map +1 -1
  27. package/lib/browser/preference-frontend-module.d.ts.map +1 -1
  28. package/lib/browser/preference-frontend-module.js +4 -0
  29. package/lib/browser/preference-frontend-module.js.map +1 -1
  30. package/lib/browser/preference-transaction-manager.d.ts +4 -7
  31. package/lib/browser/preference-transaction-manager.d.ts.map +1 -1
  32. package/lib/browser/preference-transaction-manager.js +8 -11
  33. package/lib/browser/preference-transaction-manager.js.map +1 -1
  34. package/lib/browser/preference-tree-model.d.ts +4 -6
  35. package/lib/browser/preference-tree-model.d.ts.map +1 -1
  36. package/lib/browser/preference-tree-model.js +4 -4
  37. package/lib/browser/preference-tree-model.js.map +1 -1
  38. package/lib/browser/preferences-contribution.d.ts +2 -5
  39. package/lib/browser/preferences-contribution.d.ts.map +1 -1
  40. package/lib/browser/preferences-contribution.js +7 -17
  41. package/lib/browser/preferences-contribution.js.map +1 -1
  42. package/lib/browser/preferences-json-schema-contribution.d.ts +2 -6
  43. package/lib/browser/preferences-json-schema-contribution.d.ts.map +1 -1
  44. package/lib/browser/preferences-json-schema-contribution.js +30 -35
  45. package/lib/browser/preferences-json-schema-contribution.js.map +1 -1
  46. package/lib/browser/util/preference-scope-command-manager.d.ts.map +1 -1
  47. package/lib/browser/util/preference-scope-command-manager.js +1 -1
  48. package/lib/browser/util/preference-scope-command-manager.js.map +1 -1
  49. package/lib/browser/util/preference-tree-generator.d.ts +3 -4
  50. package/lib/browser/util/preference-tree-generator.d.ts.map +1 -1
  51. package/lib/browser/util/preference-tree-generator.js +10 -14
  52. package/lib/browser/util/preference-tree-generator.js.map +1 -1
  53. package/lib/browser/util/preference-types.d.ts +2 -2
  54. package/lib/browser/util/preference-types.d.ts.map +1 -1
  55. package/lib/browser/util/preference-types.js +4 -4
  56. package/lib/browser/util/preference-types.js.map +1 -1
  57. package/lib/browser/views/components/preference-node-renderer.d.ts +2 -2
  58. package/lib/browser/views/components/preference-node-renderer.d.ts.map +1 -1
  59. package/lib/browser/views/components/preference-node-renderer.js +7 -7
  60. package/lib/browser/views/components/preference-node-renderer.js.map +1 -1
  61. package/lib/browser/views/components/preference-select-input.d.ts.map +1 -1
  62. package/lib/browser/views/components/preference-select-input.js +6 -9
  63. package/lib/browser/views/components/preference-select-input.js.map +1 -1
  64. package/lib/browser/views/preference-editor-widget.d.ts +3 -2
  65. package/lib/browser/views/preference-editor-widget.d.ts.map +1 -1
  66. package/lib/browser/views/preference-editor-widget.js +3 -3
  67. package/lib/browser/views/preference-editor-widget.js.map +1 -1
  68. package/lib/browser/views/preference-scope-tabbar-widget.d.ts +2 -2
  69. package/lib/browser/views/preference-scope-tabbar-widget.d.ts.map +1 -1
  70. package/lib/browser/views/preference-scope-tabbar-widget.js +7 -7
  71. package/lib/browser/views/preference-scope-tabbar-widget.js.map +1 -1
  72. package/lib/browser/views/preference-widget.d.ts +2 -1
  73. package/lib/browser/views/preference-widget.d.ts.map +1 -1
  74. package/lib/browser/views/preference-widget.js.map +1 -1
  75. package/lib/browser/workspace-file-preference-provider.d.ts +2 -2
  76. package/lib/browser/workspace-file-preference-provider.d.ts.map +1 -1
  77. package/lib/browser/workspace-file-preference-provider.js +2 -2
  78. package/lib/browser/workspace-file-preference-provider.js.map +1 -1
  79. package/lib/browser/workspace-preference-provider.d.ts +13 -6
  80. package/lib/browser/workspace-preference-provider.d.ts.map +1 -1
  81. package/lib/browser/workspace-preference-provider.js +27 -17
  82. package/lib/browser/workspace-preference-provider.js.map +1 -1
  83. package/lib/common/abstract-resource-preference-provider.d.ts +69 -0
  84. package/lib/common/abstract-resource-preference-provider.d.ts.map +1 -0
  85. package/lib/{browser → common}/abstract-resource-preference-provider.js +36 -62
  86. package/lib/common/abstract-resource-preference-provider.js.map +1 -0
  87. package/lib/common/abstract-resource-preference-provider.spec.d.ts.map +1 -0
  88. package/lib/{browser → common}/abstract-resource-preference-provider.spec.js +17 -17
  89. package/lib/common/abstract-resource-preference-provider.spec.js.map +1 -0
  90. package/lib/common/jsonc-editor.d.ts +10 -0
  91. package/lib/common/jsonc-editor.d.ts.map +1 -0
  92. package/lib/common/jsonc-editor.js +68 -0
  93. package/lib/common/jsonc-editor.js.map +1 -0
  94. package/lib/{browser → common}/section-preference-provider.d.ts +1 -3
  95. package/lib/common/section-preference-provider.d.ts.map +1 -0
  96. package/lib/{browser → common}/section-preference-provider.js +3 -8
  97. package/lib/common/section-preference-provider.js.map +1 -0
  98. package/lib/{browser → common}/user-configs-preference-provider.d.ts +6 -5
  99. package/lib/common/user-configs-preference-provider.d.ts.map +1 -0
  100. package/lib/{browser → common}/user-configs-preference-provider.js +17 -13
  101. package/lib/common/user-configs-preference-provider.js.map +1 -0
  102. package/lib/{browser → common}/user-preference-provider.d.ts +1 -1
  103. package/lib/common/user-preference-provider.d.ts.map +1 -0
  104. package/lib/{browser → common}/user-preference-provider.js +2 -2
  105. package/lib/common/user-preference-provider.js.map +1 -0
  106. package/lib/node/backend-preference-storage.d.ts +34 -0
  107. package/lib/node/backend-preference-storage.d.ts.map +1 -0
  108. package/lib/node/backend-preference-storage.js +100 -0
  109. package/lib/node/backend-preference-storage.js.map +1 -0
  110. package/lib/node/preference-backend-module.d.ts.map +1 -1
  111. package/lib/node/preference-backend-module.js +9 -0
  112. package/lib/node/preference-backend-module.js.map +1 -1
  113. package/lib/node/preference-bindings.d.ts +3 -0
  114. package/lib/node/preference-bindings.d.ts.map +1 -0
  115. package/lib/node/preference-bindings.js +33 -0
  116. package/lib/node/preference-bindings.js.map +1 -0
  117. package/package.json +9 -9
  118. package/src/browser/folder-preference-provider.ts +5 -2
  119. package/src/browser/folders-preferences-provider.ts +4 -5
  120. package/src/browser/frontend-preference-storage.ts +72 -0
  121. package/src/browser/index.ts +0 -3
  122. package/src/browser/monaco-jsonc-editor.ts +2 -2
  123. package/src/browser/preference-bindings.ts +7 -26
  124. package/src/browser/preference-frontend-contribution.ts +1 -1
  125. package/src/browser/preference-frontend-module.ts +10 -0
  126. package/src/browser/preference-transaction-manager.ts +8 -13
  127. package/src/browser/preference-tree-model.ts +4 -7
  128. package/src/browser/preferences-contribution.ts +2 -9
  129. package/src/browser/preferences-json-schema-contribution.ts +20 -23
  130. package/src/browser/util/preference-scope-command-manager.ts +2 -2
  131. package/src/browser/util/preference-tree-generator.ts +8 -12
  132. package/src/browser/util/preference-types.ts +2 -5
  133. package/src/browser/views/components/preference-node-renderer.ts +4 -5
  134. package/src/browser/views/components/preference-select-input.ts +6 -9
  135. package/src/browser/views/preference-editor-widget.ts +2 -5
  136. package/src/browser/views/preference-scope-tabbar-widget.tsx +2 -2
  137. package/src/browser/views/preference-widget.tsx +2 -1
  138. package/src/browser/workspace-file-preference-provider.ts +2 -2
  139. package/src/browser/workspace-preference-provider.ts +37 -19
  140. package/src/{browser → common}/abstract-resource-preference-provider.spec.ts +19 -20
  141. package/src/{browser → common}/abstract-resource-preference-provider.ts +69 -57
  142. package/src/common/jsonc-editor.ts +65 -0
  143. package/src/{browser → common}/section-preference-provider.ts +1 -5
  144. package/src/{browser → common}/user-configs-preference-provider.ts +14 -10
  145. package/src/{browser → common}/user-preference-provider.ts +1 -1
  146. package/src/node/backend-preference-storage.ts +117 -0
  147. package/src/node/preference-backend-module.ts +16 -0
  148. package/src/node/preference-bindings.ts +31 -0
  149. package/lib/browser/abstract-resource-preference-provider.d.ts +0 -48
  150. package/lib/browser/abstract-resource-preference-provider.d.ts.map +0 -1
  151. package/lib/browser/abstract-resource-preference-provider.js.map +0 -1
  152. package/lib/browser/abstract-resource-preference-provider.spec.d.ts.map +0 -1
  153. package/lib/browser/abstract-resource-preference-provider.spec.js.map +0 -1
  154. package/lib/browser/section-preference-provider.d.ts.map +0 -1
  155. package/lib/browser/section-preference-provider.js.map +0 -1
  156. package/lib/browser/user-configs-preference-provider.d.ts.map +0 -1
  157. package/lib/browser/user-configs-preference-provider.js.map +0 -1
  158. package/lib/browser/user-preference-provider.d.ts.map +0 -1
  159. package/lib/browser/user-preference-provider.js.map +0 -1
  160. /package/lib/{browser → common}/abstract-resource-preference-provider.spec.d.ts +0 -0
@@ -15,15 +15,12 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import {
18
- PreferenceDataProperty,
19
- PreferenceScope,
20
18
  TreeNode as BaseTreeNode,
21
19
  CompositeTreeNode as BaseCompositeTreeNode,
22
20
  SelectableTreeNode,
23
- PreferenceInspection,
24
21
  CommonCommands,
25
- } from '@theia/core/lib/browser';
26
- import { Command, MenuPath } from '@theia/core';
22
+ } from '@theia/core/lib/browser';
23
+ import { Command, MenuPath, PreferenceDataProperty, PreferenceInspection, PreferenceScope } from '@theia/core';
27
24
  import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
28
25
  import { JsonType } from '@theia/core/lib/common/json-schema';
29
26
 
@@ -16,13 +16,12 @@
16
16
 
17
17
  import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
18
18
  import {
19
- PreferenceService, ContextMenuRenderer, PreferenceInspection,
20
- PreferenceScope, PreferenceProvider, codicon, OpenerService, open, PreferenceDataProperty
19
+ ContextMenuRenderer, codicon, OpenerService, open
21
20
  } from '@theia/core/lib/browser';
22
21
  import { Preference, PreferenceMenus } from '../../util/preference-types';
23
22
  import { PreferenceTreeLabelProvider } from '../../util/preference-tree-label-provider';
24
23
  import { PreferencesScopeTabBar } from '../preference-scope-tabbar-widget';
25
- import { Disposable, nls } from '@theia/core/lib/common';
24
+ import { Disposable, nls, PreferenceDataProperty, PreferenceInspection, PreferenceScope, PreferenceService, PreferenceUtils } from '@theia/core/lib/common';
26
25
  import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
27
26
  import debounce = require('@theia/core/shared/lodash.debounce');
28
27
  import { PreferenceTreeModel } from '../../preference-tree-model';
@@ -295,7 +294,7 @@ export abstract class PreferenceLeafNodeRenderer<ValueType extends JSONValue, In
295
294
  const wasModified = this.isModifiedFromDefault;
296
295
  const { inspection } = this;
297
296
  const valueInCurrentScope = knownCurrentValue ?? Preference.getValueInScope(inspection, this.scopeTracker.currentScope.scope);
298
- this.isModifiedFromDefault = valueInCurrentScope !== undefined && !PreferenceProvider.deepEqual(valueInCurrentScope, inspection?.defaultValue);
297
+ this.isModifiedFromDefault = valueInCurrentScope !== undefined && !PreferenceUtils.deepEqual(valueInCurrentScope, inspection?.defaultValue);
299
298
  if (wasModified !== this.isModifiedFromDefault) {
300
299
  this.gutter.classList.toggle('theia-mod-item-modified', this.isModifiedFromDefault);
301
300
  }
@@ -422,7 +421,7 @@ export abstract class PreferenceLeafNodeRenderer<ValueType extends JSONValue, In
422
421
  for (const otherScope of [PreferenceScope.User, PreferenceScope.Workspace]) {
423
422
  if (otherScope !== currentScopeInView) {
424
423
  const valueInOtherScope = Preference.getValueInScope(inspection, otherScope);
425
- if (valueInOtherScope !== undefined && !PreferenceProvider.deepEqual(valueInOtherScope, inspection.defaultValue)) {
424
+ if (valueInOtherScope !== undefined && !PreferenceUtils.deepEqual(valueInOtherScope, inspection.defaultValue)) {
426
425
  modifiedScopes.push(otherScope);
427
426
  }
428
427
  }
@@ -17,13 +17,13 @@
17
17
  import { PreferenceLeafNodeRenderer, PreferenceNodeRenderer } from './preference-node-renderer';
18
18
  import { injectable, interfaces } from '@theia/core/shared/inversify';
19
19
  import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
20
- import { PreferenceProvider } from '@theia/core/lib/browser/preferences/preference-provider';
21
20
  import { SelectComponent, SelectOption } from '@theia/core/lib/browser/widgets/select-component';
22
21
  import { Preference } from '../../util/preference-types';
23
22
  import { PreferenceLeafNodeRendererContribution } from './preference-node-renderer-creator';
24
23
  import * as React from '@theia/core/shared/react';
25
24
  import { createRoot } from '@theia/core/shared/react-dom/client';
26
25
  import { escapeInvisibleChars } from '@theia/core/lib/common/strings';
26
+ import { PreferenceUtils } from '@theia/core';
27
27
 
28
28
  @injectable()
29
29
  export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer<JSONValue, HTMLDivElement> {
@@ -45,7 +45,7 @@ export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer<JS
45
45
  const value = values[i];
46
46
  const stringValue = `${value}`;
47
47
  const label = escapeInvisibleChars(preferenceData.enumItemLabels?.[i] ?? stringValue);
48
- const detail = PreferenceProvider.deepEqual(defaultValue, value) ? 'default' : undefined;
48
+ const detail = PreferenceUtils.deepEqual(defaultValue, value) ? 'default' : undefined;
49
49
  let enumDescription = preferenceData.enumDescriptions?.[i];
50
50
  let markdown = false;
51
51
  const markdownEnumDescription = preferenceData.markdownEnumDescriptions?.[i];
@@ -80,11 +80,8 @@ export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer<JS
80
80
  }
81
81
 
82
82
  protected getFallbackValue(): JSONValue {
83
- const { default: schemaDefault, defaultValue, enum: enumValues } = this.preferenceNode.preference.data;
84
- return schemaDefault !== undefined
85
- ? schemaDefault : defaultValue !== undefined
86
- ? defaultValue
87
- : enumValues![0];
83
+ const { default: schemaDefault, enum: enumValues } = this.preferenceNode.preference.data;
84
+ return schemaDefault !== undefined ? schemaDefault : enumValues![0];
88
85
  }
89
86
 
90
87
  protected doHandleValueChange(): void {
@@ -102,10 +99,10 @@ export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer<JS
102
99
  */
103
100
  protected getDataValue(): number {
104
101
  const currentValue = this.getValue();
105
- let selected = this.enumValues.findIndex(value => PreferenceProvider.deepEqual(value, currentValue));
102
+ let selected = this.enumValues.findIndex(value => PreferenceUtils.deepEqual(value, currentValue));
106
103
  if (selected === -1) {
107
104
  const fallback = this.getFallbackValue();
108
- selected = this.enumValues.findIndex(value => PreferenceProvider.deepEqual(value, fallback));
105
+ selected = this.enumValues.findIndex(value => PreferenceUtils.deepEqual(value, fallback));
109
106
  }
110
107
  return Math.max(selected, 0);
111
108
  }
@@ -19,16 +19,13 @@ import { postConstruct, injectable, inject } from '@theia/core/shared/inversify'
19
19
  import throttle = require('@theia/core/shared/lodash.throttle');
20
20
  import * as deepEqual from 'fast-deep-equal';
21
21
  import {
22
- PreferenceService,
23
22
  CompositeTreeNode,
24
23
  SelectableTreeNode,
25
24
  StatefulWidget,
26
25
  TopDownTreeIterator,
27
- PreferenceChanges,
28
26
  ExpandableTreeNode,
29
- PreferenceSchemaProvider,
30
27
  } from '@theia/core/lib/browser';
31
- import { unreachable } from '@theia/core/lib/common';
28
+ import { PreferenceChanges, PreferenceSchemaService, PreferenceService, unreachable } from '@theia/core/lib/common';
32
29
  import { BaseWidget, DEFAULT_SCROLL_OPTIONS } from '@theia/core/lib/browser/widgets/widget';
33
30
  import { PreferenceTreeModel, PreferenceFilterChangeEvent, PreferenceFilterChangeSource } from '../preference-tree-model';
34
31
  import { PreferenceNodeRendererFactory, GeneralPreferenceNodeRenderer } from './components/preference-node-renderer';
@@ -68,7 +65,7 @@ export class PreferencesEditorWidget extends BaseWidget implements StatefulWidge
68
65
  @inject(PreferenceTreeModel) protected readonly model: PreferenceTreeModel;
69
66
  @inject(PreferenceNodeRendererFactory) protected readonly rendererFactory: PreferenceNodeRendererFactory;
70
67
  @inject(PreferenceNodeRendererCreatorRegistry) protected readonly rendererRegistry: PreferenceNodeRendererCreatorRegistry;
71
- @inject(PreferenceSchemaProvider) protected readonly schemaProvider: PreferenceSchemaProvider;
68
+ @inject(PreferenceSchemaService) protected readonly schemaProvider: PreferenceSchemaService;
72
69
  @inject(PreferencesScopeTabBar) protected readonly tabbar: PreferencesScopeTabBar;
73
70
 
74
71
  @postConstruct()
@@ -16,13 +16,13 @@
16
16
 
17
17
  import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
18
18
  import { TabBar, Widget, Title } from '@theia/core/shared/@lumino/widgets';
19
- import { PreferenceScope, Message, ContextMenuRenderer, LabelProvider, StatefulWidget, codicon } from '@theia/core/lib/browser';
19
+ import { Message, ContextMenuRenderer, LabelProvider, StatefulWidget, codicon } from '@theia/core/lib/browser';
20
20
  import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
21
21
  import URI from '@theia/core/lib/common/uri';
22
22
  import { FileStat } from '@theia/filesystem/lib/common/files';
23
23
  import { PreferenceScopeCommandManager } from '../util/preference-scope-command-manager';
24
24
  import { Preference, PreferenceMenus } from '../util/preference-types';
25
- import { CommandRegistry, DisposableCollection, Emitter, MenuModelRegistry } from '@theia/core/lib/common';
25
+ import { CommandRegistry, DisposableCollection, Emitter, MenuModelRegistry, PreferenceScope } from '@theia/core/lib/common';
26
26
  import { nls } from '@theia/core/lib/common/nls';
27
27
 
28
28
  const USER_TAB_LABEL = nls.localizeByDefault('User');
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { postConstruct, injectable, inject } from '@theia/core/shared/inversify';
18
- import { Panel, Widget, Message, StatefulWidget, PreferenceScope, codicon } from '@theia/core/lib/browser';
18
+ import { Panel, Widget, Message, StatefulWidget, codicon } from '@theia/core/lib/browser';
19
19
  import { PreferencesEditorState, PreferencesEditorWidget } from './preference-editor-widget';
20
20
  import { PreferencesTreeWidget } from './preference-tree-widget';
21
21
  import { PreferencesSearchbarState, PreferencesSearchbarWidget } from './preference-searchbar-widget';
@@ -23,6 +23,7 @@ import { PreferencesScopeTabBar, PreferencesScopeTabBarState } from './preferenc
23
23
  import { Preference } from '../util/preference-types';
24
24
  import URI from '@theia/core/lib/common/uri';
25
25
  import { nls } from '@theia/core/lib/common/nls';
26
+ import { PreferenceScope } from '@theia/core';
26
27
 
27
28
  interface PreferencesWidgetState {
28
29
  scopeTabBarState: PreferencesScopeTabBarState,
@@ -16,9 +16,9 @@
16
16
 
17
17
  import { inject, injectable } from '@theia/core/shared/inversify';
18
18
  import URI from '@theia/core/lib/common/uri';
19
- import { PreferenceScope } from '@theia/core/lib/browser/preferences';
19
+ import { PreferenceScope } from '@theia/core/lib/common/preferences';
20
20
  import { WorkspaceService, WorkspaceData } from '@theia/workspace/lib/browser/workspace-service';
21
- import { AbstractResourcePreferenceProvider } from './abstract-resource-preference-provider';
21
+ import { AbstractResourcePreferenceProvider } from '../common/abstract-resource-preference-provider';
22
22
 
23
23
  @injectable()
24
24
  export class WorkspaceFilePreferenceProviderOptions {
@@ -16,15 +16,17 @@
16
16
 
17
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
18
 
19
- import { inject, injectable, postConstruct, named } from '@theia/core/shared/inversify';
19
+ import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
20
20
  import URI from '@theia/core/lib/common/uri';
21
21
  import { DisposableCollection } from '@theia/core/lib/common/disposable';
22
- import { PreferenceScope, PreferenceProvider } from '@theia/core/lib/browser/preferences';
23
22
  import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
24
23
  import { WorkspaceFilePreferenceProviderFactory, WorkspaceFilePreferenceProvider } from './workspace-file-preference-provider';
24
+ import { Deferred } from '@theia/core/lib/common/promise-util';
25
+ import { Emitter, Event, PreferenceProvider, PreferenceProviderDataChanges, PreferenceProviderProvider, PreferenceScope } from '@theia/core';
26
+ import { JSONObject } from '@theia/core/shared/@lumino/coreutils';
25
27
 
26
28
  @injectable()
27
- export class WorkspacePreferenceProvider extends PreferenceProvider {
29
+ export class WorkspacePreferenceProvider implements PreferenceProvider {
28
30
 
29
31
  @inject(WorkspaceService)
30
32
  protected readonly workspaceService: WorkspaceService;
@@ -32,11 +34,19 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
32
34
  @inject(WorkspaceFilePreferenceProviderFactory)
33
35
  protected readonly workspaceFileProviderFactory: WorkspaceFilePreferenceProviderFactory;
34
36
 
35
- @inject(PreferenceProvider) @named(PreferenceScope.Folder)
36
- protected readonly folderPreferenceProvider: PreferenceProvider;
37
+ @inject(PreferenceProviderProvider)
38
+ protected readonly preferenceProviderProvider: PreferenceProviderProvider;
39
+
40
+ protected readonly onDidPreferencesChangedEmitter = new Emitter<PreferenceProviderDataChanges>();
41
+ readonly onDidPreferencesChanged: Event<PreferenceProviderDataChanges> = this.onDidPreferencesChangedEmitter.event;
37
42
 
38
43
  protected readonly toDisposeOnEnsureDelegateUpToDate = new DisposableCollection();
39
44
 
45
+ protected _ready = new Deferred<void>();
46
+ readonly ready = this._ready.promise;
47
+
48
+ protected readonly disposables = new DisposableCollection();
49
+
40
50
  @postConstruct()
41
51
  protected init(): void {
42
52
  this.workspaceService.ready.then(() => {
@@ -46,15 +56,23 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
46
56
  this._ready.resolve();
47
57
  }
48
58
  });
49
- this.workspaceService.onWorkspaceLocationChanged(() => this.ensureDelegateUpToDate());
50
- this.workspaceService.onWorkspaceChanged(() => this.ensureDelegateUpToDate());
59
+ this.disposables.push(this.workspaceService.onWorkspaceLocationChanged(() => this.ensureDelegateUpToDate()));
60
+ this.disposables.push(this.workspaceService.onWorkspaceChanged(() => this.ensureDelegateUpToDate()));
61
+ }
62
+
63
+ dispose(): void {
64
+ this.disposables.dispose();
65
+ }
66
+
67
+ canHandleScope(scope: PreferenceScope): boolean {
68
+ return true;
51
69
  }
52
70
 
53
- override getConfigUri(resourceUri: string | undefined = this.ensureResourceUri(), sectionName?: string): URI | undefined {
54
- return this.delegate?.getConfigUri(resourceUri, sectionName);
71
+ getConfigUri(resourceUri: string | undefined = this.ensureResourceUri(), sectionName?: string): URI | undefined {
72
+ return this.delegate?.getConfigUri && this.delegate?.getConfigUri(resourceUri, sectionName);
55
73
  }
56
74
 
57
- override getContainingConfigUri(resourceUri: string | undefined = this.ensureResourceUri(), sectionName?: string): URI | undefined {
75
+ getContainingConfigUri(resourceUri: string | undefined = this.ensureResourceUri(), sectionName?: string): URI | undefined {
58
76
  return this.delegate?.getContainingConfigUri?.(resourceUri, sectionName);
59
77
  }
60
78
 
@@ -67,7 +85,7 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
67
85
  const delegate = this.createDelegate();
68
86
  if (this._delegate !== delegate) {
69
87
  this.toDisposeOnEnsureDelegateUpToDate.dispose();
70
- this.toDispose.push(this.toDisposeOnEnsureDelegateUpToDate);
88
+ this.disposables.push(this.toDisposeOnEnsureDelegateUpToDate);
71
89
 
72
90
  this._delegate = delegate;
73
91
 
@@ -91,7 +109,7 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
91
109
  return undefined;
92
110
  }
93
111
  if (!this.workspaceService.isMultiRootWorkspaceOpened) {
94
- return this.folderPreferenceProvider;
112
+ return this.preferenceProviderProvider(PreferenceScope.Folder);
95
113
  }
96
114
  if (this._delegate instanceof WorkspaceFilePreferenceProvider && this._delegate.getConfigUri().isEqual(workspace.resource)) {
97
115
  return this._delegate;
@@ -101,21 +119,16 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
101
119
  });
102
120
  }
103
121
 
104
- override get<T>(preferenceName: string, resourceUri: string | undefined = this.ensureResourceUri()): T | undefined {
122
+ get<T>(preferenceName: string, resourceUri: string | undefined = this.ensureResourceUri()): T | undefined {
105
123
  const delegate = this.delegate;
106
124
  return delegate ? delegate.get<T>(preferenceName, resourceUri) : undefined;
107
125
  }
108
126
 
109
- override resolve<T>(preferenceName: string, resourceUri: string | undefined = this.ensureResourceUri()): { value?: T, configUri?: URI } {
127
+ resolve<T>(preferenceName: string, resourceUri: string | undefined = this.ensureResourceUri()): { value?: T, configUri?: URI } {
110
128
  const delegate = this.delegate;
111
129
  return delegate ? delegate.resolve<T>(preferenceName, resourceUri) : {};
112
130
  }
113
131
 
114
- getPreferences(resourceUri: string | undefined = this.ensureResourceUri()): { [p: string]: any } {
115
- const delegate = this.delegate;
116
- return delegate ? delegate.getPreferences(resourceUri) : {};
117
- }
118
-
119
132
  async setPreference(preferenceName: string, value: any, resourceUri: string | undefined = this.ensureResourceUri()): Promise<boolean> {
120
133
  const delegate = this.delegate;
121
134
  if (delegate) {
@@ -124,6 +137,11 @@ export class WorkspacePreferenceProvider extends PreferenceProvider {
124
137
  return false;
125
138
  }
126
139
 
140
+ getPreferences(resourceUri: string | undefined = this.ensureResourceUri()): JSONObject {
141
+ const delegate = this.delegate;
142
+ return delegate ? delegate.getPreferences(resourceUri) : {};
143
+ }
144
+
127
145
  protected ensureResourceUri(): string | undefined {
128
146
  if (this.workspaceService.workspace && !this.workspaceService.isMultiRootWorkspaceOpened) {
129
147
  return this.workspaceService.workspace.resource.toString();
@@ -24,32 +24,31 @@ FrontendApplicationConfigProvider.set({});
24
24
 
25
25
  import { expect } from 'chai';
26
26
  import { Container } from '@theia/core/shared/inversify';
27
- import { AbstractResourcePreferenceProvider } from './abstract-resource-preference-provider';
28
- import { FileService } from '@theia/filesystem/lib/browser/file-service';
27
+ import { AbstractResourcePreferenceProvider, FileContentStatus, PreferenceStorage, PreferenceStorageFactory } from './abstract-resource-preference-provider';
29
28
  import { bindPreferenceService } from '@theia/core/lib/browser/frontend-application-bindings';
30
29
  import { bindMockPreferenceProviders } from '@theia/core/lib/browser/preferences/test';
31
30
  import { Deferred } from '@theia/core/lib/common/promise-util';
32
- import { Disposable, MessageService } from '@theia/core/lib/common';
31
+ import { Listener, MessageService, PreferenceSchemaService } from '@theia/core/lib/common';
33
32
  import { MonacoWorkspace } from '@theia/monaco/lib/browser/monaco-workspace';
34
- import { PreferenceSchemaProvider } from '@theia/core/lib/browser';
35
33
  import { EditorManager } from '@theia/editor/lib/browser';
36
- import { PreferenceTransactionFactory } from './preference-transaction-manager';
34
+ import { PreferenceTransactionFactory } from '../browser/preference-transaction-manager';
35
+ import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
37
36
 
38
37
  disableJSDOM();
39
38
 
40
- class MockFileService {
39
+ class MockPreferenceStorage implements PreferenceStorage {
40
+ onDidChangeFileContent: Listener.Registration<FileContentStatus, Promise<boolean>> = Listener.None as unknown as Listener.Registration<FileContentStatus, Promise<boolean>>;
41
+ writeValue(key: string, path: string[], value: JSONValue): Promise<boolean> {
42
+ throw new Error('Method not implemented.');
43
+ }
44
+ dispose(): void { }
41
45
  releaseContent = new Deferred();
42
- async read(): Promise<{ value: string }> {
46
+ async read(): Promise<string> {
43
47
  await this.releaseContent.promise;
44
- return { value: JSON.stringify({ 'editor.fontSize': 20 }) };
48
+ return JSON.stringify({ 'editor.fontSize': 20 });
45
49
  }
46
- watch = RETURN_DISPOSABLE;
47
- onDidFilesChange = RETURN_DISPOSABLE;
48
50
  }
49
-
50
- const RETURN_DISPOSABLE = () => Disposable.NULL;
51
-
52
- const mockSchemaProvider = { getCombinedSchema: () => ({ properties: {} }) };
51
+ const mockSchemaProvider = { getSchemaProperty: () => undefined };
53
52
 
54
53
  class LessAbstractPreferenceProvider extends AbstractResourcePreferenceProvider {
55
54
  getUri(): any { }
@@ -58,15 +57,15 @@ class LessAbstractPreferenceProvider extends AbstractResourcePreferenceProvider
58
57
 
59
58
  describe('AbstractResourcePreferenceProvider', () => {
60
59
  let provider: AbstractResourcePreferenceProvider;
61
- let fileService: MockFileService;
60
+ let preferenceStorage: MockPreferenceStorage;
62
61
 
63
62
  beforeEach(() => {
64
- fileService = new MockFileService();
63
+ preferenceStorage = new MockPreferenceStorage();
65
64
  const testContainer = new Container();
66
65
  bindPreferenceService(testContainer.bind.bind(testContainer));
67
66
  bindMockPreferenceProviders(testContainer.bind.bind(testContainer), testContainer.unbind.bind(testContainer));
68
- testContainer.rebind(<any>PreferenceSchemaProvider).toConstantValue(mockSchemaProvider);
69
- testContainer.bind(<any>FileService).toConstantValue(fileService);
67
+ testContainer.rebind(<any>PreferenceSchemaService).toConstantValue(mockSchemaProvider);
68
+ testContainer.bind(<any>PreferenceStorageFactory).toFactory(() => () => preferenceStorage);
70
69
  testContainer.bind(<any>MessageService).toConstantValue(undefined);
71
70
  testContainer.bind(<any>MonacoWorkspace).toConstantValue(undefined);
72
71
  testContainer.bind(<any>EditorManager).toConstantValue(undefined);
@@ -81,14 +80,14 @@ describe('AbstractResourcePreferenceProvider', () => {
81
80
  expect(provider.get('editor.fontSize')).to.be.undefined;
82
81
 
83
82
  resolveWhenFinished.resolve();
84
- fileService.releaseContent.resolve(); // Allow the initialization to run
83
+ preferenceStorage.releaseContent.resolve(); // Allow the initialization to run
85
84
 
86
85
  // This promise would reject if the provider had declared itself ready before we resolve `resolveWhenFinished`
87
86
  await Promise.race([resolveWhenFinished.promise, errorIfReadyFirst]);
88
87
  });
89
88
 
90
89
  it('should report values in file when `ready` resolves.', async () => {
91
- fileService.releaseContent.resolve();
90
+ preferenceStorage.releaseContent.resolve();
92
91
  await provider.ready;
93
92
  expect(provider.get('editor.fontSize')).to.equal(20); // The value provided by the mock FileService implementation.
94
93
  });
@@ -20,21 +20,52 @@
20
20
  import * as jsoncparser from 'jsonc-parser';
21
21
  import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
22
22
  import { Disposable } from '@theia/core/lib/common/disposable';
23
- import { PreferenceProvider, PreferenceSchemaProvider, PreferenceScope, PreferenceProviderDataChange } from '@theia/core/lib/browser';
23
+ import {
24
+ PreferenceProviderImpl, PreferenceScope, PreferenceProviderDataChange, PreferenceSchemaService,
25
+ PreferenceConfigurations, PreferenceUtils, PreferenceLanguageOverrideService,
26
+ Listener
27
+ } from '@theia/core/lib/common';
24
28
  import URI from '@theia/core/lib/common/uri';
25
- import { PreferenceConfigurations } from '@theia/core/lib/browser/preferences/preference-configurations';
26
29
  import { Deferred } from '@theia/core/lib/common/promise-util';
27
- import { FileService } from '@theia/filesystem/lib/browser/file-service';
28
- import { PreferenceContext, PreferenceTransaction, PreferenceTransactionFactory } from './preference-transaction-manager';
29
30
  import { Emitter, Event } from '@theia/core';
31
+ import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
32
+ export interface FileContentStatus {
33
+ content: string;
34
+ fileOK: boolean
35
+ }
36
+ /**
37
+ * Abtracts the way to read and write preferences to a given resource
38
+ */
39
+ export interface PreferenceStorage extends Disposable {
40
+ /**
41
+ * Write a value to the underlying preference store
42
+ * @param key the preference key
43
+ * @param path the path to the JSON object to change
44
+ * @param value the new preference value
45
+ * @returns a promise that will resolve when all "onStored" listeners have finished
46
+ */
47
+ writeValue(key: string, path: string[], value: JSONValue): Promise<boolean>;
48
+ /**
49
+ * List of listeners that will get a string with the newly stored resource content and should return a promise that resolves when
50
+ * they are done with their processing
51
+ */
52
+ onDidChangeFileContent: Listener.Registration<FileContentStatus, Promise<boolean>>;
53
+ /**
54
+ * Reds the content of the underlying resource
55
+ */
56
+ read(): Promise<string>;
57
+ };
58
+
59
+ export const PreferenceStorageFactory = Symbol('PreferenceStorageFactory');
60
+ export type PreferenceStorageFactory = (uri: URI, scope: PreferenceScope) => PreferenceStorage;
30
61
 
31
62
  @injectable()
32
- export abstract class AbstractResourcePreferenceProvider extends PreferenceProvider {
63
+ export abstract class AbstractResourcePreferenceProvider extends PreferenceProviderImpl {
64
+ protected preferenceStorage: PreferenceStorage;
33
65
 
34
66
  protected preferences: Record<string, any> = {};
35
67
  protected _fileExists = false;
36
68
  protected readonly loading = new Deferred();
37
- protected transaction: PreferenceTransaction | undefined;
38
69
  protected readonly onDidChangeValidityEmitter = new Emitter<boolean>();
39
70
 
40
71
  set fileExists(exists: boolean) {
@@ -48,10 +79,14 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi
48
79
  return this.onDidChangeValidityEmitter.event;
49
80
  }
50
81
 
51
- @inject(PreferenceTransactionFactory) protected readonly transactionFactory: PreferenceTransactionFactory;
52
- @inject(PreferenceSchemaProvider) protected readonly schemaProvider: PreferenceSchemaProvider;
53
- @inject(FileService) protected readonly fileService: FileService;
54
- @inject(PreferenceConfigurations) protected readonly configurations: PreferenceConfigurations;
82
+ @inject(PreferenceSchemaService)
83
+ protected readonly schemaProvider: PreferenceSchemaService;
84
+ @inject(PreferenceConfigurations)
85
+ protected readonly configurations: PreferenceConfigurations;
86
+ @inject(PreferenceLanguageOverrideService)
87
+ protected readonly preferenceOverrideService: PreferenceLanguageOverrideService;
88
+ @inject(PreferenceStorageFactory)
89
+ protected readonly preferenceStorageFactory: PreferenceStorageFactory;
55
90
 
56
91
  @postConstruct()
57
92
  protected init(): void {
@@ -61,17 +96,19 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi
61
96
  protected async doInit(): Promise<void> {
62
97
  const uri = this.getUri();
63
98
  this.toDispose.push(Disposable.create(() => this.loading.reject(new Error(`Preference provider for '${uri}' was disposed.`))));
99
+
100
+ this.preferenceStorage = this.preferenceStorageFactory(uri, this.getScope());
101
+ this.preferenceStorage.onDidChangeFileContent(async ({ content, fileOK }) => {
102
+ this.fileExists = fileOK;
103
+ this.readPreferencesFromContent(content);
104
+ await this.fireDidPreferencesChanged(); // Ensure all consumers of the event have received it.¨
105
+ return true;
106
+ });
64
107
  await this.readPreferencesFromFile();
65
108
  this._ready.resolve();
66
109
  this.loading.resolve();
67
- const storageUri = this.toFileManager().getConfigUri();
110
+
68
111
  this.toDispose.pushAll([
69
- this.fileService.watch(storageUri),
70
- this.fileService.onDidFilesChange(e => {
71
- if (e.contains(storageUri)) {
72
- this.readPreferencesFromFile();
73
- }
74
- }),
75
112
  Disposable.create(() => this.reset()),
76
113
  ]);
77
114
  }
@@ -116,30 +153,8 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi
116
153
  return this.doSetPreference(key, path, value);
117
154
  }
118
155
 
119
- protected async doSetPreference(key: string, path: string[], value: unknown): Promise<boolean> {
120
- if (!this.transaction?.open) {
121
- const current = this.transaction;
122
- this.transaction = this.transactionFactory(this.toFileManager(), current?.result);
123
- this.transaction.onWillConclude(({ status, waitUntil }) => {
124
- if (status) {
125
- waitUntil((async () => {
126
- await this.readPreferencesFromFile();
127
- await this.fireDidPreferencesChanged(); // Ensure all consumers of the event have received it.
128
- })());
129
- }
130
- });
131
- this.toDispose.push(this.transaction);
132
- }
133
- return this.transaction.enqueueAction(key, path, value);
134
- }
135
-
136
- /**
137
- * Use this method as intermediary for interactions with actual files.
138
- * Allows individual providers to modify where they store their files without disrupting the preference system's
139
- * conventions about scope and file location.
140
- */
141
- protected toFileManager(): PreferenceContext {
142
- return this;
156
+ protected doSetPreference(key: string, path: string[], value: JSONValue): Promise<boolean> {
157
+ return this.preferenceStorage.writeValue(key, path, value);
143
158
  }
144
159
 
145
160
  protected getPath(preferenceName: string): string[] | undefined {
@@ -150,19 +165,16 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi
150
165
  return [preferenceName];
151
166
  }
152
167
 
153
- protected async readPreferencesFromFile(): Promise<void> {
154
- const content = await this.fileService.read(this.toFileManager().getConfigUri())
155
- .then(value => {
156
- this.fileExists = true;
157
- return value;
158
- })
159
- .catch(() => {
160
- this.fileExists = false;
161
- return { value: '' };
162
- });
163
- this.readPreferencesFromContent(content.value);
164
- }
168
+ protected readPreferencesFromFile(): Promise<void> {
169
+ return this.preferenceStorage.read().then(value => {
170
+ this.fileExists = true;
171
+ this.readPreferencesFromContent(value);
172
+ }).catch(() => {
173
+ this.fileExists = false;
174
+ this.readPreferencesFromContent('');
175
+ });
165
176
 
177
+ }
166
178
  protected readPreferencesFromContent(content: string): void {
167
179
  let preferencesInJson;
168
180
  try {
@@ -192,16 +204,16 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi
192
204
  for (const prefName of prefNames.values()) {
193
205
  const oldValue = oldPrefs[prefName];
194
206
  const newValue = newPrefs[prefName];
195
- const schemaProperties = this.schemaProvider.getCombinedSchema().properties[prefName];
196
- if (schemaProperties) {
197
- const scope = schemaProperties.scope;
207
+ const schemaProperty = this.schemaProvider.getSchemaProperty(prefName);
208
+ if (schemaProperty) {
209
+ const scope = schemaProperty.scope;
198
210
  // do not emit the change event if the change is made out of the defined preference scope
199
211
  if (!this.schemaProvider.isValidInScope(prefName, this.getScope())) {
200
212
  console.warn(`Preference ${prefName} in ${uri} can only be defined in scopes: ${PreferenceScope.getScopeNames(scope).join(', ')}.`);
201
213
  continue;
202
214
  }
203
215
  }
204
- if (!PreferenceProvider.deepEqual(newValue, oldValue)) {
216
+ if (!PreferenceUtils.deepEqual(newValue, oldValue)) {
205
217
  prefChanges.push({
206
218
  preferenceName: prefName, newValue, oldValue, scope: this.getScope(), domain: this.getDomain()
207
219
  });
@@ -0,0 +1,65 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2021 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import * as jsoncparser from 'jsonc-parser';
18
+ import { inject, injectable } from '@theia/core/shared/inversify';
19
+ import { JSONValue } from '@theia/core/shared/@lumino/coreutils';
20
+ import { isWindows, PreferenceService } from '@theia/core';
21
+
22
+ @injectable()
23
+ export class JSONCEditor {
24
+ @inject(PreferenceService)
25
+ protected readonly preferenceService: PreferenceService;
26
+
27
+ setValue(model: string, path: jsoncparser.JSONPath, value: JSONValue): string {
28
+ const edits = this.getEditOperations(model, path, value);
29
+ return jsoncparser.applyEdits(model, edits);
30
+ }
31
+
32
+ protected getEditOperations(content: string, path: jsoncparser.JSONPath, value: JSONValue): jsoncparser.Edit[] {
33
+ // Everything is already undefined - no need for changes.
34
+ if (!content && value === undefined) {
35
+ return [];
36
+ }
37
+ // Delete the entire document.
38
+ if (!path.length && value === undefined) {
39
+ return [{
40
+ offset: 0,
41
+ length: content.length,
42
+ content: ''
43
+ }];
44
+ }
45
+ const tabSize = this.preferenceService.get('[json].editor.tabSize', 4);
46
+ const insertSpaces = this.preferenceService.get('[json].editor.insertSpaces', true);
47
+
48
+ const jsonCOptions = {
49
+ formattingOptions: {
50
+ insertSpaces,
51
+ tabSize,
52
+ eol: this.getEOL()
53
+ }
54
+ };
55
+ return jsoncparser.modify(content, path, value, jsonCOptions);
56
+ }
57
+
58
+ getEOL(): string {
59
+ const eol = this.preferenceService.get('[json].files.eol');
60
+ if (eol && typeof eol === 'string' && eol !== 'auto') {
61
+ return eol;
62
+ }
63
+ return isWindows ? '\r\n' : '\n';
64
+ }
65
+ }