@opensumi/ide-editor 2.21.13 → 2.22.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 (238) hide show
  1. package/lib/browser/breadcrumb/default.js.map +1 -1
  2. package/lib/browser/breadcrumb/document-symbol.js.map +1 -1
  3. package/lib/browser/breadcrumb/index.js.map +1 -1
  4. package/lib/browser/component.js.map +1 -1
  5. package/lib/browser/decoration-applier.js.map +1 -1
  6. package/lib/browser/diff/compare.js.map +1 -1
  7. package/lib/browser/diff/index.d.ts.map +1 -1
  8. package/lib/browser/diff/index.js +1 -1
  9. package/lib/browser/diff/index.js.map +1 -1
  10. package/lib/browser/doc-cache/empty-doc-cache.js.map +1 -1
  11. package/lib/browser/doc-cache/local-storage-cache.js.map +1 -1
  12. package/lib/browser/doc-model/editor-document-model-service.js +3 -3
  13. package/lib/browser/doc-model/editor-document-model-service.js.map +1 -1
  14. package/lib/browser/doc-model/editor-document-model.d.ts +8 -0
  15. package/lib/browser/doc-model/editor-document-model.d.ts.map +1 -1
  16. package/lib/browser/doc-model/editor-document-model.js +61 -11
  17. package/lib/browser/doc-model/editor-document-model.js.map +1 -1
  18. package/lib/browser/doc-model/editor-document-registry.js.map +1 -1
  19. package/lib/browser/doc-model/override.js.map +1 -1
  20. package/lib/browser/doc-model/save-task.js +1 -1
  21. package/lib/browser/doc-model/save-task.js.map +1 -1
  22. package/lib/browser/doc-model/saveParticipants.d.ts +7 -7
  23. package/lib/browser/doc-model/saveParticipants.d.ts.map +1 -1
  24. package/lib/browser/doc-model/saveParticipants.js +69 -38
  25. package/lib/browser/doc-model/saveParticipants.js.map +1 -1
  26. package/lib/browser/doc-model/types.d.ts +1 -1
  27. package/lib/browser/doc-model/types.d.ts.map +1 -1
  28. package/lib/browser/editor-collection.service.d.ts +8 -3
  29. package/lib/browser/editor-collection.service.d.ts.map +1 -1
  30. package/lib/browser/editor-collection.service.js +75 -66
  31. package/lib/browser/editor-collection.service.js.map +1 -1
  32. package/lib/browser/editor-opener.js.map +1 -1
  33. package/lib/browser/editor.contribution.d.ts.map +1 -1
  34. package/lib/browser/editor.contribution.js +31 -3
  35. package/lib/browser/editor.contribution.js.map +1 -1
  36. package/lib/browser/editor.decoration.service.d.ts +5 -6
  37. package/lib/browser/editor.decoration.service.d.ts.map +1 -1
  38. package/lib/browser/editor.decoration.service.js +9 -1
  39. package/lib/browser/editor.decoration.service.js.map +1 -1
  40. package/lib/browser/editor.override.js +2 -2
  41. package/lib/browser/editor.override.js.map +1 -1
  42. package/lib/browser/editor.status-bar.service.js.map +1 -1
  43. package/lib/browser/editor.view.d.ts.map +1 -1
  44. package/lib/browser/editor.view.js +20 -23
  45. package/lib/browser/editor.view.js.map +1 -1
  46. package/lib/browser/error.d.ts +1 -1
  47. package/lib/browser/error.d.ts.map +1 -1
  48. package/lib/browser/feature.js.map +1 -1
  49. package/lib/browser/format/format.service.js.map +1 -1
  50. package/lib/browser/format/formatterSelect.js.map +1 -1
  51. package/lib/browser/fs-resource/file-tree-set.js +6 -6
  52. package/lib/browser/fs-resource/file-tree-set.js.map +1 -1
  53. package/lib/browser/fs-resource/fs-editor-doc.js +1 -1
  54. package/lib/browser/fs-resource/fs-editor-doc.js.map +1 -1
  55. package/lib/browser/fs-resource/fs-resource.js.map +1 -1
  56. package/lib/browser/fs-resource/index.js.map +1 -1
  57. package/lib/browser/history/index.d.ts.map +1 -1
  58. package/lib/browser/history/index.js +2 -1
  59. package/lib/browser/history/index.js.map +1 -1
  60. package/lib/browser/index.d.ts.map +1 -1
  61. package/lib/browser/index.js +2 -0
  62. package/lib/browser/index.js.map +1 -1
  63. package/lib/browser/language/diagnostic-collection.d.ts +5 -5
  64. package/lib/browser/language/diagnostic-collection.d.ts.map +1 -1
  65. package/lib/browser/language/diagnostic-collection.js +1 -1
  66. package/lib/browser/language/diagnostic-collection.js.map +1 -1
  67. package/lib/browser/language/language-status.contribution.js.map +1 -1
  68. package/lib/browser/language/language-status.service.js.map +1 -1
  69. package/lib/browser/language/language.service.d.ts +4 -3
  70. package/lib/browser/language/language.service.d.ts.map +1 -1
  71. package/lib/browser/language/language.service.js +8 -2
  72. package/lib/browser/language/language.service.js.map +1 -1
  73. package/lib/browser/menu/editor.context.js +3 -3
  74. package/lib/browser/menu/editor.context.js.map +1 -1
  75. package/lib/browser/menu/editor.menu.d.ts +2 -2
  76. package/lib/browser/menu/editor.menu.d.ts.map +1 -1
  77. package/lib/browser/menu/editor.menu.js +6 -8
  78. package/lib/browser/menu/editor.menu.js.map +1 -1
  79. package/lib/browser/menu/open-type-menu.contribution.js +9 -9
  80. package/lib/browser/menu/open-type-menu.contribution.js.map +1 -1
  81. package/lib/browser/menu/title-context.menu.js.map +1 -1
  82. package/lib/browser/merge-editor/merge-editor.contribution.d.ts +8 -0
  83. package/lib/browser/merge-editor/merge-editor.contribution.d.ts.map +1 -0
  84. package/lib/browser/merge-editor/merge-editor.contribution.js +29 -0
  85. package/lib/browser/merge-editor/merge-editor.contribution.js.map +1 -0
  86. package/lib/browser/merge-editor/merge-editor.provider.d.ts +8 -0
  87. package/lib/browser/merge-editor/merge-editor.provider.d.ts.map +1 -0
  88. package/lib/browser/merge-editor/merge-editor.provider.js +44 -0
  89. package/lib/browser/merge-editor/merge-editor.provider.js.map +1 -0
  90. package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.contribution.js.map +1 -1
  91. package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.service.js +7 -7
  92. package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.service.js.map +1 -1
  93. package/lib/browser/monaco-contrib/command/command.service.d.ts +1 -1
  94. package/lib/browser/monaco-contrib/command/command.service.d.ts.map +1 -1
  95. package/lib/browser/monaco-contrib/command/command.service.js.map +1 -1
  96. package/lib/browser/monaco-contrib/tokenizer/textmate-registry.js.map +1 -1
  97. package/lib/browser/monaco-contrib/tokenizer/textmate.service.d.ts +2 -1
  98. package/lib/browser/monaco-contrib/tokenizer/textmate.service.d.ts.map +1 -1
  99. package/lib/browser/monaco-contrib/tokenizer/textmate.service.js +5 -2
  100. package/lib/browser/monaco-contrib/tokenizer/textmate.service.js.map +1 -1
  101. package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.contribution.js.map +1 -1
  102. package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.js +7 -7
  103. package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.js.map +1 -1
  104. package/lib/browser/navigation.module.less +1 -1
  105. package/lib/browser/navigation.view.d.ts.map +1 -1
  106. package/lib/browser/navigation.view.js +26 -15
  107. package/lib/browser/navigation.view.js.map +1 -1
  108. package/lib/browser/preference/contribution.js.map +1 -1
  109. package/lib/browser/preference/converter.d.ts +3 -3
  110. package/lib/browser/preference/converter.d.ts.map +1 -1
  111. package/lib/browser/preference/schema.d.ts +1 -1
  112. package/lib/browser/preference/schema.d.ts.map +1 -1
  113. package/lib/browser/preference/schema.js +8 -8
  114. package/lib/browser/preference/schema.js.map +1 -1
  115. package/lib/browser/quick-open/go-to-line.js.map +1 -1
  116. package/lib/browser/quick-open/workspace-symbol-quickopen.d.ts.map +1 -1
  117. package/lib/browser/quick-open/workspace-symbol-quickopen.js +2 -2
  118. package/lib/browser/quick-open/workspace-symbol-quickopen.js.map +1 -1
  119. package/lib/browser/resource.service.js.map +1 -1
  120. package/lib/browser/tab.view.d.ts +1 -1
  121. package/lib/browser/tab.view.d.ts.map +1 -1
  122. package/lib/browser/tab.view.js +2 -2
  123. package/lib/browser/tab.view.js.map +1 -1
  124. package/lib/browser/types.d.ts +5 -5
  125. package/lib/browser/types.d.ts.map +1 -1
  126. package/lib/browser/untitled-resource.js +1 -1
  127. package/lib/browser/untitled-resource.js.map +1 -1
  128. package/lib/browser/view/suggest-widget.js.map +1 -1
  129. package/lib/browser/workbench-editor.service.d.ts +17 -0
  130. package/lib/browser/workbench-editor.service.d.ts.map +1 -1
  131. package/lib/browser/workbench-editor.service.js +259 -176
  132. package/lib/browser/workbench-editor.service.js.map +1 -1
  133. package/lib/common/doc-cache.d.ts +2 -2
  134. package/lib/common/doc-cache.d.ts.map +1 -1
  135. package/lib/common/editor.d.ts +20 -6
  136. package/lib/common/editor.d.ts.map +1 -1
  137. package/lib/common/editor.js +12 -1
  138. package/lib/common/editor.js.map +1 -1
  139. package/lib/common/language.d.ts +18 -7
  140. package/lib/common/language.d.ts.map +1 -1
  141. package/lib/common/language.js +15 -7
  142. package/lib/common/language.js.map +1 -1
  143. package/lib/common/mocks/workbench-editor.service.js.map +1 -1
  144. package/lib/common/resource.d.ts +8 -2
  145. package/lib/common/resource.d.ts.map +1 -1
  146. package/lib/common/resource.js +1 -0
  147. package/lib/common/resource.js.map +1 -1
  148. package/package.json +17 -16
  149. package/src/browser/breadcrumb/default.ts +299 -0
  150. package/src/browser/breadcrumb/document-symbol.ts +187 -0
  151. package/src/browser/breadcrumb/index.ts +96 -0
  152. package/src/browser/component.ts +204 -0
  153. package/src/browser/decoration-applier.ts +256 -0
  154. package/src/browser/diff/compare.ts +99 -0
  155. package/src/browser/diff/index.ts +81 -0
  156. package/src/browser/doc-cache/empty-doc-cache.ts +26 -0
  157. package/src/browser/doc-cache/index.ts +2 -0
  158. package/src/browser/doc-cache/local-storage-cache.ts +67 -0
  159. package/src/browser/doc-model/editor-document-error.ts +10 -0
  160. package/src/browser/doc-model/editor-document-model-service.ts +346 -0
  161. package/src/browser/doc-model/editor-document-model.ts +690 -0
  162. package/src/browser/doc-model/editor-document-registry.ts +119 -0
  163. package/src/browser/doc-model/editor-is-fn.ts +9 -0
  164. package/src/browser/doc-model/main.ts +4 -0
  165. package/src/browser/doc-model/override.ts +49 -0
  166. package/src/browser/doc-model/save-task.ts +88 -0
  167. package/src/browser/doc-model/saveParticipants.ts +227 -0
  168. package/src/browser/doc-model/types.ts +350 -0
  169. package/src/browser/editor-collection.service.ts +790 -0
  170. package/src/browser/editor-opener.ts +44 -0
  171. package/src/browser/editor.contribution.ts +1438 -0
  172. package/src/browser/editor.decoration.service.ts +247 -0
  173. package/src/browser/editor.less +4 -0
  174. package/src/browser/editor.module.less +548 -0
  175. package/src/browser/editor.override.ts +133 -0
  176. package/src/browser/editor.status-bar.service.ts +116 -0
  177. package/src/browser/editor.view.tsx +623 -0
  178. package/src/browser/error.ts +21 -0
  179. package/src/browser/feature.ts +63 -0
  180. package/src/browser/format/format.service.ts +95 -0
  181. package/src/browser/format/formatterSelect.ts +82 -0
  182. package/src/browser/fs-resource/file-tree-set.ts +126 -0
  183. package/src/browser/fs-resource/fs-editor-doc.ts +213 -0
  184. package/src/browser/fs-resource/fs-resource.ts +247 -0
  185. package/src/browser/fs-resource/index.ts +27 -0
  186. package/src/browser/grid/grid.service.ts +288 -0
  187. package/src/browser/history/index.ts +228 -0
  188. package/src/browser/index.ts +236 -0
  189. package/src/browser/language/diagnostic-collection.ts +83 -0
  190. package/src/browser/language/language-status.contribution.ts +81 -0
  191. package/src/browser/language/language-status.service.ts +32 -0
  192. package/src/browser/language/language.service.ts +185 -0
  193. package/src/browser/menu/editor.context.ts +186 -0
  194. package/src/browser/menu/editor.menu.ts +45 -0
  195. package/src/browser/menu/open-type-menu.contribution.ts +90 -0
  196. package/src/browser/menu/title-context.menu.ts +54 -0
  197. package/src/browser/merge-editor/merge-editor.contribution.ts +25 -0
  198. package/src/browser/merge-editor/merge-editor.provider.ts +36 -0
  199. package/src/browser/monaco-contrib/callHierarchy/callHierarchy.contribution.ts +78 -0
  200. package/src/browser/monaco-contrib/callHierarchy/callHierarchy.service.ts +160 -0
  201. package/src/browser/monaco-contrib/command/command.service.ts +438 -0
  202. package/src/browser/monaco-contrib/index.ts +4 -0
  203. package/src/browser/monaco-contrib/tokenizer/textmate-registry.ts +107 -0
  204. package/src/browser/monaco-contrib/tokenizer/textmate-tokenizer.ts +104 -0
  205. package/src/browser/monaco-contrib/tokenizer/textmate.service.ts +925 -0
  206. package/src/browser/monaco-contrib/typeHierarchy/typeHierarchy.contribution.ts +78 -0
  207. package/src/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.ts +154 -0
  208. package/src/browser/navigation.module.less +96 -0
  209. package/src/browser/navigation.view.tsx +254 -0
  210. package/src/browser/preference/contribution.ts +8 -0
  211. package/src/browser/preference/converter.ts +793 -0
  212. package/src/browser/preference/schema.ts +1896 -0
  213. package/src/browser/preference/util.ts +14 -0
  214. package/src/browser/quick-open/go-to-line.ts +164 -0
  215. package/src/browser/quick-open/workspace-symbol-quickopen.ts +276 -0
  216. package/src/browser/resource.service.ts +263 -0
  217. package/src/browser/tab.view.tsx +514 -0
  218. package/src/browser/types.ts +467 -0
  219. package/src/browser/untitled-resource.ts +223 -0
  220. package/src/browser/view/editor.react.tsx +82 -0
  221. package/src/browser/view/react-hook.tsx +7 -0
  222. package/src/browser/view/suggest-widget.ts +77 -0
  223. package/src/browser/view/topPadding.ts +18 -0
  224. package/src/browser/workbench-editor.service.ts +2291 -0
  225. package/src/common/doc-cache.ts +117 -0
  226. package/src/common/editor.ts +799 -0
  227. package/src/common/index.ts +6 -0
  228. package/src/common/language-status.ts +33 -0
  229. package/src/common/language.ts +206 -0
  230. package/src/common/mocks/workbench-editor.service.ts +52 -0
  231. package/src/common/resource.ts +147 -0
  232. package/src/common/utils.ts +10 -0
  233. package/src/index.ts +1 -0
  234. package/lib/browser/component/scroll/scroll.d.ts +0 -2
  235. package/lib/browser/component/scroll/scroll.d.ts.map +0 -1
  236. package/lib/browser/component/scroll/scroll.js +0 -5
  237. package/lib/browser/component/scroll/scroll.js.map +0 -1
  238. package/lib/browser/component/scroll/scroll.module.less +0 -86
