Conversation
9f9e354 to
d916e08
Compare
## Walkthrough
本次更改为编辑器系统引入了多文件对比(multi-diff)编辑器功能。主要内容包括新增多文件对比相关的抽象接口、服务、贡献点、资源解析器、编辑器实现和 UI 组件。AI Native 聊天模块集成了多文件对比能力,支持通过会话代码块动态生成多文件对比资源。Monaco 编辑器和前端样式也同步扩展以支持多文件对比编辑器的渲染和交互。此外,命令系统、状态栏和本地化文件也做了相应适配,允许通过命令或 UI 操作打开多文件对比视图。
## Changes
| 文件/路径分组 | 变更摘要 |
|---|---|
| `packages/editor/src/common/multi-diff.ts` | 新增多文件对比相关接口与类型定义,包括资源解析、编辑器模型和编辑器项等。 |
| `packages/editor/src/common/editor.ts` | `EditorCollectionService` 增加 `createMultiDiffEditor` 抽象方法,`EditorOpenType` 增加 `multiDiff` 类型。 |
| `packages/editor/src/browser/editor-collection.service.ts` | 实现 `createMultiDiffEditor` 方法,支持创建多文件对比编辑器实例。 |
| `packages/editor/src/browser/multi-diff/`(多个文件) | 新增多文件对比编辑器实现(`BrowserMultiDiffEditor`)、资源提供器、解析器、服务和贡献点,支持多文件对比的注册、资源解析与渲染。 |
| `packages/editor/src/browser/editor.contribution.ts` | 注册 `_workbench.openMultiDiffEditor` 命令,支持通过命令打开多文件对比编辑器。 |
| `packages/editor/src/browser/editor.view.tsx` | 编辑器容器支持渲染多文件对比编辑器,并处理其 DOM 挂载与布局。 |
| `packages/editor/src/browser/index.ts` | 编辑器模块注册多文件对比相关服务、贡献点,并在初始化时完成注册。 |
| `packages/editor/src/browser/types.ts` | 新增 `MultiDiffSourceContribution` 贡献点接口及符号。 |
| `packages/editor/src/browser/workbench-editor.service.ts` | `EditorGroup` 支持多文件对比编辑器的生命周期、布局、打开与挂载。 |
| `packages/ai-native/src/browser/chat/`(多个文件) | 聊天模块新增多文件对比资源与解析器,实现基于会话代码块的多文件对比能力。 |
| `packages/ai-native/src/browser/ai-core.contribution.ts` | 聊天贡献点实现多文件对比源注册和内容提供能力。 |
| `packages/ai-native/src/browser/components/ChangeList.tsx` | 增加“查看改动”按钮,支持一键打开多文件对比视图。 |
| `packages/ai-native/src/browser/components/change-list.module.less` | 样式调整,新增 `viewChanges` 类,优化按钮与图标的交互和布局。 |
| `packages/ai-native/src/browser/mcp/base-apply.service.ts` | 新增 `CHAT_EDITING_SOURCE_RESOLVER_SCHEME` 常量。 |
| `packages/core-browser/src/common/common.command.ts` | 新增多文件对比编辑器命令常量。 |
| `packages/core-browser/src/monaco/index.ts` | `MonacoService` 增加 `createMultiDiffEditorWidget` 抽象方法。 |
| `packages/core-browser/src/services/label-service.ts` | `getIconClass` 重命名为 `getResourceIconClass` 并导出。 |
| `packages/i18n/src/common/en-US.lang.ts`<br>`packages/i18n/src/common/zh-CN.lang.ts` | 新增“查看改动”相关本地化字符串。 |
| `packages/monaco/src/browser/monaco.service.ts` | 实现 `createMultiDiffEditorWidget`,支持创建多文件对比编辑器控件。 |
| `packages/monaco/src/browser/monaco-api/editor.ts` | 对外暴露 `createMultiFileDiffEditor`。 |
| `packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.ts`<br>`resource-label.module.less` | 新增资源标签组件及样式,用于多文件对比资源展示。 |
| `packages/monaco/src/common/observable.ts` | 新增若干 observable 工具类,支持 lazy 计算与 promise 状态跟踪。 |
| `packages/editor/src/browser/editor.module.less` | 多文件对比编辑器样式适配。 |
| `packages/startup/entry/sample-modules/status-bar.contribution.ts` | 状态栏贡献点注册测试命令,可打开多文件对比编辑器。 |
| `packages/ai-native/src/browser/ai-core.contribution.ts` | `AINativeBrowserContribution` 实现 `MultiDiffSourceContribution`,注册多文件对比源解析器和编辑器内容提供者。 |
| `packages/ai-native/src/browser/chat/chat-edit-resource.ts` | 新增 `ChatEditSchemeDocumentProvider`,基于 URI 动态提供聊天编辑会话代码内容。 |
| `packages/ai-native/src/browser/chat/chat-multi-diff-source.ts` | 新增 `ChatMultiDiffResolver` 和 `ChatMultiDiffSource`,实现基于聊天会话的多文件对比资源解析。 |
| `packages/ai-native/src/browser/components/ChangeList.tsx` | 增加“查看改动”按钮,点击打开多文件对比视图。 |
| `packages/editor/src/browser/multi-diff/multi-diff-editor.ts` | 新增 `BrowserMultiDiffEditor`,实现多文件对比编辑器核心逻辑与界面交互。 |
| `packages/editor/src/browser/multi-diff/multi-diff-resolver.ts` | 新增 `MultiDiffResolver`,管理多文件对比资源的注册与解析。 |
| `packages/editor/src/browser/multi-diff/multi-diff-resource.ts` | 新增 `MultiDiffResourceProvider`,提供多文件对比资源的解析和图标支持。 |
| `packages/editor/src/browser/multi-diff/multi-diff.contribution.ts` | 新增 `MultiDiffEditorContribution`,注册多文件对比源解析器、资源提供器和编辑器组件。 |
| `packages/editor/src/browser/multi-diff/resolver.service.ts` | 新增 `MultiDiffSourceResolverService`,管理多文件对比源解析器的注册和调用。 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant 用户
participant UI组件
participant WorkbenchEditorService
participant MultiDiffSourceResolverService
participant MultiDiffResolver/ChatMultiDiffResolver
participant BrowserMultiDiffEditor
participant MonacoService
用户->>UI组件: 点击“查看改动”按钮
UI组件->>WorkbenchEditorService: 调用 open(),openType=multiDiff
WorkbenchEditorService->>MultiDiffSourceResolverService: resolve(multiDiffSourceUri)
MultiDiffSourceResolverService->>MultiDiffResolver/ChatMultiDiffResolver: resolveDiffSource(uri)
MultiDiffResolver/ChatMultiDiffResolver-->>MultiDiffSourceResolverService: 返回 diff 资源列表
MultiDiffSourceResolverService-->>WorkbenchEditorService: 返回资源
WorkbenchEditorService->>BrowserMultiDiffEditor: compareMultiple(resource, options)
BrowserMultiDiffEditor->>MonacoService: createMultiDiffEditorWidget()
BrowserMultiDiffEditor->>BrowserMultiDiffEditor: 渲染多文件对比视图
BrowserMultiDiffEditor-->>用户: 展示多文件对比编辑器Suggested reviewers
|
There was a problem hiding this comment.
Actionable comments posted: 8
🔭 Outside diff range comments (2)
packages/monaco/src/common/observable.ts (2)
58-64:⚠️ Potential issuedispose 时未清理定时器,存在潜在内存泄漏
debouncedObservable2的dispose仅释放 autorun,但若已经设置了timeout,仍会在组件销毁后继续执行回调。建议在销毁时一并clearTimeout。dispose() { d.dispose(); + if (timeout) { + clearTimeout(timeout); + timeout = undefined; + } hasValue = false; lastValue = undefined; }
1-2: 🛠️ Refactor suggestion全文件使用
// @ts-nocheck关闭类型检查,建议逐步移除当前文件直接禁用了 TS 类型检查,长期会掩盖大量潜在问题。建议分阶段恢复类型检查:
- 先启用
// @ts-check查看报错概况;- 借助
ts-expect-error精准忽略无法立刻解决的位置;- 最终完全移除。
🧹 Nitpick comments (17)
packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.module.less (1)
1-5: flex-gap 在旧版浏览器可能失效,可按需兜底
gap在旧版 Safari(≤14.1)及部分 Electron 老版本的嵌套 WebView 中并不支持。若对这些环境有兼容需求,可考虑添加margin-right/margin-bottom方案或升级运行时。packages/editor/src/browser/editor.module.less (1)
10-14: 样式 OK,可考虑补充 overflow 防止溢出
.kt_editor_multi_diff_editor填充父容器且position: relative设置正确;如后续需要在内部叠加浮层组件,建议同时设置overflow: hidden以避免内容溢出。packages/monaco/src/browser/monaco-api/editor.ts (1)
73-73: 将多文件 Diff 编辑器暴露至 API
向createMonacoEditorApi添加createMultiFileDiffEditor方法,已满足多文件对比编辑器功能需求。请同时更新文档和示例,指导外部消费者如何使用该新 API。packages/ai-native/src/browser/components/ChangeList.tsx (1)
54-72: 查看变更功能实现
renderViewChanges函数实现了查看多文件差异的功能,设计合理:
- 当没有文件时正确处理了边缘情况
- 使用编辑器服务打开多文件差异视图
- 阻止事件冒泡以避免触发父元素的点击事件
- 使用本地化字符串支持国际化
建议考虑将URI常量提取为模块级常量或配置项,以增强可维护性。
+const CHAT_EDITING_MULTI_DIFF_URI = URI.parse('chat-editing-multi-diff-source://chat-editing-multi-diff-source/'); const renderViewChanges = (totalFiles: number) => { if (!totalFiles) { return null; } return ( <span className={styles.viewChanges} onClick={(e) => { e.stopPropagation(); - editorService.open(URI.parse('chat-editing-multi-diff-source://chat-editing-multi-diff-source/'), { + editorService.open(CHAT_EDITING_MULTI_DIFF_URI, { label: localize('aiNative.chat.view-changes'), }); }} >packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.ts (2)
6-23: ResourceLabel类实现高内聚
ResourceLabel类设计简洁明了:
- 构造函数接收一个HTML元素作为容器
setUri方法处理URI规范化并委托给renderFilerenderFile方法生成包含图标和显示名称的HTMLclear方法提供了清理功能建议添加类级别的JSDoc注释以提高代码的可维护性,并明确类的用途和职责。
+/** + * 管理资源标签渲染的类 + * 负责在指定的HTML元素中渲染包含图标和名称的资源标签 + */ export class ResourceLabel { constructor(private readonly element: HTMLElement) {} + /** + * 设置要显示的URI和选项 + * @param uri 要显示的资源URI + * @param options 标签选项,如是否添加删除线 + */ setUri(uri: Uri, options?: IResourceLabelOptions) { this.renderFile(URI.from(uri), options); }
13-18: renderFile方法实现简洁有效
renderFile方法的实现简洁高效:
- 获取资源图标类
- 根据选项条件性地应用删除线样式
- 直接使用innerHTML设置内容
一个潜在的安全考虑是使用
innerHTML可能引起XSS风险,特别是当处理用户输入或不受信任的URI时。考虑使用更安全的DOM操作方法。private renderFile(uri: URI, options?: IResourceLabelOptions) { const icon = getResourceIconClass(uri); - this.element.innerHTML = `<span class="${styles.resourceLabel}${ - options?.strikethrough ? ' strikethrough' : '' - }"><span class="${icon.iconClass}"></span>${uri.displayName}</span>`; + this.element.innerHTML = ''; + + const labelElement = document.createElement('span'); + labelElement.className = `${styles.resourceLabel}${options?.strikethrough ? ' strikethrough' : ''}`; + + const iconElement = document.createElement('span'); + iconElement.className = icon.iconClass; + + labelElement.appendChild(iconElement); + labelElement.appendChild(document.createTextNode(uri.displayName)); + + this.element.appendChild(labelElement); }packages/startup/entry/sample-modules/status-bar.contribution.ts (2)
22-27: 添加测试变量和命令常量添加了用于测试的计数变量和命令常量,但变量名和命令名称过于简单,建议使用更具描述性的名称。
建议修改变量和命令名称为更具描述性的形式:
-let executeCount = 0; -const TEST_MULTI_DIFF_COMMAND = 'testMultiDiffCommand'; +let multiDiffTestExecuteCount = 0; +const TEST_MULTI_DIFF_EDITOR_COMMAND = 'testMultiDiffEditorCommand';
76-83: 条件添加文件对比项使用了简单的计数变量来切换不同的文件对比组合,这个实现比较简单,但在更复杂的场景中可能不够灵活。
考虑使用更灵活的方式来管理多文件对比的测试用例,例如:
- executeCount++ === 0 + multiDiffTestExecuteCount++ % 3 === 0 ? [] - : [ + : multiDiffTestExecuteCount % 3 === 1 ? [ { originalUri: Uri.file('./packages/startup/webpack.lite.config.js'), modifiedUri: Uri.file('./packages/startup/webpack.preview.config.js'), }, - ], + ] : [ + { + originalUri: Uri.file('./packages/startup/webpack.lite.config.js'), + modifiedUri: Uri.file('./packages/startup/webpack.preview.config.js'), + }, + { + originalUri: Uri.file('./tsconfig.json'), + modifiedUri: Uri.file('./tsconfig.web.json'), + }, + ],这样可以测试更多的多文件对比组合情况。
packages/ai-native/src/browser/chat/chat-edit-resource.ts (2)
39-46: 实现文档内容提供逻辑根据URI查询参数提取代码内容,使用了合理的空值处理。但代码块查找使用了数组搜索,在大量代码块的情况下可能效率不高。
对于大量代码块的情况,考虑使用Map结构来提高查找效率:
@Injectable() export class ChatEditSchemeDocumentProvider implements IEditorDocumentModelContentProvider { // 现有代码... + private codeBlocksMap: Map<string, any> = new Map(); + + private updateCodeBlocksMap() { + this.codeBlocksMap.clear(); + const codeBlocks = this.baseApplyService.getSessionCodeBlocks(); + for (const block of codeBlocks) { + if (block.toolCallId) { + this.codeBlocksMap.set(block.toolCallId, block); + } + } + } async provideEditorDocumentModelContent(uri: URI, encoding?: string | undefined): Promise<string> { // Get the content from the base apply service based on the uri query parameters const { id, side } = uri.getParsedQuery(); - const codeBlocks = this.baseApplyService.getSessionCodeBlocks(); - const codeBlock = codeBlocks.find((block) => block.toolCallId === id); + this.updateCodeBlocksMap(); + const codeBlock = this.codeBlocksMap.get(id); const content = side === 'left' ? codeBlock?.originalCode : codeBlock?.updatedCode; return content || ''; } }
52-52: 处理模型释放事件提供了空的模型释放处理方法,但应该考虑在资源释放时进行适当的清理。
模型释放时应考虑进行资源清理:
- onDidDisposeModel() {} + onDidDisposeModel(uri: URI) { + // 清理与该URI相关的资源或缓存 + }packages/editor/src/browser/multi-diff/multi-diff-resource.ts (1)
55-58: 资源关闭决策方法
shouldCloseResource方法目前总是返回true,允许关闭资源。注释指出这是临时实现,未来可能会增强。建议未来实现时考虑检查是否有未保存的更改。
packages/editor/src/browser/workbench-editor.service.ts (2)
831-854: 重复且命名不一致的 DOM 节点字段易混淆文件中同时存在
_multiFileDiffEditorDomNode与_multiDiffEditorDomNode两套字段,但只有后一套被真正使用。冗余成员不仅增加心智负担,还可能在后续维护中导致引用错误。
建议统一为一套命名(如_multiDiffEditorDomNode),并删除未使用的_multiFileDiffEditorDomNode*相关代码。
2475-2482: 缺少与其他编辑器一致的 Ready 事件,可能影响外部监听
createMultiDiffEditor里未触发类似multiDiffEditorReady的就绪信号,而codeEditor,diffEditor,mergeEditor均有对应ReadyEvent。为保持一致,建议补充:this.multiDiffEditor = editor; this.multiDiffEditorReady?.ready(); // 需提前声明或在现有生命周期中提供统一回调。
packages/editor/src/browser/multi-diff/multi-diff-editor.ts (1)
57-64: 事件发射器未在dispose中清理
multiDiffModelChangeEmitter创建后只在类销毁时通过super.dispose()释放multiDiffWidget,但未显式dispose该Emitter。为避免潜在的事件泄漏,建议在dispose()中补充:this.multiDiffWidget.dispose(); + this.multiDiffModelChangeEmitter.dispose();packages/editor/src/common/multi-diff.ts (3)
17-34: 建议为接口添加JSDoc文档注释接口
IMultiDiffSourceResolverService、IMultiDiffSourceResolver和IResolvedMultiDiffSource缺少JSDoc注释。为这些关键接口添加文档注释将有助于开发者理解它们的用途、职责和使用方法。添加文档注释示例:
+/** + * 多文件差异源解析器服务接口 + * 负责管理和解析多文件差异源 + */ export interface IMultiDiffSourceResolverService { registerResolver(resolver: IMultiDiffSourceResolver): IDisposable; resolve(uri: URI): Promise<IResolvedMultiDiffSource | undefined>; getResolvers(): IMultiDiffSourceResolver[]; } +/** + * 多文件差异源解析器接口 + * 负责处理特定类型的URI并解析对应的差异源 + */ export interface IMultiDiffSourceResolver { canHandleUri(uri: URI): boolean; resolveDiffSource(uri: URI): Promise<IResolvedMultiDiffSource | undefined>; } +/** + * 已解析的多文件差异源接口 + * 包含差异资源列表和可选的上下文键值对 + */ export interface IResolvedMultiDiffSource { readonly resources: IValueWithChangeEvent<readonly MultiDiffEditorItem[]>; readonly contextKeys?: Record<string, ContextKeyValue>; }
36-51: 建议优化键生成方法并添加类文档
MultiDiffEditorItem类缺少JSDoc文档注释,建议添加以说明其用途和重要性。getKey()方法直接使用 JSON.stringify 可能在URI包含特殊字符或非常长时导致问题。建议改进如下:
+/** + * 多文件差异编辑器项 + * 表示差异编辑中的一对文件(原始文件和修改后文件) + */ export class MultiDiffEditorItem { constructor( readonly originalUri: URI | undefined, readonly modifiedUri: URI | undefined, readonly goToFileUri: URI | undefined, readonly contextKeys?: Record<string, ContextKeyValue>, ) { if (!originalUri && !modifiedUri) { throw new Error('Invalid arguments'); } } getKey(): string { - return JSON.stringify([this.modifiedUri?.toString(), this.originalUri?.toString()]); + // 使用更可靠的方式生成唯一键 + const original = this.originalUri?.toString() || 'undefined'; + const modified = this.modifiedUri?.toString() || 'undefined'; + return `${modified}:${original}`; } }
61-61: 建议为方法参数添加详细文档注释
compareMultiple方法参数缺少详细说明,这对于使用该API的开发者理解参数要求很重要。建议添加参数说明:
/** * Compare multiple file pairs + * @param resource 包含多文件差异信息的资源 + * @param options 可选的资源打开选项 */ compareMultiple(resource: IResource, options?: IResourceOpenOptions): Promise<void>;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (31)
packages/ai-native/src/browser/ai-core.contribution.ts(6 hunks)packages/ai-native/src/browser/chat/chat-edit-resource.ts(1 hunks)packages/ai-native/src/browser/chat/chat-multi-diff-source.ts(1 hunks)packages/ai-native/src/browser/components/ChangeList.tsx(4 hunks)packages/ai-native/src/browser/components/change-list.module.less(2 hunks)packages/ai-native/src/browser/mcp/base-apply.service.ts(1 hunks)packages/core-browser/src/common/common.command.ts(1 hunks)packages/core-browser/src/monaco/index.ts(2 hunks)packages/core-browser/src/services/label-service.ts(2 hunks)packages/editor/src/browser/editor-collection.service.ts(3 hunks)packages/editor/src/browser/editor.contribution.ts(5 hunks)packages/editor/src/browser/editor.module.less(1 hunks)packages/editor/src/browser/editor.view.tsx(3 hunks)packages/editor/src/browser/index.ts(7 hunks)packages/editor/src/browser/multi-diff/multi-diff-editor.ts(1 hunks)packages/editor/src/browser/multi-diff/multi-diff-resolver.ts(1 hunks)packages/editor/src/browser/multi-diff/multi-diff-resource.ts(1 hunks)packages/editor/src/browser/multi-diff/multi-diff.contribution.ts(1 hunks)packages/editor/src/browser/multi-diff/resolver.service.ts(1 hunks)packages/editor/src/browser/types.ts(2 hunks)packages/editor/src/browser/workbench-editor.service.ts(10 hunks)packages/editor/src/common/editor.ts(3 hunks)packages/editor/src/common/multi-diff.ts(1 hunks)packages/i18n/src/common/en-US.lang.ts(1 hunks)packages/i18n/src/common/zh-CN.lang.ts(1 hunks)packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.module.less(1 hunks)packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.ts(1 hunks)packages/monaco/src/browser/monaco-api/editor.ts(2 hunks)packages/monaco/src/browser/monaco.service.ts(3 hunks)packages/monaco/src/common/observable.ts(2 hunks)packages/startup/entry/sample-modules/status-bar.contribution.ts(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/startup/entry/sample-modules/status-bar.contribution.ts (4)
packages/editor/src/browser/multi-diff/multi-diff-resolver.ts (1)
Injectable(12-44)packages/editor/src/browser/multi-diff/multi-diff.contribution.ts (1)
Domain(16-54)packages/editor/src/browser/editor.contribution.ts (2)
Domain(96-1415)Domain(1417-1546)packages/editor/src/common/multi-diff.ts (1)
MULTI_DIFF_SCHEME(13-13)
packages/editor/src/browser/multi-diff/multi-diff-resolver.ts (1)
packages/editor/src/common/multi-diff.ts (4)
IMultiDiffSourceResolver(25-29)MultiDiffEditorItem(36-51)MULTI_DIFF_SCHEME(13-13)IResolvedMultiDiffSource(31-34)
packages/editor/src/browser/types.ts (1)
packages/editor/src/common/multi-diff.ts (2)
IMultiDiffSourceResolverService(15-15)IMultiDiffSourceResolverService(17-23)
packages/monaco/src/browser/monaco.service.ts (1)
packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.ts (1)
ResourceLabel(6-23)
packages/editor/src/browser/index.ts (2)
packages/editor/src/common/multi-diff.ts (2)
IMultiDiffSourceResolverService(15-15)IMultiDiffSourceResolverService(17-23)packages/editor/src/browser/types.ts (4)
BrowserEditorContribution(154-154)BrowserEditorContribution(156-190)MultiDiffSourceContribution(192-192)MultiDiffSourceContribution(194-196)
packages/ai-native/src/browser/chat/chat-multi-diff-source.ts (2)
packages/ai-native/src/browser/chat/chat-edit-resource.ts (1)
Injectable(11-53)packages/editor/src/common/multi-diff.ts (3)
IMultiDiffSourceResolver(25-29)IResolvedMultiDiffSource(31-34)MultiDiffEditorItem(36-51)
packages/ai-native/src/browser/ai-core.contribution.ts (2)
packages/core-browser/src/monaco/index.ts (2)
MonacoContribution(79-79)MonacoContribution(92-106)packages/monaco/src/common/types.ts (1)
IDisposable(27-29)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: unittest (ubuntu-latest, 18.x, node)
- GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
- GitHub Check: unittest (macos-latest, 18.x, node)
- GitHub Check: unittest (macos-latest, 18.x, jsdom)
- GitHub Check: build (macos-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: build-windows
- GitHub Check: ubuntu-latest, Node.js 20.x
🔇 Additional comments (61)
packages/ai-native/src/browser/mcp/base-apply.service.ts (1)
38-38: 新增 URI scheme 常量命名验证
静态常量CHAT_EDITING_SOURCE_RESOLVER_SCHEME的命名清晰,且值'chat-editing-source'与对应的ChatEditSchemeDocumentProvider保持一致。请确认在ai-core.contribution.ts中已正确注册该 scheme。packages/monaco/src/browser/monaco-api/editor.ts (1)
42-42:Details
❓ Verification inconclusive
确认
createMultiFileDiffEditor导入有效
请验证@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneEditor模块中已经导出createMultiFileDiffEditor,以避免运行时undefined错误。
🏁 Script executed:
#!/bin/bash # 验证 createMultiFileDiffEditor 是否在项目中定义并导出 rg "createMultiFileDiffEditor" -n .Length of output: 203
🏁 Script executed:
#!/bin/bash # 获取 @opensumi/monaco-editor-core 版本号 version=$(grep '"@opensumi/monaco-editor-core"' -n package.json | head -1 | sed -E 's/.*"@opensumi\/monaco-editor-core": *"([^"]+)".*/\1/') echo "Detected @opensumi/monaco-editor-core version: $version" # 拉取 standaloneEditor 模块并查找 createMultiFileDiffEditor 导出 curl -s "https://unpkg.com/@opensumi/monaco-editor-core@$version/esm/vs/editor/standalone/browser/standaloneEditor.js" \ | grep -nE "export .*createMultiFileDiffEditor"Length of output: 408
确认
createMultiFileDiffEditor导入有效
请手动检查@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneEditor.js中是否已导出createMultiFileDiffEditor,以避免运行时出现undefined错误。packages/i18n/src/common/zh-CN.lang.ts (1)
1250-1250: 中文本地化条目添加完毕
确认'aiNative.chat.view-changes': '查看改动'已添加且与英文对应项同步,并已更新 i18n 系统来加载此新键值。packages/i18n/src/common/en-US.lang.ts (1)
1481-1481: 英文本地化条目添加完毕
确认'aiNative.chat.view-changes': 'View Changes'已正确添加,并与中文翻译保持一致。packages/core-browser/src/common/common.command.ts (1)
305-306: 新增多文件差异编辑器命令常量常量命名符合项目规范,与其他编辑器命令如
API_OPEN_EDITOR_COMMAND_ID和API_OPEN_DIFF_EDITOR_COMMAND_ID保持一致的命名风格,这有助于代码的一致性和可维护性。packages/core-browser/src/services/label-service.ts (2)
128-128: 函数调用更新为使用重命名后的函数将内部使用的
getIconClass更新为了新重命名的getResourceIconClass函数。此修改使代码逻辑保持一致,同时也使得引用明确清晰。
264-329: 函数重命名并导出为公共API将
getIconClass重命名为getResourceIconClass并将其导出,使外部模块可以利用资源URI的图标类检索逻辑。这种改变遵循了良好的代码重用实践,使功能组件化并提高了可重用性。这一修改与PR中引入的多文件差异编辑器功能相匹配,新的多文件差异资源可能需要适当的图标解析支持。
🧰 Tools
🪛 Biome (1.9.4)
[error] 274-274: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 289-290: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/core-browser/src/monaco/index.ts (2)
3-3: 导入MultiDiffEditorWidget类型从Monaco编辑器核心包导入了
MultiDiffEditorWidget类型,为新增的多文件差异编辑器功能提供类型支持,这是符合TypeScript最佳实践的做法。
53-57: 新增创建多文件差异编辑器widget的抽象方法新增了
createMultiDiffEditorWidget抽象方法,该方法与类中已有的createCodeEditor和createDiffEditor等方法保持了一致的风格和参数模式。这种一致性有助于开发者理解和使用API。该方法将由具体的
MonacoService实现类提供实现,为多文件差异编辑器功能提供基础设施。packages/editor/src/browser/types.ts (2)
30-30: 导入多文件差异源解析器服务接口从
../common/multi-diff模块导入了IMultiDiffSourceResolverService接口,为新增的多文件差异功能提供类型支持。
192-196: 定义多文件差异源贡献点新增了
MultiDiffSourceContribution符号和接口,遵循了项目中已有的贡献点模式(如BrowserEditorContribution)。这个接口允许组件注册多文件差异源解析器,从而扩展多文件差异编辑器的能力。接口设计简洁明了,只包含一个
registerMultiDiffSourceResolver方法,符合单一职责原则,有助于后续组件实现该接口。packages/ai-native/src/browser/components/change-list.module.less (4)
23-25: 样式过渡效果优化过渡效果的添加使悬停状态变化更加平滑,提升了用户体验。
38-41: 图标样式与交互优化添加间距并确保图标继承颜色是一个很好的改进,使元素更加一致和易于维护。
48-48: 布局对齐优化添加
align-items: center确保了标题内容的垂直居中对齐,提升了视觉一致性。
131-143: 新增的查看变更按钮样式实现得当新增的
.viewChanges类样式设计合理,与现有UI风格一致。悬停效果和过渡动画增强了交互体验,图标颜色继承确保了样式的一致性。packages/editor/src/browser/editor-collection.service.ts (2)
30-30: 确保导入顺序和分组一致导入的相关类型和实现已正确添加,与项目的导入规范一致。
Also applies to: 40-40, 42-42
157-163: 多文件差异编辑器创建方法实现完善新增的
createMultiDiffEditor方法设计合理,遵循了与其他编辑器创建方法一致的模式:
- 获取转换后的Monaco配置选项
- 创建底层编辑器组件
- 合并选项
- 使用依赖注入创建并返回编辑器实例
方法签名和实现与整体代码风格保持一致。
packages/ai-native/src/browser/components/ChangeList.tsx (3)
4-5: 依赖导入优化新增的导入正确地包含了所需的
WorkbenchEditorService和其他依赖,保持了导入的清晰和有序。
29-29: 编辑器服务注入使用
useInjectable注入WorkbenchEditorService的方式符合项目的依赖注入模式。
109-116: UI布局更新在标题部分添加查看变更按钮的集成方式合理,使用现有的样式结构保持了UI的一致性。按钮的布局顺序合理,从切换按钮到变更统计再到查看变更,符合用户操作的自然流程。
packages/monaco/src/browser/contrib/multi-diff-editor/resource-label.ts (2)
1-5: 导入依赖设计合理导入了必要的依赖,包括URI处理、资源图标类和样式模块,符合项目的模块组织结构。
20-22: 清理方法简单明了
clear方法实现简单,有效地清除了元素内容。packages/editor/src/common/editor.ts (3)
19-19: 引入新的多文件差异编辑器接口引入了新的
IMultiDiffEditor接口为多文件差异编辑器特性提供支持。
348-359: 扩展 EditorCollectionService 抽象类以支持多文件差异编辑器新增的抽象方法
createMultiDiffEditor使编辑器集合服务能够创建多文件差异编辑器实例。方法签名与其他编辑器创建方法保持一致,维持了良好的接口设计。
885-885: 添加新的编辑器打开类型在
EditorOpenType枚举中添加了multiDiff类型,使系统能够识别和支持新的多文件差异编辑器类型。packages/monaco/src/browser/monaco.service.ts (3)
9-9: 引入多文件差异编辑器所需的依赖正确导入了实现多文件差异编辑器所需的相关组件和服务。
Also applies to: 19-19, 23-26, 31-31
161-192: 实现多文件差异编辑器部件创建方法该方法实现了创建多文件差异编辑器部件的功能,但有两个注释掉的行(189-190行)可能表示实现不完整或有意禁用某些功能。
- // this.overrideMonacoKeybindingService(editor); - // this.addClickEventListener(editor); + this.overrideMonacoKeybindingService(editorWidget); + this.addClickEventListener(editorWidget);请确认是否有意注释这些行,以及是否需要在合并前取消注释并实现这些功能?如果有意注释,建议添加说明注释解释原因。
173-185: 资源标签创建实现
createResourceLabel回调函数的实现合理,能够正确处理 URI 为空的情况并提供清理方法。资源标签的创建和管理方式符合组件设计模式。packages/editor/src/browser/multi-diff/resolver.service.ts (1)
1-35: 多文件差异源解析器服务实现
MultiDiffSourceResolverService类实现了IMultiDiffSourceResolverService接口,提供了注册、解析和获取解析器的功能。实现逻辑清晰,使用Set存储解析器以避免重复,并正确实现了所有必要的方法。注意到在
registerResolver方法中有一个显式的重复检查(第16-18行),虽然Set本身就会自动防止重复元素。不过这种显式检查可能是为了提供更清晰的错误消息,有助于调试。packages/editor/src/browser/multi-diff/multi-diff-resolver.ts (1)
1-44: 多文件差异解析器实现
MultiDiffResolver类实现了IMultiDiffSourceResolver接口,能够管理和解析基于MULTI_DIFF_SCHEME方案的 URI 的多文件差异源。该实现支持注册新源或更新现有源,并正确处理解析和释放资源。实现使用
ValueWithChangeEvent包装MultiDiffEditorItem数组,这种设计能够在源发生变化时通知监听器,支持编辑器的反应式更新。packages/ai-native/src/browser/ai-core.contribution.ts (4)
53-54: 实现 MultiDiffSourceContribution 接口类定义和实现列表中已添加
MultiDiffSourceContribution接口,确保了多文件对比功能的正确集成。Also applies to: 73-77
102-104: 导入聊天编辑资源提供器已正确导入
ChatEditSchemeDocumentProvider类,用于支持聊天会话中的编辑资源。
282-286: 注入多文件对比相关的依赖已添加两个关键依赖的自动注入,这些依赖对于实现聊天会话中的多文件对比功能至关重要。
292-298: 实现 MultiDiffSourceContribution 接口方法这两个方法负责注册多文件对比源解析器和编辑器文档模型内容提供器,是实现多文件对比功能的核心部分。实现简洁明了,职责分明。
packages/editor/src/browser/editor.view.tsx (3)
319-319: 添加多文件对比编辑器的 React 引用为多文件对比编辑器容器添加了 React 引用,与现有的编辑器引用保持一致的命名风格。
371-384: 添加多文件对比编辑器 DOM 挂载逻辑实现了多文件对比编辑器的 DOM 元素挂载和大小观察功能,使用 ResizeObserver 确保编辑器在容器大小变化时能够正确布局。代码风格与其他编辑器类型的处理一致。
497-502: 添加多文件对比编辑器的 DOM 容器为多文件对比编辑器添加了条件渲染的 DOM 容器,样式类和条件判断与其他编辑器类型保持一致,使用了正确的 CSS 类和引用。
packages/startup/entry/sample-modules/status-bar.contribution.ts (3)
13-20: 添加命令相关的导入导入了实现命令功能所需的接口和服务,包括
CommandContribution,CommandRegistry,CommandService以及多文件对比所需的 URI 和方案常量。
27-33: 扩展贡献类以实现命令接口正确地扩展了
StatusBarContribution类以实现CommandContribution接口,并添加了CommandService依赖。
98-104: 添加状态栏测试按钮添加了一个状态栏按钮用于测试多文件对比功能,提示文本清晰地描述了功能。
packages/ai-native/src/browser/chat/chat-edit-resource.ts (4)
1-8: 导入必要的依赖正确导入了实现文档模型内容提供器所需的所有依赖,包括核心服务和编辑器相关接口。
11-33: 实现文档模型内容提供器类类定义和依赖注入清晰,创建了必要的事件发射器用于内容变更通知。依赖了多个服务以支持聊天会话中的编辑资源。
35-37: 实现方案处理逻辑方法判断当前URI方案是否由该提供器处理,使用了
BaseApplyService中定义的常量,确保了一致性。
48-50: 实现只读判断逻辑所有文档被标记为只读,符合查看差异的场景需求。
packages/editor/src/browser/multi-diff/multi-diff.contribution.ts (4)
16-17: 良好的类注解使用类注解
@Domain正确地将此类标记为同时实现BrowserEditorContribution和MultiDiffSourceContribution接口,使其能够被依赖注入系统正确识别和实例化。
27-30: 多Diff源解析器注册实现这个方法将内置的
multiDiffResolver注册到解析器服务中,使其可以通过命令使用。代码简洁明了,功能定义清晰。
32-34: 资源提供器注册实现该方法将
multiDiffResourceProvider注册到资源服务中,使多文件比对能够被识别为一种资源类型。实现简单有效。
36-53: 编辑器组件解析器实现这个方法实现了对多文件对比编辑器组件的支持。它通过检查是否有注册的解析器能够处理给定的URI方案来确定优先级,并在支持时添加multiDiff编辑器打开类型。
实现逻辑清晰,特别是优先级判断和结果推送的处理方式得当。
packages/editor/src/browser/editor.contribution.ts (2)
236-238: 依赖注入MultiDiffResolver正确地注入了MultiDiffResolver依赖,这是实现多文件对比编辑器命令的基础。
1240-1268: 多文件对比编辑器命令实现此命令实现了打开多文件对比编辑器的功能,支持指定标题、多文件对比源URI和资源列表。代码实现以下关键功能:
- 从配置中提取原始和修改后的URI
- 将URI组件转换为URI对象并创建MultiDiffEditorItem实例
- 将源注册到resolver中,支持相同URI的更新操作
- 打开带有指定标题的多文件对比编辑器
实现得当且考虑了URI的正确转换和更新场景。
packages/editor/src/browser/multi-diff/multi-diff-resource.ts (3)
9-25: 资源提供器类依赖注入类定义和依赖注入实现正确,继承了WithEventBus并实现了IResourceProvider接口。注入了所有必要的服务,包括标签服务、资源服务、文件服务客户端、应用配置和多文件对比源解析器服务。
26-34: URI处理优先级方法
handlesUri方法通过检查所有注册的解析器是否能处理给定URI来确定优先级。返回10表示支持,-1表示不支持,这种设计简单明了。
36-53: 资源提供实现
provideResource方法从URI查询参数中提取名称和源文件信息,并尝试从第一个修改文件URI获取图标。如果没有找到,则使用通用的diff图标。返回的资源对象包含名称、图标、URI、是否支持恢复以及包含源的元数据。实现合理且考虑了图标获取的回退策略。
packages/editor/src/browser/index.ts (6)
187-190: 多文件对比源解析器服务注册正确注册了
IMultiDiffSourceResolverService令牌并将其绑定到MultiDiffSourceResolverService实现类,这是实现多文件对比功能的基础服务。
193-193: 多文件对比编辑器贡献注册将
MultiDiffEditorContribution添加到模块提供者列表中,确保它在应用启动时被正确初始化。
207-207: 贡献提供者扩展通过添加
MultiDiffSourceContribution到贡献提供者列表,允许其他模块通过实现此接口来提供多文件对比源。
236-238: 多文件对比源解析器服务依赖注入在
EditorClientAppContribution中注入IMultiDiffSourceResolverService,使其可用于初始化过程。
242-244: 多文件对比源贡献依赖注入注入
MultiDiffSourceContribution提供者,使EditorClientAppContribution能够访问所有多文件对比源贡献实现。
263-265: 多文件对比源解析器初始化初始化过程中,遍历所有
MultiDiffSourceContribution实现并调用其registerMultiDiffSourceResolver方法,确保所有多文件对比源都被正确注册到解析器服务中。这种设计允许各种模块(如AI原生模块)提供自己的多文件对比源实现,增强了系统的扩展性。
packages/editor/src/common/multi-diff.ts (2)
1-12: 代码导入结构良好,满足功能需求导入的各个模块和类型清晰明确,符合功能需求。代码遵循了TypeScript的最佳实践,使用了显式类型声明。
53-87: 接口设计合理且文档完善
IMultiDiffEditor接口设计合理,方法职责清晰,并且有良好的JSDoc文档。接口扩展了IDisposable,确保了资源的正确释放。API设计符合编辑器功能的需求,包括比较、检索、布局和事件通知等核心功能。
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4523 +/- ##
==========================================
- Coverage 53.03% 52.91% -0.13%
==========================================
Files 1668 1677 +9
Lines 102934 103315 +381
Branches 22286 22377 +91
==========================================
+ Hits 54590 54664 +74
- Misses 40216 40478 +262
- Partials 8128 8173 +45
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/editor/src/browser/multi-diff/multi-diff-editor.ts (1)
122-124: 使用错误的API
ValueWithChangeEvent.const方法并不存在,这将导致编译错误。应使用已导入的constObservable函数。请应用以下修复:
- ? { resources: ValueWithChangeEvent.const(resource.metadata.sources) } + ? { resources: constObservable(resource.metadata.sources) }
🧹 Nitpick comments (5)
packages/editor/src/browser/multi-diff/multi-diff-editor.ts (5)
157-161: 添加空值检查以增强代码健壮性当前代码假设
original和modified的instance属性始终可用。虽然使用了可选链接操作符,但建议在创建result对象时进行更全面的空值检查。建议更健壮的实现方式:
const result = { multiDiffEditorItem: r, - original: original?.instance.getMonacoModel(), - modified: modified?.instance.getMonacoModel(), + original: original?.instance?.getMonacoModel() ?? null, + modified: modified?.instance?.getMonacoModel() ?? null, contextKeys: r.contextKeys, options: { readOnly: modified?.instance.readonly, ...this.convertedOptions.diffOptions, },
226-228: reveal方法缺少参数验证和错误处理
reveal方法直接将参数传递给底层widget,但没有验证参数的有效性或处理可能的错误。如果resource无效,可能导致未处理的异常。添加参数验证和错误处理:
reveal(resource: IMultiDiffResourceId, options?: { range?: Range; highlight: boolean }): void { + if (!resource) { + return; + } + try { this.multiDiffWidget.reveal(resource, options); + } catch (error) { + console.error('Failed to reveal resource:', error); + } }
167-173: 优化配置变更监听方式当前实现为每个文档项都创建了一个偏好设置变更监听器,这可能在大量文件差异比较时导致性能问题。
考虑使用一个共享的监听器来处理所有文档项的配置变更,或者在适当的时候清理这些监听器:
onOptionsDidChange: (h) => { - return this.preferenceService.onPreferenceChanged((e) => { + const disposable = this.preferenceService.onPreferenceChanged((e) => { if (e.affects(uri.toString()) && e.preferenceName.includes('editor')) { h(); } }); + return disposable; // 返回disposable以便后续清理 }
214-224: getCurrentDiffEntry方法实现效率低下当前实现先获取活动编辑器,然后从原始编辑器获取URI,最后再次查找文档差异项,这个过程可能不是最高效的。
考虑使用MultiDiffEditorWidget提供的更直接方法(如果存在):
getCurrentDiffEntry(): IDocumentDiffItem | undefined { + // 如果MultiDiffEditorWidget有直接提供当前活动项的方法,请使用它 + // return this.multiDiffWidget.getActiveDocumentDiffItem(); const activeControl = this.multiDiffWidget.getActiveControl(); if (!activeControl) { return undefined; } const originalUri = activeControl.getOriginalEditor().getModel()?.uri; if (!originalUri) { return undefined; } return this.multiDiffWidget.findDocumentDiffItem(originalUri); }
176-176: RefCounted对象创建方式可能引起资源管理复杂性当前代码使用
RefCounted.createOfNonDisposable将多个可释放对象组合在一起,这种模式虽然有效,但增加了资源管理的复杂性。在大型代码库中,这种资源管理模式可能变得难以追踪。考虑封装这种模式到一个更高级别的抽象中,或者使用更明确的资源生命周期管理策略。例如,可以创建一个专门的DiffItemResourceManager类来处理这些资源的生命周期管理。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/ai-native/src/browser/chat/chat-multi-diff-source.ts(1 hunks)packages/editor/src/browser/multi-diff/multi-diff-editor.ts(1 hunks)packages/editor/src/browser/workbench-editor.service.ts(10 hunks)packages/startup/entry/sample-modules/status-bar.contribution.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/startup/entry/sample-modules/status-bar.contribution.ts
- packages/ai-native/src/browser/chat/chat-multi-diff-source.ts
- packages/editor/src/browser/workbench-editor.service.ts
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: build-windows
- GitHub Check: build (macos-latest, 20.x)
- GitHub Check: build (ubuntu-latest, 20.x)
- GitHub Check: unittest (ubuntu-latest, 18.x, jsdom)
- GitHub Check: ubuntu-latest, Node.js 20.x
- GitHub Check: unittest (macos-latest, 18.x, jsdom)
- GitHub Check: unittest (ubuntu-latest, 18.x, node)
- GitHub Check: unittest (macos-latest, 18.x, node)
🔇 Additional comments (2)
packages/editor/src/browser/multi-diff/multi-diff-editor.ts (2)
74-74: 代码中存在待解决的问题注释中提到当前设计不支持动态修改 resource 的 name,且在 diff 数量变化时会有问题。
请考虑是否需要在正式发布前解决此问题,或者添加更多细节说明何时会出现此问题及其影响。这个限制应该在文档中明确说明,以便用户了解使用限制。
192-193: 通过调用dispose方法正确释放旧模型代码现在在赋值新的
multiDiffModel之前调用了dispose()方法,这解决了之前审阅中提出的内存泄漏问题。
Types
Background or solution
feat: support multi file diff editor
支持多文件 diff 编辑器管理,支持通过 resolverService 响应文件信息变化(command 多次调用更新,chat 文件改动自动更新),内置支持通过 command 和 chat 能力使用。(Git 需要后续升级 SCM 适配插件)
Changelog
feat: support multi file diff editor
feat: support view-changes for chat session
Summary by CodeRabbit
新功能
样式优化
国际化
其他改进