Conversation
…tree views, and issue display - Add IdeaResizableSplitPane and IdeaVerticalResizableSplitPane components - Redesign DiffViewerPanel to match DiffCenterView from mpp-ui: - Add commit info card with issue display - Add file view mode toggle (list/tree) - Add expandable file list with diff hunks - Add tree view with directory grouping - Add issue loading/error states with refresh - Add new icons: List, AccountTree, Edit, DriveFileRenameOutline, FolderOpen, ChevronRight, BugReport, Info - Replace mikepenz markdown library with SimpleJewelMarkdown to fix NoSuchMethodError - Add openFileViewer method to IdeaCodeReviewViewModel
WalkthroughReplaced the multiplatform markdown renderer with a local SimpleJewelMarkdown (intellij-markdown), removed JewelMarkdown and its theme helpers, added eight ImageVector icons, introduced horizontal and vertical resizable split-pane composables, and refactored the code-review UI/viewmodel (added openFileViewer). Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Points requiring extra attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
| // Inline issue indicator | ||
| IdeaIssueIndicator( | ||
| commit = selectedCommit, | ||
| commitIndex = 0, |
There was a problem hiding this comment.
In the single‑commit view, commitIndex is hardcoded to 0 when calling IdeaIssueIndicator, so refresh can target the wrong commit if the selected commit isn’t the first; consider passing the actual selected commit’s index.
🤖 Was this useful? React with 👍 or 👎
| val basePath = project.basePath ?: return | ||
| val file = java.io.File(basePath, path) | ||
| if (file.exists()) { | ||
| val virtualFile = com.intellij.openapi.vfs.LocalFileSystem.getInstance().findFileByIoFile(file) |
There was a problem hiding this comment.
Using LocalFileSystem.findFileByIoFile without ensuring the VFS is current can return null even for existing files, which may prevent opening a file that exists on disk (e.g., if it hasn’t been indexed/loaded yet).
🤖 Was this useful? React with 👍 or 👎
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.kt (1)
18-27: Update outdated documentation.Line 21 references the old
multiplatform-markdown-rendererlibrary, which has been replaced withSimpleJewelMarkdownbacked by IntelliJ's markdown parser.Apply this diff to update the documentation:
/** * IntelliJ IDEA-specific Markdown renderer with Mermaid diagram support. * Uses Jewel components for native IntelliJ look and feel. - * Uses multiplatform-markdown-renderer for proper markdown parsing. + * Uses SimpleJewelMarkdown backed by IntelliJ's markdown parser. * * @param content The markdown content to render * @param isComplete Whether the content is complete (not streaming) * @param parentDisposable Parent disposable for JCEF resource cleanup * @param modifier Compose modifier */
🧹 Nitpick comments (15)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt (1)
928-980: New List / AccountTree icons are consistent and idiomaticThe
ListandAccountTreevectors follow the existing pattern (24×24 viewport, black fill,lazyinitialization) and fit cleanly into the existing icon set; nothing blocking here. One tiny detail: inAccountTree, theverticalLineToRelative(8f)fromy=17fbriefly moves the path down toy=25f, which is just outside the 24px viewport and will be clipped. It’s harmless, but if you care about pixel‑perfect bounds you could adjust that segment (e.g., to land aty=24for switch to an absoluteverticalLineTo(23f)depending on the intended design).Also applies to: 982-1020
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (2)
44-201: Add a true raw‑text fallback for unhandled node typesThe
elsebranch comment says “render children or show raw text”, but currently only child traversal happens; leaf token nodes with no children will render nothing. You can make the behavior match the comment and improve robustness for unhandled types by adding a raw‑text fallback for leaf nodes:- else -> { - // For other node types, try to render children or show raw text - if (node.children.isNotEmpty()) { - node.children.forEach { child -> - RenderNode(node = child, content = content) - } - } - } + else -> { + // For other node types, try to render children or show raw text + if (node.children.isNotEmpty()) { + node.children.forEach { child -> + RenderNode(node = child, content = content) + } + } else { + val text = node.getTextInNode(content).toString().trim() + if (text.isNotEmpty()) { + Text( + text = text, + style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp), + modifier = Modifier.padding(vertical = 2.dp) + ) + } + } + }This keeps existing behavior for structured nodes while ensuring stray or less common nodes still show something sensible.
214-219: Consider how to handle very short or malformed code fencesCurrently
extractCodeFenceContentreturns an empty string when there are ≤ 2 lines, which effectively drops single‑line or malformed fences. That may be fine for your use case, but if you expect partial fences from streaming or tools, you might want to preserve whatever content is present instead of returning an empty string.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.kt (1)
18-24: Update KDoc to reference SimpleJewelMarkdown instead of JewelMarkdownThe doc still says “Markdown/Text -> JewelMarkdown”, but the implementation now uses
SimpleJewelMarkdown. To keep the documentation accurate, update this line accordingly, for example:- * - Markdown/Text -> JewelMarkdown + * - Markdown/Text -> SimpleJewelMarkdownmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaVerticalResizableSplitPane.kt (3)
83-83: Consider using a vertical resize cursor instead of Crosshair.
PointerIcon.Crosshairis typically used for precision selection, not for resize operations. For a vertical split pane, users would expect a north-south resize cursor to indicate the divider can be dragged vertically.- .pointerHoverIcon(PointerIcon.Crosshair) + .pointerHoverIcon(PointerIcon.Hand)Note: Compose Multiplatform may have limited cursor options. If
PointerIcon.Handdoesn't convey the resize intent well, consider creating a custom cursor or leaving as-is if platform constraints apply.
90-101: Scaled divider may overflow its container.When
dividerScaleanimates to 1.2f, the inner Spacer's height becomesdividerHeight * 1.2, which exceeds the parent Box's fixed height ofdividerHeight.dp. This could cause visual clipping. If the scale effect is intentional for visual feedback, consider usingModifier.graphicsLayer { scaleY = dividerScale }instead to scale without affecting layout bounds.
123-128: State update during measurement phase.Setting
containerHeightinside the Layout's measure lambda is a side effect during composition, which could potentially trigger recomposition. While this pattern is common and works in practice, usingModifier.onGloballyPositioned { containerHeight = it.size.height }on the root modifier would be more idiomatic.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaResizableSplitPane.kt (2)
83-83: Consider using a horizontal resize cursor.Similar to the vertical variant,
PointerIcon.Crosshairis not the conventional cursor for horizontal resize operations. Users typically expect an east-west resize cursor for horizontal dividers.
36-140: Consider extracting shared logic between horizontal and vertical split panes.Both
IdeaResizableSplitPaneandIdeaVerticalResizableSplitPaneshare nearly identical logic (~90% overlap). Consider creating a shared internal implementation parameterized by orientation to reduce duplication and ensure consistent behavior when making future changes.This could be a follow-up refactor if the current implementation proves stable.
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt (6)
90-90: TODO: Token configuration not implemented.The
onConfigureTokencallback currently has an empty implementation with a TODO comment. Consider creating an issue to track this.Would you like me to open an issue to track the token configuration implementation?
169-173: Selection highlight may have insufficient contrast.Using
panelBackground.copy(alpha = 0.8f)for selected items versuspanelBackgroundfor unselected may not provide enough visual distinction. Consider using a different color (e.g.,JewelTheme.globalColors.outlines.focused.copy(alpha = 0.1f)) or a more contrasting approach.
544-544: Fragile error detection via string matching.Using
errorMessage.contains("Authentication", ignoreCase = true)to detect auth errors is fragile and may break if error messages change or are localized. Consider using a structured error type or error code instead.// Example: Use a sealed class or enum for error types sealed class IssueLoadError { data class AuthenticationError(val message: String) : IssueLoadError() data class NetworkError(val message: String) : IssueLoadError() data class UnknownError(val message: String) : IssueLoadError() }
1718-1725: Non-collapsible card using collapsible wrapper.This section uses
IdeaCollapsibleCardwithisExpanded = trueand an emptyonExpandChange, making it effectively non-collapsible. While functional, this is slightly misleading. Consider adding acollapsible: Boolean = trueparameter toIdeaCollapsibleCardor using a simpler card wrapper for non-collapsible sections.
1850-1856: Consider using icons for collapse indicator.The collapsible card uses text (
+/-) for the expand/collapse indicator, while other components use proper icons (ChevronRight,ExpandMore). Consider using consistent iconography for a more polished appearance.Text( - text = if (isExpanded) "-" else "+", + // Replace with: +) +Icon( + imageVector = if (isExpanded) + cc.unitmesh.devins.idea.toolwindow.IdeaComposeIcons.ExpandMore + else + cc.unitmesh.devins.idea.toolwindow.IdeaComposeIcons.ChevronRight, + contentDescription = if (isExpanded) "Collapse" else "Expand", + tint = JewelTheme.globalColors.text.normal, + modifier = Modifier.size(16.dp) +)
1-40: Consider splitting this large file.At 1900+ lines, this file contains multiple logical groupings that could be extracted into separate files for better maintainability:
IdeaCommitListComponents.kt- CommitListPanel, CommitItemIdeaDiffViewerComponents.kt- DiffViewerPanel, IdeaCompactFileListView, IdeaFileTreeView, etc.IdeaAIAnalysisComponents.kt- IdeaAIAnalysisPanel and related sectionsIdeaUIComponents.kt- Reusable utilities like IdeaCollapsibleCard, IdeaBadgeThis would improve code navigation and make the codebase more modular.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
mpp-idea/build.gradle.kts(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.kt(3 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdown.kt(0 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdownColors.kt(0 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdownTypography.kt(0 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.kt(2 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt(4 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaResizableSplitPane.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaVerticalResizableSplitPane.kt(1 hunks)
💤 Files with no reviewable changes (3)
- mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdownTypography.kt
- mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdownColors.kt
- mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/JewelMarkdown.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Use
expect/actualfor platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaVerticalResizableSplitPane.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaResizableSplitPane.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
🧠 Learnings (4)
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/src/{androidMain,desktopMain}/**/*.kt : For Compose (Desktop/Android), use `AutoDevColors` from `cc.unitmesh.devins.ui.compose.theme` or `MaterialTheme.colorScheme`
Applied to files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to {mpp-ui/src/jsMain/typescript/**/*.{ts,tsx},**/src/{androidMain,desktopMain}/**/*.kt} : DO NOT hardcode colors (e.g., `Color(0xFF...)` or `#hex`). Always use design tokens for consistency across platforms
Applied to files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: For IntelliJ IDEA Plugin build, use `cd mpp-idea && ../gradlew compileKotlin` instead of `./gradlew :mpp-idea:compileKotlin` from root
Applied to files:
mpp-idea/build.gradle.kts
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Use `cd mpp-idea && ../gradlew test --tests "cc.unitmesh.devins.idea.renderer.JewelRendererTest"` for running standalone JUnit 5 tests that do not require IntelliJ Platform
Applied to files:
mpp-idea/build.gradle.kts
🧬 Code graph analysis (3)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.kt (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (1)
SimpleJewelMarkdown(30-42)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.kt (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (1)
SimpleJewelMarkdown(30-42)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaResizableSplitPane.kt (1)
IdeaResizableSplitPane(36-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build (223)
- GitHub Check: Build (241)
🔇 Additional comments (16)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/IdeaMarkdownRenderer.kt (2)
48-52: LGTM!The migration to
SimpleJewelMarkdownis correct. The simplified API (content + modifier only) aligns with the new implementation and removes the need for explicit color/typography configuration.
83-86: LGTM!The migration to
SimpleJewelMarkdownfor inline markdown blocks within the Mermaid-aware renderer is consistent with the main renderer changes and correctly uses the new simplified API.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt (3)
1022-1089: Edit / DriveFileRenameOutline icons: shapes and naming look good
EditandDriveFileRenameOutlinematch their Material counterparts closely and keep the same naming convention as the rest of the file. Builder parameters and fill settings are consistent with the existing icons; no issues from a correctness or style perspective.
1091-1150: FolderOpen / ChevronRight: aligned with existing Folder and navigation icons
FolderOpennicely complements the existingFoldericon, andChevronRightmatches the style and proportions ofExpandLess/ExpandMore. Both reuse the same 24×24 vector baseline and SolidColor fill, so they should integrate cleanly with the redesigned diff tree/list toggles.
1152-1256: BugReport / Info icons integrate cleanly with existing status glyphs
BugReportandInforeuse the same circular/status idiom asErrorandCheckCircleabove (same viewport, circle‑plus‑glyph composition, black fill), which will give consistent visual language for issue/diagnostic states. Paths look well‑formed and bounded; nothing stands out as problematic.mpp-idea/build.gradle.kts (1)
108-109: Comment clarification about markdown renderer looks goodThe note accurately reflects the migration to
SimpleJewelMarkdownwith the IntelliJ markdown parser and documents the Compose version‑mismatch rationale clearly.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (2)
30-42: Markdown parsing and Compose state usage are soundCreating the GFM flavour, parser, and markdown tree with
rememberkeyed bycontentis appropriate; it avoids unnecessary reparsing while ensuring updates when the input changes.
206-209: Header text extraction is straightforward and correctTrimming leading
#characters and then whitespace matches typical ATX header formatting and should work well with the upstream parser.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/sketch/IdeaSketchRenderer.kt (1)
9-10: Switch to SimpleJewelMarkdown in sketch renderer looks correctThe new import and usage of
SimpleJewelMarkdown(fence.text, Modifier.fillMaxWidth())align with its API and cleanly swap out the previous markdown renderer without affecting the surrounding control flow.Also applies to: 48-51
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaVerticalResizableSplitPane.kt (1)
36-45: LGTM - Well-structured vertical split pane component.The component provides a clean API with sensible defaults. The implementation properly handles drag gestures, state management, and visual feedback. The consistency with
IdeaResizableSplitPaneis good for maintainability.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/components/IdeaResizableSplitPane.kt (1)
102-117: Good practice: keying pointerInput on containerWidth.Using
containerWidthas the key forpointerInputensures the gesture detector is recreated when the container dimension changes, preventing stale closure issues.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt (5)
50-106: Well-structured three-column layout.The nested
IdeaResizableSplitPaneapproach provides a clean implementation of the three-column resizable layout. The split ratios (18%, 55%) provide sensible defaults.
229-351: LGTM - DiffViewerPanel implementation.The panel properly handles loading, empty, and populated states. The view mode toggle between list and tree views is well-implemented, and the component delegates rendering to appropriate child composables.
1015-1023: Potential display issue with prefix removal.
line.content.removePrefix(prefix)assumes the line content may start with the prefix. Ifline.contentis already stripped of the prefix (from the diff parser), this is fine. However, if the content includes a different character at the start, it will display correctly. Just ensure consistency with howDiffLine.contentis populated upstream.
1295-1417: Well-organized AI Analysis panel.The panel effectively organizes multiple analysis stages (lint, AI analysis, plan, user input, fixes) into collapsible sections. The conditional rendering based on
AnalysisStageis clear and maintainable.
1506-1557: LGTM - Lint analysis card.The collapsible lint analysis card with error/warning counts as badges and per-file issue display is well-implemented. The limit of 5 issues per file with a "more" indicator is a good UX choice.
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
Outdated
Show resolved
Hide resolved
| if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) { | ||
| CircularProgressIndicator() | ||
| } |
There was a problem hiding this comment.
Add size modifier to CircularProgressIndicator.
The CircularProgressIndicator() inside the status badge box has no size constraint and may render too large. Add a size modifier for consistent appearance within the badge.
if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) {
- CircularProgressIndicator()
+ CircularProgressIndicator(modifier = Modifier.size(12.dp))
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) { | |
| CircularProgressIndicator() | |
| } | |
| if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) { | |
| CircularProgressIndicator(modifier = Modifier.size(12.dp)) | |
| } |
🤖 Prompt for AI Agents
In
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
around lines 1468-1470, the CircularProgressIndicator in the status badge lacks
a size constraint and can render too large; update the composable invocation to
apply a size modifier (e.g., Modifier.size(16.dp or 20.dp)) so it fits the
badge, and keep any existing alignment/padding modifiers consistent with the
surrounding layout.
| horizontalArrangement = Arrangement.spacedBy(4.dp), | ||
| verticalAlignment = Alignment.CenterVertically | ||
| ) { | ||
| CircularProgressIndicator() |
There was a problem hiding this comment.
Add size modifier to CircularProgressIndicator.
Same issue as in IdeaAnalysisHeader - the spinner should have a size modifier.
-CircularProgressIndicator()
+CircularProgressIndicator(modifier = Modifier.size(12.dp))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CircularProgressIndicator() | |
| CircularProgressIndicator(modifier = Modifier.size(12.dp)) |
🤖 Prompt for AI Agents
In
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
around line 1780, the CircularProgressIndicator is missing a size modifier; add
a Modifier.size(...) to the spinner (use the same dp value used in
IdeaAnalysisHeader so both spinners match), ensuring you import and use
Modifier.size from androidx.compose.ui and the dp unit from
androidx.compose.ui.unit.
...dea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.kt
Show resolved
Hide resolved
- Add support for inline formatting (bold, italic, strikethrough, code) - Add clickable links with URL annotations - Add GFM table rendering with header/body rows - Add horizontal rule support - Add nested list support with proper indentation - Add GFM checkbox/task list support - Add code fence with language header display - Add block quote with styled left border - Add image alt text display - Fix Composable context issues by passing colors as parameters
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt (2)
1428-1487: Constrain spinner size in AI header status badge
CircularProgressIndicator()in the small status badge can visually dominate the label. As previously noted, adding a size modifier keeps it proportional to the badge:- if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) { - CircularProgressIndicator() - } + if (stage != AnalysisStage.COMPLETED && stage != AnalysisStage.ERROR) { + CircularProgressIndicator(modifier = Modifier.size(12.dp)) + }This matches the compact badge styling without affecting behavior.
1768-1792: Constrain spinner size in Fix Generation badgeThe
CircularProgressIndicator()inside the “Fix Generation” card’s badge row is also unbounded and can appear oversized next toIdeaBadge. Recommend mirroring the compact sizing used elsewhere:- if (isGenerating) { - Row( + if (isGenerating) { + Row( horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically ) { - CircularProgressIndicator() + CircularProgressIndicator(modifier = Modifier.size(12.dp)) IdeaBadge(text = "Generating...", color = AutoDevColors.Indigo.c400) }The larger, centered spinner in the body (
Box(...){ CircularProgressIndicator() }) can rightly stay full‑size.
🧹 Nitpick comments (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.kt (1)
52-75: openFileViewer: EDT usage and VFS refresh look solid; consider guarding disposed projectThe method correctly logs failure cases, resolves paths relative to
basePath, refreshes VFS, and runsopenFileon the EDT viainvokeLater. One small robustness improvement would be to bail out if the project is disposed by the time the runnable executes:val localFileSystem = LocalFileSystem.getInstance() ApplicationManager.getApplication().invokeLater { if (project.isDisposed) { logger.warn("Project disposed before opening file: ${file.path}") return@invokeLater } val virtualFile = localFileSystem.refreshAndFindFileByIoFile(file) if (virtualFile != null) { FileEditorManager.getInstance(project).openFile(virtualFile, true) } else { logger.warn("VirtualFile not found for file: ${file.path}") } }This avoids trying to open editors on a disposed project in edge cases.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt(4 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.kt(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Use
expect/actualfor platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewViewModel.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
🧠 Learnings (1)
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/src/{androidMain,desktopMain}/**/*.kt : For Compose (Desktop/Android), use `AutoDevColors` from `cc.unitmesh.devins.ui.compose.theme` or `MaterialTheme.colorScheme`
Applied to files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build (223)
- GitHub Check: Build (241)
🔇 Additional comments (3)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/codereview/IdeaCodeReviewContent.kt (3)
57-106: Three‑pane layout and diff viewer wiring look consistentThe new nested
IdeaResizableSplitPanelayout cleanly separates commits, diff, and AI analysis, andDiffViewerPanelis correctly wired withselectedCommits,selectedCommitIndices, and callbacks (onViewFile,onRefreshIssue,onConfigureToken). Using the view model’s state flow viacollectAsState()keeps the UI reactive without obvious recomposition pitfalls. No functional issues spotted here.Also applies to: 214-354
356-751: Diff/file views and tree structure are well‑factored and performant enough for typical sizesThe commit info + issue indicator, compact file list, and tree view are nicely decomposed:
IdeaIssueIndicatorcovers loading/info/error states with clear affordances (refresh, token config) and uses small, focused composables (IdeaInlineIssueChip,IdeaIssueInfoCard).IdeaCompactFileListViewandIdeaFileTreeViewavoid repeatedindexOfscans and use either list indices orfile.pathfor expansion, giving O(1) state checks per row.IdeaDiffHunkView/IdeaDiffLineViewcorrectly derive prefixes, line numbers, and colors fromDiffLineType, and horizontal scrolling on content is a pragmatic choice for long lines.Overall, the diff rendering and file navigation structure look sound, with no clear correctness or performance issues for expected diff sizes.
Also applies to: 753-959, 962-1032, 1038-1160, 1120-1142, 1147-1197, 1202-1295
1301-1423: AI analysis, plan, user input, and fixes flow is coherent and stage‑driven
IdeaAIAnalysisPaneland its subcomponents (IdeaAnalysisHeader, lint/analysis/plan/user input/fix sections,IdeaCollapsibleCard,IdeaBadge) form a clear stage machine aroundAnalysisStageandaiProgress. Conditions for rendering each section match the intended flow (lint → analysis → plan → optional user feedback → fixes), and the shared collapsible card primitive keeps the UI consistent and maintainable. Aside from the spinner sizing nits already noted, this structure looks ready for incremental enhancements (e.g., richer plan selection) without major changes.Also applies to: 1512-1915
- Parse GFM table structure correctly using HEADER, ROW, and CELL types - Calculate adaptive column weights based on content length - Clean cell text by removing markdown formatting (|, `, **, *) - Add proper vertical alignment for table rows - Reference implementation from mpp-ui/MarkdownTableRenderer.kt
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (1)
625-645: Document magic numbers for table column constraints.The values
0.15f(min) and0.65f(max) for column width constraints lack explanation. Adding comments would improve maintainability.// Convert to weights with min/max constraints val floatLengths = lengths.map { it.coerceAtLeast(1).toFloat() } val total = floatLengths.sum() + // Constrain each column between 15% and 65% to prevent extremely narrow/wide columns val constrained = floatLengths.map { (it / total).coerceIn(0.15f, 0.65f) } val constrainedTotal = constrained.sum() + // Normalize weights to sum to 1.0 constrained.map { it / constrainedTotal }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Use
expect/actualfor platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build (223)
- GitHub Check: Build (241)
🔇 Additional comments (5)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (5)
216-307: LGTM!The inline formatting builder comprehensively handles markdown inline elements with proper styling. The approach of using
withStyleandpushStringAnnotationfor links is correct.
349-442: LGTM!Code block rendering is well-implemented with proper theming, language display, and horizontal scrolling support. The visual design with rounded corners and borders aligns well with the Jewel theme.
481-588: LGTM!List rendering with nested support and GFM checkbox handling is well-implemented. The depth-based bullet variation and indentation provide good visual hierarchy.
755-810: LGTM!Helper functions properly extract text from header and code fence nodes with appropriate fallbacks and bounds checking.
33-34: [No changes required]This is a JVM-only IntelliJ plugin module (using
kotlin("jvm")plugin), not a multiplatform module. TheDesktopAPI usage is appropriate for this context and does not violate KMP guidelines.
| @Suppress("DEPRECATION") | ||
| ClickableText( | ||
| text = annotatedString, | ||
| style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp), | ||
| modifier = Modifier.padding(vertical = 2.dp), | ||
| onClick = { offset -> | ||
| annotatedString.getStringAnnotations("URL", offset, offset) | ||
| .firstOrNull()?.let { annotation -> | ||
| if (onLinkClick != null) { | ||
| onLinkClick(annotation.item) | ||
| } else { | ||
| try { | ||
| Desktop.getDesktop().browse(URI(annotation.item)) | ||
| } catch (e: Exception) { | ||
| // Ignore | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ) |
There was a problem hiding this comment.
Address deprecated API and improve error handling.
Two concerns:
ClickableTextis deprecated in Compose. Consider migrating toTextwithModifier.clickableorClickableTextalternatives when available.- The exception at lines 197-199 is silently ignored, making it difficult to diagnose link-opening failures.
Apply this diff to at least log the exception:
} else {
try {
Desktop.getDesktop().browse(URI(annotation.item))
} catch (e: Exception) {
- // Ignore
+ // Log or report link opening failure
+ println("Failed to open link: ${annotation.item}, error: ${e.message}")
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Suppress("DEPRECATION") | |
| ClickableText( | |
| text = annotatedString, | |
| style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp), | |
| modifier = Modifier.padding(vertical = 2.dp), | |
| onClick = { offset -> | |
| annotatedString.getStringAnnotations("URL", offset, offset) | |
| .firstOrNull()?.let { annotation -> | |
| if (onLinkClick != null) { | |
| onLinkClick(annotation.item) | |
| } else { | |
| try { | |
| Desktop.getDesktop().browse(URI(annotation.item)) | |
| } catch (e: Exception) { | |
| // Ignore | |
| } | |
| } | |
| } | |
| } | |
| ) | |
| @Suppress("DEPRECATION") | |
| ClickableText( | |
| text = annotatedString, | |
| style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp), | |
| modifier = Modifier.padding(vertical = 2.dp), | |
| onClick = { offset -> | |
| annotatedString.getStringAnnotations("URL", offset, offset) | |
| .firstOrNull()?.let { annotation -> | |
| if (onLinkClick != null) { | |
| onLinkClick(annotation.item) | |
| } else { | |
| try { | |
| Desktop.getDesktop().browse(URI(annotation.item)) | |
| } catch (e: Exception) { | |
| // Log or report link opening failure | |
| println("Failed to open link: ${annotation.item}, error: ${e.message}") | |
| } | |
| } | |
| } | |
| } | |
| ) |
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt
Show resolved
Hide resolved
- Extract text from TEXT tokens within cells instead of raw substring - Add collectTextFromNode to recursively collect text from AST nodes - Handle WHITE_SPACE tokens as spaces - Fixes table rendering showing one character per line
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (1)
640-642: Consider documenting magic numbers for table column constraints.The column weight constraints
0.15fand0.65fcontrol minimum and maximum column widths but lack explanation. Consider extracting these as named constants with comments describing the rationale (e.g., preventing columns from being too narrow or too wide).+ // Column width constraints: minimum 15%, maximum 65% to prevent extreme sizes + private const val MIN_COLUMN_WEIGHT = 0.15f + private const val MAX_COLUMN_WEIGHT = 0.65f + // Calculate adaptive column weights based on content length val columnWeights = remember(node, content) { val lengths = IntArray(columnsCount) { 0 } // ... val floatLengths = lengths.map { it.coerceAtLeast(1).toFloat() } val total = floatLengths.sum() - val constrained = floatLengths.map { (it / total).coerceIn(0.15f, 0.65f) } + val constrained = floatLengths.map { (it / total).coerceIn(MIN_COLUMN_WEIGHT, MAX_COLUMN_WEIGHT) } val constrainedTotal = constrained.sum() constrained.map { it / constrainedTotal } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Use
expect/actualfor platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Files:
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt
🔇 Additional comments (2)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt (2)
265-267: Verify intentional spacing around inline code.Adding spaces around inline code spans (
" $codeText ") ensures visual separation but may introduce unwanted whitespace in some contexts. Confirm this is the desired behavior.
33-34: > Likely an incorrect or invalid review comment.
| try { | ||
| Desktop.getDesktop().browse(URI(annotation.item)) |
There was a problem hiding this comment.
Validate URLs before opening to prevent potential security issues.
Opening arbitrary URLs from markdown content without validation could pose security risks, especially if the markdown source is untrusted. Consider validating the URL scheme to allow only safe protocols like http and https.
Apply this diff to add URL validation:
} else {
try {
- Desktop.getDesktop().browse(URI(annotation.item))
+ val uri = URI(annotation.item)
+ if (uri.scheme in listOf("http", "https")) {
+ Desktop.getDesktop().browse(uri)
+ }
} catch (e: Exception) {
// Ignore
}
}🤖 Prompt for AI Agents
In
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/renderer/markdown/SimpleJewelMarkdown.kt
around lines 195-196, validate the annotation.item URI before calling
Desktop.getDesktop().browse: parse annotation.item into a java.net.URI, check
its scheme (lowercased) is either "http" or "https", and only call
Desktop.browse when valid; otherwise skip and log or ignore. Also wrap the
parsing and browse call in a try/catch to handle URISyntaxException and
IOException and avoid throwing unchecked exceptions for malformed or unsupported
URLs.
Summary
Redesign the
IdeaCodeReviewContent.ktto add missing Plan and Fix UI sections, and rewriteDiffViewerPanelto matchDiffCenterView.ktfrom mpp-ui.Changes
New Components
IdeaResizableSplitPane.kt- Horizontal resizable split pane with Jewel themingIdeaVerticalResizableSplitPane.kt- Vertical resizable split pane with Jewel themingSimpleJewelMarkdown.kt- Custom markdown renderer using JetBrains'intellij-markdownparser (fixes NoSuchMethodError crash)New Icons
Added 8 new icons to
IdeaComposeIcons.kt:DiffViewerPanel Redesign
Bug Fixes
SimpleJewelMarkdownopenFileViewermethod toIdeaCodeReviewViewModelfor opening files in IDETesting
cd mpp-idea && ../gradlew compileKotlinSummary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.