@@ -0,0 +1,95 @@
1
+ import { Injector, Injectable, Autowired, INJECTOR_TOKEN } from '@opensumi/di';
2
+ import { CancellationToken, ILogger } from '@opensumi/ide-core-common';
3
+ import { languageFeaturesService } from '@opensumi/ide-monaco/lib/browser/monaco-api/languages';
4
+ import { Range } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
5
+ import {
6
+ DocumentFormattingEditProvider,
7
+ DocumentRangeFormattingEditProvider,
8
+ } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages';
9
+ import {
10
+ getRealAndSyntheticDocumentFormattersOrdered,
11
+ FormattingMode,
12
+ } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/format/browser/format';
13
+ import { FormattingEdit } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/format/browser/formattingEdit';
14
+
15
+ import { WorkbenchEditorService } from '../types';
16
+ import { WorkbenchEditorServiceImpl } from '../workbench-editor.service';
17
+
18
+ import { FormattingSelector } from './formatterSelect';
19
+
20
+ @Injectable()
21
+ export class DocumentFormatService {
22
+ @Autowired(ILogger)
23
+ private readonly logger: ILogger;
24
+
25
+ @Autowired(WorkbenchEditorService)
26
+ private workbenchEditorService: WorkbenchEditorServiceImpl;
27
+
28
+ @Autowired(INJECTOR_TOKEN)
29
+ injector: Injector;
30
+
31
+ async formatDocumentWith() {
32
+ const model = this.workbenchEditorService.currentEditor?.monacoEditor.getModel();
33
+ if (model) {
34
+ const formatterProviders = getRealAndSyntheticDocumentFormattersOrdered(
35
+ languageFeaturesService.documentFormattingEditProvider,
36
+ languageFeaturesService.documentRangeFormattingEditProvider,
37
+ model,
38
+ );
39
+ const selector = this.injector.get(FormattingSelector);
40
+ const formatter = await selector.select(formatterProviders, model, FormattingMode.Explicit, true);
41
+ if (formatter) {
42
+ try {
43
+ const edits = await (formatter as DocumentFormattingEditProvider).provideDocumentFormattingEdits(
44
+ model,
45
+ model.getFormattingOptions(),
46
+ CancellationToken.None,
47
+ );
48
+ if (edits) {
49
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
50
+ FormattingEdit.execute(this.workbenchEditorService.currentEditor?.monacoEditor!, edits, true);
51
+ }
52
+ } catch (err) {
53
+ this.logger.error('execute format document with error', err);
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ async formatSelectionWith() {
60
+ if (!this.workbenchEditorService.currentEditor?.monacoEditor.hasModel()) {
61
+ return;
62
+ }
63
+ const model = this.workbenchEditorService.currentEditor?.monacoEditor.getModel();
64
+ if (model) {
65
+ let range: Range | null | undefined = this.workbenchEditorService.currentEditor?.monacoEditor.getSelection();
66
+ if (range?.isEmpty()) {
67
+ range = new Range(
68
+ range.startLineNumber,
69
+ 1,
70
+ range.startLineNumber,
71
+ model.getLineMaxColumn(range.startLineNumber),
72
+ );
73
+ }
74
+ const formatterProviders = languageFeaturesService.documentRangeFormattingEditProvider.ordered(model);
75
+ const selector = this.injector.get(FormattingSelector);
76
+ const formatter = await selector.select(formatterProviders, model, FormattingMode.Explicit, true);
77
+ if (formatter) {
78
+ try {
79
+ const edits = await (formatter as DocumentRangeFormattingEditProvider).provideDocumentRangeFormattingEdits(
80
+ model,
81
+ range!,
82
+ model.getFormattingOptions(),
83
+ CancellationToken.None,
84
+ );
85
+ if (edits) {
86
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
87
+ FormattingEdit.execute(this.workbenchEditorService.currentEditor?.monacoEditor!, edits, true);
88
+ }
89
+ } catch (err) {
90
+ this.logger.error('execute format document with error', err);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,82 @@
1
+ import { Injectable, Autowired } from '@opensumi/di';
2
+ import { QuickPickService, localize, PreferenceService, URI, PreferenceScope } from '@opensumi/ide-core-browser';
3
+ import { ITextModel } from '@opensumi/ide-monaco/lib/browser/monaco-api/types';
4
+ import { FormattingMode } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/format/browser/format';
5
+ import * as monaco from '@opensumi/monaco-editor-core/esm/vs/editor/editor.api';
6
+
7
+ import { IEditorDocumentModelService } from '../doc-model/types';
8
+
9
+ type IProvider = monaco.languages.DocumentFormattingEditProvider | monaco.languages.DocumentRangeFormattingEditProvider;
10
+
11
+ @Injectable()
12
+ export class FormattingSelector {
13
+ @Autowired(QuickPickService)
14
+ private quickPickService: QuickPickService;
15
+
16
+ @Autowired(PreferenceService)
17
+ private preferenceService: PreferenceService;
18
+
19
+ @Autowired(IEditorDocumentModelService)
20
+ private modelService: IEditorDocumentModelService;
21
+
22
+ async select(
23
+ formatters: Array<
24
+ monaco.languages.DocumentFormattingEditProvider | monaco.languages.DocumentRangeFormattingEditProvider
25
+ >,
26
+ document: ITextModel,
27
+ mode: FormattingMode,
28
+ forceSelect = false,
29
+ ): Promise<
30
+ monaco.languages.DocumentFormattingEditProvider | monaco.languages.DocumentRangeFormattingEditProvider | undefined
31
+ > {
32
+ const docRef = this.modelService.getModelReference(URI.from(document.uri.toJSON()));
33
+ if (!docRef) {
34
+ return;
35
+ }
36
+ const languageId = docRef.instance.languageId;
37
+ docRef.dispose();
38
+ let preferred;
39
+ if (!forceSelect) {
40
+ preferred = (this.preferenceService.get<{ [key: string]: string }>('editor.preferredFormatter') || {})[
41
+ languageId
42
+ ];
43
+ }
44
+
45
+ const elements: { [key: string]: IProvider } = {};
46
+ formatters.forEach((provider: IProvider) => {
47
+ if (provider.extensionId) {
48
+ elements[provider.extensionId] = provider;
49
+ }
50
+ });
51
+
52
+ if (preferred && !forceSelect) {
53
+ const idx = formatters.findIndex((provider: IProvider) => provider.extensionId === preferred);
54
+ if (idx >= 0) {
55
+ return formatters[idx];
56
+ }
57
+ } else if (formatters.length < 2 && !forceSelect) {
58
+ return formatters[0];
59
+ }
60
+
61
+ if (mode === FormattingMode.Explicit) {
62
+ const selected = await this.quickPickService.show(
63
+ Object.keys(elements).map((k) => ({
64
+ label: elements[k].displayName!,
65
+ value: elements[k].extensionId,
66
+ })),
67
+ { placeholder: localize('editor.format.chooseFormatter') },
68
+ );
69
+ if (selected) {
70
+ const config = this.preferenceService.get<{ [key: string]: string }>('editor.preferredFormatter') || {};
71
+ this.preferenceService.set(
72
+ 'editor.preferredFormatter',
73
+ { ...config, [languageId]: selected },
74
+ PreferenceScope.User,
75
+ );
76
+ return elements[selected];
77
+ }
78
+ } else {
79
+ return undefined;
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * 对于 tree-like 的结构,希望父节点被删除/更新时,能影响到子节点
3
+ */
4
+ export class FileTreeNode {
5
+ public readonly key: string;
6
+
7
+ private _children: Map<string, FileTreeNode> | undefined;
8
+
9
+ private _disposed = false;
10
+
11
+ private _onDisposed: () => void;
12
+
13
+ private get children() {
14
+ if (!this._children) {
15
+ this._children = new Map();
16
+ }
17
+ return this._children!;
18
+ }
19
+
20
+ constructor(public readonly path: string, public readonly parent?: FileTreeNode, private separator: string = '/') {
21
+ if (parent) {
22
+ this.key = parent.key + this.separator + path;
23
+ } else {
24
+ this.key = path;
25
+ }
26
+ }
27
+
28
+ public bindOnDispose(callback: () => void) {
29
+ this._onDisposed = callback;
30
+ }
31
+
32
+ addChild(path: string): FileTreeNode {
33
+ const node = new FileTreeNode(path, this, this.separator);
34
+ this.children.set(path, node);
35
+ return node;
36
+ }
37
+
38
+ getAllDescendants(): FileTreeNode[] {
39
+ if (!this._children) {
40
+ return [this];
41
+ } else {
42
+ const result: FileTreeNode[] = [this];
43
+ this.children.forEach((c) => {
44
+ result.push(...c.getAllDescendants());
45
+ });
46
+ return result;
47
+ }
48
+ }
49
+
50
+ dispose() {
51
+ if (this._disposed) {
52
+ return;
53
+ }
54
+ if (this.parent) {
55
+ this.parent.children.delete(this.path);
56
+ if (this.parent.children.size === 0) {
57
+ this.parent.dispose();
58
+ }
59
+ }
60
+ if (this._onDisposed) {
61
+ this._onDisposed();
62
+ }
63
+ this._disposed = true;
64
+ }
65
+ }
66
+
67
+ export class FileTreeSet<T = any> {
68
+ private separator: string;
69
+ constructor(isWindows = false) {
70
+ this.separator = isWindows ? '\\' : '/';
71
+ }
72
+
73
+ private nodes: Map<string, FileTreeNode> = new Map();
74
+
75
+ add<T>(path: string) {
76
+ const segments = path.split(this.separator);
77
+ let p: string | undefined;
78
+ let currentNode: FileTreeNode | undefined;
79
+ for (const seg of segments) {
80
+ if (p === undefined) {
81
+ p = seg;
82
+ } else {
83
+ p += this.separator + seg;
84
+ }
85
+ let node: FileTreeNode;
86
+ if (this.nodes.has(p)) {
87
+ node = this.nodes.get(p)!;
88
+ } else {
89
+ if (currentNode) {
90
+ node = currentNode!.addChild(seg);
91
+ } else {
92
+ node = new FileTreeNode(seg, undefined, this.separator);
93
+ }
94
+ node.bindOnDispose(() => {
95
+ this.nodes.delete(node.key);
96
+ });
97
+ this.nodes.set(node.key, node);
98
+ }
99
+ currentNode = node;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * 返回所有被影响的子节点
105
+ * @param path
106
+ */
107
+ delete(path: string): string[] {
108
+ const effected = this.effects(path);
109
+ effected.forEach((e) => {
110
+ const node = this.nodes.get(e);
111
+ if (node) {
112
+ node.dispose();
113
+ }
114
+ });
115
+ return effected;
116
+ }
117
+
118
+ effects(path: string): string[] {
119
+ const target = this.nodes.get(path);
120
+ if (!target) {
121
+ return [];
122
+ } else {
123
+ return target!.getAllDescendants().map((n) => n.key);
124
+ }
125
+ }
126
+ }
@@ -0,0 +1,213 @@
1
+ import { Injectable, Autowired } from '@opensumi/di';
2
+ import {
3
+ Emitter,
4
+ URI,
5
+ Event,
6
+ IApplicationService,
7
+ FileChangeType,
8
+ OperatingSystem,
9
+ IEditorDocumentChange,
10
+ IEditorDocumentModelSaveResult,
11
+ PreferenceService,
12
+ getLanguageIdFromMonaco,
13
+ EncodingRegistry,
14
+ UTF8_with_bom,
15
+ UTF8,
16
+ detectEncodingFromBuffer,
17
+ SaveTaskResponseState,
18
+ } from '@opensumi/ide-core-browser';
19
+ import { IFileServiceClient } from '@opensumi/ide-file-service';
20
+ import { EOL } from '@opensumi/ide-monaco/lib/browser/monaco-api/types';
21
+
22
+ import { IEditorDocumentModelContentProvider } from '../doc-model/types';
23
+ import { EditorPreferences } from '../preference/schema';
24
+
25
+ export interface ReadEncodingOptions {
26
+ /**
27
+ * The optional encoding parameter allows to specify the desired encoding when resolving
28
+ * the contents of the file.
29
+ */
30
+ encoding?: string;
31
+
32
+ /**
33
+ * The optional guessEncoding parameter allows to guess encoding from content of the file.
34
+ */
35
+ autoGuessEncoding?: boolean;
36
+ }
37
+
38
+ /**
39
+ * 通用的用来处理 FileSystem 提供的文档
40
+ * 可以 extend 这个来添加更强的能力,如 file-scheme 中的 file-doc
41
+ */
42
+ @Injectable()
43
+ export class BaseFileSystemEditorDocumentProvider implements IEditorDocumentModelContentProvider {
44
+ protected _onDidChangeContent: Emitter<URI> = new Emitter();
45
+
46
+ public onDidChangeContent: Event<URI> = this._onDidChangeContent.event;
47
+
48
+ protected _fileContentMd5OnBrowserFs: Set<string> = new Set();
49
+
50
+ private _detectedEncodingMap = new Map<string, string>();
51
+
52
+ @Autowired(IFileServiceClient)
53
+ protected readonly fileServiceClient: IFileServiceClient;
54
+
55
+ @Autowired(EditorPreferences)
56
+ protected readonly editorPreferences: EditorPreferences;
57
+
58
+ @Autowired(IApplicationService)
59
+ protected readonly applicationService: IApplicationService;
60
+
61
+ @Autowired(PreferenceService)
62
+ protected readonly preferenceService: PreferenceService;
63
+
64
+ @Autowired(EncodingRegistry)
65
+ encodingRegistry: EncodingRegistry;
66
+
67
+ constructor() {
68
+ this.fileServiceClient.onFilesChanged((changes) => {
69
+ changes.forEach((change) => {
70
+ if (this._fileContentMd5OnBrowserFs.has(change.uri)) {
71
+ if (change.type === FileChangeType.ADDED || change.type === FileChangeType.UPDATED) {
72
+ this._onDidChangeContent.fire(new URI(change.uri));
73
+ }
74
+ }
75
+ });
76
+ });
77
+ }
78
+
79
+ handlesScheme(scheme: string) {
80
+ return this.fileServiceClient.handlesScheme(scheme);
81
+ }
82
+
83
+ provideEncoding(uri: URI) {
84
+ return this._detectedEncodingMap.get(uri.toString()) || UTF8;
85
+ }
86
+
87
+ async provideEOL(uri: URI) {
88
+ const backendOS = await this.applicationService.getBackendOS();
89
+ const eol = this.preferenceService.get<EOL | 'auto'>(
90
+ 'files.eol',
91
+ 'auto',
92
+ uri.toString(),
93
+ getLanguageIdFromMonaco(uri)!,
94
+ )!;
95
+
96
+ if (eol !== 'auto') {
97
+ return eol;
98
+ }
99
+ return backendOS === OperatingSystem.Windows ? EOL.CRLF : EOL.LF;
100
+ }
101
+
102
+ async read(uri: URI, options: ReadEncodingOptions): Promise<{ encoding: string; content: string }> {
103
+ const { content: buffer } = await this.fileServiceClient.readFile(uri.toString());
104
+
105
+ const guessEncoding =
106
+ options.autoGuessEncoding ||
107
+ this.preferenceService.get<boolean>(
108
+ 'files.autoGuessEncoding',
109
+ undefined,
110
+ uri.toString(),
111
+ getLanguageIdFromMonaco(uri)!,
112
+ );
113
+ const detected = await detectEncodingFromBuffer(buffer, guessEncoding);
114
+ detected.encoding = await this.getReadEncoding(uri, options, detected.encoding);
115
+
116
+ const content = buffer.toString(detected.encoding);
117
+
118
+ const uriString = uri.toString();
119
+
120
+ this._detectedEncodingMap.set(uriString, detected.encoding);
121
+
122
+ // 记录表示这个文档被[这个editorDocumentProvider]引用了
123
+ this._fileContentMd5OnBrowserFs.add(uriString);
124
+
125
+ return {
126
+ encoding: detected.encoding || UTF8,
127
+ content,
128
+ };
129
+ }
130
+
131
+ async provideEditorDocumentModelContent(uri: URI, encoding: string) {
132
+ // TODO: 这部分要优化成buffer获取(长期来看是stream获取,encoding在哪一层做?)
133
+ // 暂时还是使用 resolveContent 内提供的 decode 功能
134
+ // 之后 encoding 做了分层之后和其他的需要 decode 的地方一起改
135
+ return (await this.read(uri, { encoding })).content;
136
+ }
137
+
138
+ async isReadonly(uri: URI): Promise<boolean> {
139
+ const readonlyFiles: string[] = this.editorPreferences['editor.readonlyFiles'];
140
+ if (readonlyFiles && readonlyFiles.length) {
141
+ for (const file of readonlyFiles) {
142
+ if (
143
+ uri.isEqual(URI.file(file)) ||
144
+ uri.matchGlobPattern(file) ||
145
+ uri.toString().endsWith(file.replace('./', ''))
146
+ ) {
147
+ return true;
148
+ }
149
+ }
150
+ }
151
+ return this.fileServiceClient.isReadonly(uri.toString());
152
+ }
153
+
154
+ async saveDocumentModel(
155
+ uri: URI,
156
+ content: string,
157
+ baseContent: string,
158
+ changes: IEditorDocumentChange[],
159
+ encoding: string,
160
+ ignoreDiff = false,
161
+ ): Promise<IEditorDocumentModelSaveResult> {
162
+ // 默认的文件系统都直接存 content
163
+ try {
164
+ const fileStat = await this.fileServiceClient.getFileStat(uri.toString());
165
+ if (!fileStat) {
166
+ await this.fileServiceClient.createFile(uri.toString(), { content, overwrite: true, encoding });
167
+ } else {
168
+ await this.fileServiceClient.setContent(fileStat, content, { encoding });
169
+ }
170
+ return {
171
+ state: SaveTaskResponseState.SUCCESS,
172
+ };
173
+ } catch (e) {
174
+ return {
175
+ state: SaveTaskResponseState.ERROR,
176
+ errorMessage: e.message,
177
+ };
178
+ }
179
+ }
180
+
181
+ onDidDisposeModel(uri: URI) {
182
+ this._fileContentMd5OnBrowserFs.delete(uri.toString());
183
+ }
184
+
185
+ async guessEncoding(uri: URI) {
186
+ return (await this.read(uri, { autoGuessEncoding: true })).encoding;
187
+ }
188
+
189
+ protected getReadEncoding(
190
+ resource: URI,
191
+ options: ReadEncodingOptions | undefined,
192
+ detectedEncoding: string | null,
193
+ ): Promise<string> {
194
+ let preferredEncoding: string | undefined;
195
+
196
+ // Encoding passed in as option
197
+ if (options?.encoding) {
198
+ if (detectedEncoding === UTF8_with_bom && options.encoding === UTF8) {
199
+ preferredEncoding = UTF8_with_bom; // indicate the file has BOM if we are to resolve with UTF 8
200
+ } else {
201
+ preferredEncoding = options.encoding; // give passed in encoding highest priority
202
+ }
203
+ } else if (detectedEncoding) {
204
+ preferredEncoding = detectedEncoding;
205
+ }
206
+
207
+ return this.getEncodingForResource(resource, preferredEncoding);
208
+ }
209
+
210
+ protected async getEncodingForResource(resource: URI, preferredEncoding?: string): Promise<string> {
211
+ return this.encodingRegistry.getEncodingForResource(resource, preferredEncoding);
212
+ }
213
+ }