Skip to content

Commit c27a762

Browse files
committed
feat(linter): add AI-powered linting and detectors #453
Introduce AI-based linting with new detectors and exports. Update related core logic and documentation to support enhanced linting capabilities.
1 parent 25f606f commit c27a762

File tree

8 files changed

+1190
-24
lines changed

8 files changed

+1190
-24
lines changed

mpp-core/docs/linter.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
| Azure DevOps Pipelines | Pipeline Remediation | CI/CD Failure Remediation |
66
| CircleCI | CircleCI, Pipeline Remediation | Configuration Validation, CI/CD Failure Remediation |
77
| CloudFormation | Checkov | Code Security |
8-
| Cppcheck | Cppcheck | Code Quality |
8+
| Cppcheck | Cppcheck `` | Code Quality |
99
| CSS | Biome | Code Quality |
1010
| Docker | Hadolint, Checkov | Code Quality, Code Security |
1111
| Environment Files (.env) | Dotenv Linter | Code Quality |
1212
| GitHub Actions | actionlint, Pipeline Remediation | Code Quality, CI/CD Failure Remediation |
1313
| GitLab Pipelines | Pipeline Remediation | CI/CD Failure Remediation |
14-
| Go | golangci-lint `` | Code Quality |
14+
| Go | golangci-lint `` | Code Quality |
1515
| Helm | Checkov | Code Security |
1616
| HTML | HTMLHint | Code Quality |
17-
| Javascript | Biome, oxlint | Code Quality |
17+
| Javascript | Biome, lint | Code Quality |
1818
| JSON, JSONC | Biome | Code Quality |
1919
| JSX | Biome, oxlint | Code Quality |
2020
| Kotlin | detekt | Code Quality |
@@ -41,4 +41,4 @@
4141
| Typescript | Biome, oxlint | Code Quality |
4242
| YAML | YAMLlint | Code Quality |
4343
| Prisma | Prisma Lint | Code Quality |
44-
``
44+
``

mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodeReviewAgent.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,26 @@ class CodeReviewAgent(
158158
}
159159

160160
private suspend fun buildContext(task: ReviewTask): CodeReviewContext {
161+
// Get linter summary for the files
162+
val linterSummary = if (task.filePaths.isNotEmpty()) {
163+
try {
164+
val linterRegistry = cc.unitmesh.agent.linter.LinterRegistry.getInstance()
165+
linterRegistry.getLinterSummaryForFiles(task.filePaths)
166+
} catch (e: Exception) {
167+
logger.warn { "Failed to get linter summary: ${e.message}" }
168+
null
169+
}
170+
} else {
171+
null
172+
}
173+
161174
return CodeReviewContext(
162175
projectPath = task.projectPath,
163176
filePaths = task.filePaths,
164177
reviewType = task.reviewType,
165178
additionalContext = task.additionalContext,
166-
toolList = formatToolList()
179+
toolList = formatToolList(),
180+
linterSummary = linterSummary
167181
)
168182
}
169183

@@ -222,7 +236,8 @@ data class CodeReviewContext(
222236
val filePaths: List<String>,
223237
val reviewType: ReviewType,
224238
val additionalContext: String,
225-
val toolList: String
239+
val toolList: String,
240+
val linterSummary: cc.unitmesh.agent.linter.LinterSummary? = null
226241
)
227242

228243
/**

mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodeReviewAgentPromptRenderer.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,59 @@ class CodeReviewAgentPromptRenderer {
1515
else -> CodeReviewAgentTemplate.EN
1616
}
1717

18+
val linterInfo = formatLinterInfo(context.linterSummary)
19+
1820
val prompt = template
1921
.replace("{{projectPath}}", context.projectPath)
2022
.replace("{{reviewType}}", context.reviewType.name)
2123
.replace("{{filePaths}}", context.filePaths.joinToString(", "))
2224
.replace("{{toolList}}", context.toolList)
2325
.replace("{{additionalContext}}", context.additionalContext)
26+
.replace("{{linterInfo}}", linterInfo)
2427

2528
logger.debug { "Generated code review prompt (${prompt.length} chars)" }
2629
return prompt
2730
}
31+
32+
private fun formatLinterInfo(summary: cc.unitmesh.agent.linter.LinterSummary?): String {
33+
if (summary == null) {
34+
return "No linter information available."
35+
}
36+
37+
return buildString {
38+
appendLine("### Available Linters")
39+
appendLine()
40+
41+
if (summary.availableLinters.isNotEmpty()) {
42+
appendLine("**Installed and Ready (${summary.availableLinters.size}):**")
43+
summary.availableLinters.forEach { linter ->
44+
appendLine("- **${linter.name}** ${linter.version?.let { "($it)" } ?: ""}")
45+
if (linter.supportedFiles.isNotEmpty()) {
46+
appendLine(" - Files: ${linter.supportedFiles.joinToString(", ")}")
47+
}
48+
}
49+
appendLine()
50+
}
51+
52+
if (summary.unavailableLinters.isNotEmpty()) {
53+
appendLine("**Not Installed (${summary.unavailableLinters.size}):**")
54+
summary.unavailableLinters.forEach { linter ->
55+
appendLine("- **${linter.name}**")
56+
linter.installationInstructions?.let {
57+
appendLine(" - Install: $it")
58+
}
59+
}
60+
appendLine()
61+
}
62+
63+
if (summary.fileMapping.isNotEmpty()) {
64+
appendLine("### File-Linter Mapping")
65+
summary.fileMapping.forEach { (file, linters) ->
66+
appendLine("- `$file` → ${linters.joinToString(", ")}")
67+
}
68+
}
69+
}
70+
}
2871
}
2972

3073
/**
@@ -60,6 +103,10 @@ Analyze code thoroughly and provide constructive, actionable feedback. Focus on:
60103
- **Files to Review**: {{filePaths}}
61104
- **Additional Context**: {{additionalContext}}
62105
106+
## Linter Information
107+
108+
{{linterInfo}}
109+
63110
## Available Tools
64111
65112
{{toolList}}
@@ -159,6 +206,10 @@ Be constructive, specific, and actionable in your feedback.
159206
- **待审查文件**: {{filePaths}}
160207
- **额外上下文**: {{additionalContext}}
161208
209+
## Linter 信息
210+
211+
{{linterInfo}}
212+
162213
## 可用工具
163214
164215
{{toolList}}

0 commit comments

Comments
 (0)