@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,247 @@
1
+ import { Autowired, Injectable } from '@opensumi/di';
2
+ import {
3
+ OperatingSystem,
4
+ URI,
5
+ MaybePromise,
6
+ WithEventBus,
7
+ localize,
8
+ formatLocalize,
9
+ MessageType,
10
+ LRUMap,
11
+ IApplicationService,
12
+ } from '@opensumi/ide-core-browser';
13
+ import { LabelService } from '@opensumi/ide-core-browser/lib/services';
14
+ import { FileChangeType, path } from '@opensumi/ide-core-common';
15
+ import { IFileServiceClient, FileStat } from '@opensumi/ide-file-service/lib/common';
16
+ import { IDialogService } from '@opensumi/ide-overlay';
17
+
18
+ import { IResourceProvider, IResource, ResourceNeedUpdateEvent, AskSaveResult } from '../../common';
19
+ import { DIFF_SCHEME } from '../../common';
20
+ import { IEditorDocumentModelService } from '../doc-model/types';
21
+
22
+ import { FileTreeSet } from './file-tree-set';
23
+
24
+ const { Path } = path;
25
+
26
+ @Injectable()
27
+ export class FileSystemResourceProvider extends WithEventBus implements IResourceProvider {
28
+ private static SUBNAME_LIMIT = 20;
29
+
30
+ @Autowired()
31
+ protected labelService: LabelService;
32
+
33
+ @Autowired(IFileServiceClient)
34
+ protected fileServiceClient: IFileServiceClient;
35
+
36
+ @Autowired(IDialogService)
37
+ protected dialogService: IDialogService;
38
+
39
+ @Autowired(IEditorDocumentModelService)
40
+ protected documentModelService: IEditorDocumentModelService;
41
+
42
+ @Autowired(IApplicationService)
43
+ protected applicationService: IApplicationService;
44
+
45
+ cachedFileStat = new LRUMap<string, FileStat | undefined>(200, 100);
46
+
47
+ private involvedFiles: FileTreeSet;
48
+
49
+ private ready: Promise<void>;
50
+
51
+ constructor() {
52
+ super();
53
+ this.ready = this.init();
54
+ this.listen();
55
+ }
56
+
57
+ async init() {
58
+ const os = await this.applicationService.getBackendOS();
59
+ this.involvedFiles = new FileTreeSet(os === OperatingSystem.Windows);
60
+ }
61
+
62
+ handlesUri(uri: URI): number {
63
+ const scheme = uri.scheme;
64
+ if (this.fileServiceClient.handlesScheme(scheme)) {
65
+ return 10;
66
+ } else {
67
+ return -1;
68
+ }
69
+ }
70
+
71
+ protected listen() {
72
+ this.fileServiceClient.onFilesChanged((e) => {
73
+ e.forEach((change) => {
74
+ if (change.type === FileChangeType.ADDED || change.type === FileChangeType.DELETED) {
75
+ // 对于文件夹的删除,做要传递给子文件
76
+ const effectedPaths = this.involvedFiles?.effects(new URI(change.uri).codeUri.fsPath);
77
+ effectedPaths.forEach((p) => {
78
+ const effected = URI.file(p);
79
+ this.cachedFileStat.delete(effected.toString());
80
+ this.eventBus.fire(new ResourceNeedUpdateEvent(effected));
81
+ });
82
+ } else {
83
+ // Linux下,可能 update 事件代表了 create
84
+ // 此时如果 cached 是undefined,就更新
85
+ if (this.cachedFileStat.has(change.uri) && this.cachedFileStat.get(change.uri) === undefined) {
86
+ this.cachedFileStat.delete(change.uri);
87
+ this.eventBus.fire(new ResourceNeedUpdateEvent(new URI(change.uri)));
88
+ }
89
+ }
90
+ });
91
+ });
92
+ this.labelService.onDidChange((uri) => {
93
+ if (uri.codeUri.fsPath && this.involvedFiles?.effects(uri.codeUri.fsPath)) {
94
+ this.eventBus.fire(new ResourceNeedUpdateEvent(uri));
95
+ }
96
+ });
97
+ }
98
+
99
+ async getFileStat(uri: string) {
100
+ if (!this.cachedFileStat.has(uri)) {
101
+ this.cachedFileStat.set(uri, await this.fileServiceClient.getFileStat(uri.toString()));
102
+ }
103
+ return this.cachedFileStat.get(uri);
104
+ }
105
+
106
+ async provideResource(uri: URI): Promise<IResource<any>> {
107
+ // 获取文件类型 getFileType: (path: string) => string
108
+ await this.ready;
109
+ this.involvedFiles.add(uri.codeUri.fsPath);
110
+ return Promise.all([
111
+ this.getFileStat(uri.toString()),
112
+ this.labelService.getName(uri),
113
+ this.labelService.getIcon(uri),
114
+ ] as const).then(([stat, name, icon]) => ({
115
+ name: stat ? name : name + localize('file.resource-deleted', '(已删除)'),
116
+ icon,
117
+ uri,
118
+ metadata: null,
119
+ deleted: !stat,
120
+ supportsRevive: true,
121
+ }));
122
+ }
123
+
124
+ provideResourceSubname(resource: IResource, groupResources: IResource[]): string | null {
125
+ const shouldDiff: URI[] = [];
126
+ for (const res of groupResources) {
127
+ if (
128
+ this.fileServiceClient.handlesScheme(res.uri.scheme) &&
129
+ res.uri.displayName === resource.uri.displayName &&
130
+ res !== resource
131
+ ) {
132
+ // 存在file协议的相同名称的文件
133
+ shouldDiff.push(res.uri);
134
+ }
135
+ }
136
+ if (shouldDiff.length > 0) {
137
+ const tail = getMinimalDiffPath(resource.uri, shouldDiff);
138
+ if (tail.startsWith(Path.separator)) {
139
+ // 说明当前为全路径
140
+ if (tail.length > FileSystemResourceProvider.SUBNAME_LIMIT) {
141
+ return '...' + tail.slice(tail.length - FileSystemResourceProvider.SUBNAME_LIMIT);
142
+ } else {
143
+ return tail;
144
+ }
145
+ } else {
146
+ return '...' + Path.separator + getMinimalDiffPath(resource.uri, shouldDiff);
147
+ }
148
+ } else {
149
+ return null;
150
+ }
151
+ }
152
+
153
+ onDisposeResource(resource) {
154
+ this.involvedFiles?.delete(resource.uri.codeUri.fsPath);
155
+ this.cachedFileStat.delete(resource.uri.toString());
156
+ }
157
+ async shouldCloseResourceWithoutConfirm(resource: IResource) {
158
+ const documentModelRef = this.documentModelService.getModelReference(resource.uri, 'close-resource-check');
159
+ if (documentModelRef && documentModelRef.instance.dirty) {
160
+ return true;
161
+ }
162
+ return false;
163
+ }
164
+ async close(resource: IResource, saveAction?: AskSaveResult) {
165
+ const documentModelRef = this.documentModelService.getModelReference(resource.uri, 'close-resource-check');
166
+ if (!documentModelRef) {
167
+ return false;
168
+ }
169
+ if (saveAction === AskSaveResult.SAVE) {
170
+ const res = await documentModelRef.instance.save();
171
+ documentModelRef.dispose();
172
+ return res;
173
+ } else if (saveAction === AskSaveResult.REVERT) {
174
+ await documentModelRef.instance.revert();
175
+ documentModelRef.dispose();
176
+ return true;
177
+ } else if (!saveAction || saveAction === AskSaveResult.CANCEL) {
178
+ documentModelRef.dispose();
179
+ return false;
180
+ } else {
181
+ return true;
182
+ }
183
+ }
184
+ async shouldCloseResource(resource: IResource, openedResources: IResource[][]): Promise<boolean> {
185
+ let count = 0;
186
+ for (const resources of openedResources) {
187
+ for (const r of resources) {
188
+ if (r.uri.scheme === DIFF_SCHEME && r.metadata && r.metadata.modified.toString() === resource.uri.toString()) {
189
+ count++;
190
+ }
191
+ if (this.fileServiceClient.handlesScheme(r.uri.scheme) && r.uri.toString() === resource.uri.toString()) {
192
+ count++;
193
+ }
194
+ if (count > 1) {
195
+ return true;
196
+ }
197
+ }
198
+ }
199
+ const documentModelRef = this.documentModelService.getModelReference(resource.uri, 'close-resource-check');
200
+ if (!documentModelRef || !documentModelRef.instance.dirty) {
201
+ if (documentModelRef) {
202
+ documentModelRef.dispose();
203
+ }
204
+ return true;
205
+ }
206
+
207
+ // 询问用户是否保存
208
+ const buttons = {
209
+ [localize('file.prompt.dontSave', "Don't Save")]: AskSaveResult.REVERT,
210
+ [localize('file.prompt.save', 'Save')]: AskSaveResult.SAVE,
211
+ [localize('file.prompt.cancel', 'Cancel')]: AskSaveResult.CANCEL,
212
+ };
213
+ const selection = await this.dialogService.open(
214
+ formatLocalize('saveChangesMessage', resource.name),
215
+ MessageType.Info,
216
+ Object.keys(buttons),
217
+ );
218
+ const result = buttons[selection!];
219
+ return this.close(resource, result);
220
+ }
221
+ }
222
+
223
+ /**
224
+ * 找到 source 文件 url 和中从末尾开始和 target 不一样的 path
225
+ * @param source
226
+ * @param targets
227
+ */
228
+ function getMinimalDiffPath(source: URI, targets: URI[]): string {
229
+ const sourceDirPartsReverse = source.path.dir.toString().split(Path.separator).reverse();
230
+ const targetDirPartsReverses = targets.map((target) => target.path.dir.toString().split(Path.separator).reverse());
231
+ for (let i = 0; i < sourceDirPartsReverse.length; i++) {
232
+ let foundSame = false;
233
+ for (const targetDirPartsReverse of targetDirPartsReverses) {
234
+ if (targetDirPartsReverse[i] === sourceDirPartsReverse[i]) {
235
+ foundSame = true;
236
+ break;
237
+ }
238
+ }
239
+ if (!foundSame) {
240
+ return sourceDirPartsReverse
241
+ .slice(0, i + 1)
242
+ .reverse()
243
+ .join(Path.separator);
244
+ }
245
+ }
246
+ return sourceDirPartsReverse.reverse().join(Path.separator);
247
+ }
@@ -0,0 +1,27 @@
1
+ import { Autowired } from '@opensumi/di';
2
+ import { Domain } from '@opensumi/ide-core-browser';
3
+
4
+
5
+ import { ResourceService } from '../../common';
6
+ import { IEditorDocumentModelContentRegistry } from '../doc-model/types';
7
+ import { BrowserEditorContribution } from '../types';
8
+
9
+ import { BaseFileSystemEditorDocumentProvider } from './fs-editor-doc';
10
+ import { FileSystemResourceProvider } from './fs-resource';
11
+
12
+ @Domain(BrowserEditorContribution)
13
+ export class FileSystemResourceContribution implements BrowserEditorContribution {
14
+ @Autowired(FileSystemResourceProvider)
15
+ fsResourceProvider: FileSystemResourceProvider;
16
+
17
+ @Autowired(BaseFileSystemEditorDocumentProvider)
18
+ fsDocProvider: BaseFileSystemEditorDocumentProvider;
19
+
20
+ registerResource(registry: ResourceService) {
21
+ registry.registerResourceProvider(this.fsResourceProvider);
22
+ }
23
+
24
+ registerEditorDocumentModelContentProvider(registry: IEditorDocumentModelContentRegistry) {
25
+ registry.registerEditorDocumentModelContentProvider(this.fsDocProvider);
26
+ }
27
+ }
@@ -0,0 +1,288 @@
1
+ import { IDisposable, IEventBus, MaybeNull, Emitter } from '@opensumi/ide-core-browser';
2
+ import { makeRandomHexString } from '@opensumi/ide-core-common';
3
+
4
+ import { IEditorGroup, IEditorGroupState, Direction } from '../../common';
5
+ import { GridResizeEvent } from '../types';
6
+
7
+ export const editorGridUid = new Set();
8
+
9
+ export class EditorGrid implements IDisposable {
10
+ public editorGroup: IGridEditorGroup | null = null;
11
+
12
+ public children: EditorGrid[] = [];
13
+
14
+ public splitDirection: SplitDirection | undefined;
15
+
16
+ protected readonly _onDidGridStateChange = new Emitter<void>();
17
+
18
+ public readonly onDidGridStateChange = this._onDidGridStateChange.event;
19
+
20
+ protected readonly _onDidGridAndDesendantStateChange = new Emitter<void>();
21
+
22
+ public readonly onDidGridAndDesendantStateChange = this._onDidGridAndDesendantStateChange.event;
23
+
24
+ public readonly uid: string;
25
+
26
+ constructor(public parent?: EditorGrid) {
27
+ let uid = makeRandomHexString(5);
28
+ while (editorGridUid.has(uid)) {
29
+ uid = makeRandomHexString(5);
30
+ }
31
+ this.uid = uid;
32
+ editorGridUid.add(uid);
33
+ this.onDidGridStateChange(() => {
34
+ this._onDidGridAndDesendantStateChange.fire();
35
+ this.parent?._onDidGridAndDesendantStateChange.fire();
36
+ });
37
+ }
38
+
39
+ setEditorGroup(editorGroup: IGridEditorGroup) {
40
+ this.editorGroup = editorGroup;
41
+ editorGroup.grid = this;
42
+ this.splitDirection = undefined;
43
+ }
44
+ // 当前 grid 作为 parent ,原有 grid 与新增 grid 作为子元素
45
+ private generateSplitParent(direction: SplitDirection, editorGroup: IGridEditorGroup, before?: boolean) {
46
+ this.splitDirection = direction;
47
+ const originalChild = new EditorGrid(this);
48
+ originalChild.setEditorGroup(this.editorGroup!);
49
+ this.editorGroup = null;
50
+ const newGrid = new EditorGrid(this);
51
+ newGrid.setEditorGroup(editorGroup);
52
+ if (before) {
53
+ this.children = [newGrid, originalChild];
54
+ } else {
55
+ this.children = [originalChild, newGrid];
56
+ }
57
+ this._onDidGridStateChange.fire();
58
+ }
59
+ // 新增 grid 与当前 grid 作为同一父 grid 的子元素
60
+ private generateSplitSibling(editorGroup: IGridEditorGroup, before?: boolean) {
61
+ if (this.parent) {
62
+ const index = this.parent.children.indexOf(this);
63
+ const newGrid = new EditorGrid(this.parent);
64
+ newGrid.setEditorGroup(editorGroup);
65
+
66
+ if (before) {
67
+ this.parent.children.splice(index, 0, newGrid);
68
+ } else {
69
+ this.parent.children.splice(index + 1, 0, newGrid);
70
+ }
71
+ this.parent._onDidGridStateChange.fire();
72
+ }
73
+ }
74
+ public split(direction: SplitDirection, editorGroup: IGridEditorGroup, before?: boolean) {
75
+ // 由于split永远只会从未分割的含有editorGroup的grid发出
76
+ // 父元素不含有实际渲染 ui
77
+ if (!this.splitDirection) {
78
+ // 顶层 grid 且未有指定方向,生成初始父级单元
79
+ if (!this.parent) {
80
+ this.generateSplitParent(direction, editorGroup, before);
81
+ // 非顶层 grid
82
+ } else {
83
+ // 与父元素方向一致,则为同级子元素
84
+ if (this.parent.splitDirection === direction) {
85
+ this.generateSplitSibling(editorGroup, before);
86
+ // 与父元素方向不一致,则生成为父级单元
87
+ } else if (this.parent.splitDirection !== direction) {
88
+ this.generateSplitParent(direction, editorGroup, before);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ public dispose() {
95
+ if (this.editorGroup) {
96
+ this.editorGroup = null;
97
+ if (!this.parent) {
98
+ return; // geng
99
+ }
100
+ const index = this.parent.children.indexOf(this);
101
+ this.parent.children.splice(index, 1);
102
+ if (this.parent.children.length === 1) {
103
+ this.parent.replaceBy(this.parent.children[0]);
104
+ }
105
+ this.parent._onDidGridStateChange.fire();
106
+ } else {
107
+ // 应该不会落入这里
108
+ }
109
+ }
110
+
111
+ public replaceBy(target: EditorGrid) {
112
+ if (target.editorGroup) {
113
+ this.setEditorGroup(target.editorGroup);
114
+ }
115
+ this.splitDirection = target.splitDirection;
116
+ this.children.splice(0, this.children.length, ...target.children.splice(0, target.children.length));
117
+ this.children.forEach((grid) => {
118
+ grid.parent = this;
119
+ });
120
+ if (this.parent) {
121
+ this.parent._onDidGridStateChange.fire();
122
+ }
123
+ }
124
+
125
+ public emitResizeWithEventBus(eventBus: IEventBus) {
126
+ eventBus.fire(new GridResizeEvent({ gridId: this.uid }));
127
+ this.children.forEach((c) => {
128
+ c.emitResizeWithEventBus(eventBus);
129
+ });
130
+ }
131
+
132
+ serialize(): IEditorGridState | null {
133
+ if (this.editorGroup) {
134
+ const editorGroupState = this.editorGroup.getState();
135
+ if (this.parent && editorGroupState.uris.length === 0) {
136
+ return null;
137
+ }
138
+ return {
139
+ editorGroup: editorGroupState,
140
+ };
141
+ } else {
142
+ if (this.parent && this.children.length === 0) {
143
+ return null;
144
+ }
145
+ const children = this.children.map((c) => c.serialize()).filter((c) => !!c) as IEditorGridState[];
146
+ if (children.length === 1) {
147
+ // 只有一个孩子,直接覆盖
148
+ return children[0];
149
+ }
150
+ return {
151
+ splitDirection: this.splitDirection,
152
+ children,
153
+ };
154
+ }
155
+ }
156
+
157
+ async deserialize(
158
+ state: IEditorGridState,
159
+ editorGroupFactory: () => IGridEditorGroup,
160
+ editorGroupRestoreStatePromises: Promise<any>[],
161
+ ): Promise<any> {
162
+ const promises: Promise<any>[] = [];
163
+ if (state.editorGroup) {
164
+ this.setEditorGroup(editorGroupFactory());
165
+ editorGroupRestoreStatePromises.push(this.editorGroup!.restoreState(state.editorGroup));
166
+ } else {
167
+ this.splitDirection = state.splitDirection;
168
+ this.children = (state.children || []).map((c) => {
169
+ const grid = new EditorGrid(this);
170
+ promises.push(grid.deserialize(c, editorGroupFactory, editorGroupRestoreStatePromises));
171
+ return grid;
172
+ });
173
+ }
174
+ return Promise.all(promises);
175
+ }
176
+
177
+ findGird(direction: Direction, currentIndex = 0): MaybeNull<EditorGrid> {
178
+ if (this.splitDirection && splitDirectionMatches(this.splitDirection, direction)) {
179
+ const targetIndex = currentIndex + (direction === Direction.LEFT || direction === Direction.UP ? -1 : 1);
180
+ if (this.children[targetIndex]) {
181
+ return this.children[targetIndex].getFirstLeaf();
182
+ }
183
+ }
184
+
185
+ if (!this.parent) {
186
+ return null;
187
+ } else {
188
+ return this.parent.findGird(direction, this.parent.children.indexOf(this));
189
+ }
190
+ }
191
+
192
+ getFirstLeaf(): MaybeNull<EditorGrid> {
193
+ if (this.editorGroup) {
194
+ return this;
195
+ } else {
196
+ if (this.children.length > 0) {
197
+ return this.children[0].getFirstLeaf();
198
+ } else {
199
+ return null;
200
+ }
201
+ }
202
+ }
203
+
204
+ sortEditorGroups(results: IEditorGroup[]) {
205
+ if (this.editorGroup) {
206
+ results.push(this.editorGroup);
207
+ } else {
208
+ if (this.children.length > 0) {
209
+ this.children.forEach((children) => {
210
+ children.sortEditorGroups(results);
211
+ });
212
+ }
213
+ }
214
+ }
215
+
216
+ move(direction: Direction) {
217
+ if (this.parent) {
218
+ if (this.parent.splitDirection === SplitDirection.Horizontal) {
219
+ if (direction === Direction.LEFT) {
220
+ const index = this.parent.children.indexOf(this);
221
+ if (index > 0) {
222
+ this.parent!.children.splice(index, 1);
223
+ this.parent!.children.splice(index - 1, 0, this);
224
+ this.parent._onDidGridStateChange.fire();
225
+ }
226
+ } else if (direction === Direction.RIGHT) {
227
+ const index = this.parent.children.indexOf(this);
228
+ if (index < this.parent.children.length) {
229
+ this.parent!.children.splice(index, 1);
230
+ this.parent!.children.splice(index + 1, 0, this);
231
+ this.parent._onDidGridStateChange.fire();
232
+ }
233
+ }
234
+ } else if (this.parent.splitDirection === SplitDirection.Vertical) {
235
+ if (direction === Direction.UP) {
236
+ const index = this.parent.children.indexOf(this);
237
+ if (index > 0) {
238
+ this.parent!.children.splice(index, 1);
239
+ this.parent!.children.splice(index - 1, 0, this);
240
+ this.parent._onDidGridStateChange.fire();
241
+ }
242
+ } else if (direction === Direction.DOWN) {
243
+ const index = this.parent.children.indexOf(this);
244
+ if (index < this.parent.children.length) {
245
+ this.parent!.children.splice(index, 1);
246
+ this.parent!.children.splice(index + 1, 0, this);
247
+ this.parent._onDidGridStateChange.fire();
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ export interface IEditorGridState {
256
+ editorGroup?: IEditorGroupState;
257
+ splitDirection?: SplitDirection;
258
+ children?: IEditorGridState[];
259
+ }
260
+
261
+ export interface IGridChild {
262
+ grid: EditorGrid;
263
+ percentage: number; // 0-100
264
+ }
265
+
266
+ export enum SplitDirection {
267
+ // 水平拆分
268
+ Horizontal = 1,
269
+
270
+ // 垂直拆分
271
+ Vertical = 2,
272
+ }
273
+
274
+ export interface IGridEditorGroup extends IEditorGroup {
275
+ grid: EditorGrid;
276
+ }
277
+
278
+ export function splitDirectionMatches(split: SplitDirection, direction: Direction): boolean {
279
+ if (direction === Direction.UP || direction === Direction.DOWN) {
280
+ return split === SplitDirection.Vertical;
281
+ }
282
+
283
+ if (direction === Direction.LEFT || direction === Direction.RIGHT) {
284
+ return split === SplitDirection.Horizontal;
285
+ }
286
+
287
+ return false;
288
+ }