Repository navigation
Expand file tree
/
Copy path.coderabbit.yaml
More file actions
271 lines (251 loc) · 15.3 KB
/
Copy path.coderabbit.yaml
File metadata and controls
271 lines (251 loc) · 15.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# yaml-language-server: $schema=https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json
#
# CodeRabbit configuration for compose-stability-analyzer.
#
# This repository is NOT an app — it is a multi-module developer-tool suite:
# - stability-compiler : Kotlin K2 compiler plugin (FIR analysis + IR instrumentation)
# - stability-runtime : KMP runtime (android/jvm/js/wasmJs/ios) emitting recomposition logs
# - stability-gradle : Gradle plugin (KotlinCompilerPluginSupportPlugin + stabilityDump/Check)
# - stability-lint : Android Lint rules packaged into the runtime AAR
# - compose-stability-analyzer-idea : IntelliJ/Android Studio plugin (separate build)
# - compiler-tests : Kotlin compiler-test-framework suite (box/diagnostic/golden dumps)
# - app, app-model : sample/integration app only
#
# Review priorities follow from that: cross-module protocol compatibility (logcat format,
# SubpluginOption keys, version pins) and "never break the user's build" failure-safety matter
# far more than style — formatting is fully owned by Spotless in CI.
language: "en-US"
early_access: false
tone_instructions: >-
Review as a senior Kotlin compiler/Gradle/IntelliJ-plugin engineer. Prioritize
correctness, cross-module protocol compatibility, and published-API backward
compatibility. Never comment on formatting (Spotless owns it). Be direct; skip praise.
reviews:
profile: "chill"
request_changes_workflow: false
high_level_summary: true
poem: false
review_status: true
collapse_walkthrough: true
auto_review:
enabled: true
drafts: false
ignore_usernames:
- "dependabot[bot]"
- "renovate[bot]"
# ── What NOT to review ─────────────────────────────────────────────────────
# Everything below the `!` lines is machine-generated, binary, or a baseline that must be
# regenerated by a Gradle task instead of being hand-edited — review comments on these
# files are pure noise.
path_filters:
# Generated JUnit classes from the Kotlin compiler test framework
# (regenerated via `./gradlew :compiler-tests:generateTests` — never hand-written).
- "!compiler-tests/src/test/java/**"
# Golden dump data (FIR/IR snapshots), regenerated with `-Pupdate.test.data`.
# The *.kt test-data SOURCES next to them ARE reviewed; only snapshots are excluded.
- "!compiler-tests/src/test/data/**/*.txt"
# Binary-compatibility-validator dumps, regenerated via `./gradlew apiDump`.
- "!**/api/*.api"
# Stability baselines produced by the plugin's own `stabilityDump` task.
- "!app/stability/*.stability"
# Kotlin/JS package-manager lockfiles.
- "!kotlin-js-store/**"
# Images / marketing assets and IDE plugin icons.
- "!art/**"
- "!**/*.png"
- "!**/*.gif"
- "!**/*.svg"
# Gradle wrapper binaries/scripts and build outputs.
- "!gradle/wrapper/**"
- "!gradlew"
- "!gradlew.bat"
- "!**/build/**"
- "!**/.gradle/**"
# Spotless license-header templates (boilerplate by definition).
- "!spotless/**"
# IDE metadata and GitHub boilerplate.
- "!.idea/**"
- "!**/*.iml"
- "!.github/ISSUE_TEMPLATE/**"
- "!.github/FUNDING.yml"
- "!LICENSE"
# ── Per-module review checklists ───────────────────────────────────────────
path_instructions:
# ===== stability-compiler: K2 compiler plugin =====
- path: "stability-compiler/src/main/kotlin/**"
instructions: >-
This is a K2-only Kotlin compiler plugin (FIR frontend analysis + IR backend
instrumentation). Check:
(1) FAILURE SAFETY — IR transformation must never break a consumer's build: codegen
paths should degrade to "not instrumented" (guarded returns / try-catch) rather than
throw out of the transformer.
(2) INFERENCE PARITY — any change to stability inference (analyzeTypeStability and
related helpers, KNOWN_STABLE_TYPES) must mirror the IDE plugin's analyzer
(compose-stability-analyzer-idea: StabilityAnalyzer/KtStabilityInferencer and
StabilityAnalysisConstants) and Compose 2.4.0 semantics (interfaces and non-final
classes infer UNKNOWN). Flag one-sided edits.
(3) SYMBOL RESOLUTION — runtime symbols must be resolved defensively: overloads
selected deliberately (e.g. by arity, never firstOrNull on findFunctions), and missing
symbols must disable instrumentation instead of failing.
(4) OPTION PLUMBING — new CommandLineProcessor options need the full chain: CliOption +
CompilerConfigurationKey + registrar + extension + a matching SubpluginOption key in
stability-gradle (names must match exactly).
(5) Reflection-based IrConst value extraction is intentionally version-tolerant; keep
fallbacks when touching it.
(6) Golden-impacting changes require regenerated compiler-tests dump data in the same PR.
# ===== stability-runtime: KMP runtime + log protocol =====
- path: "stability-runtime/src/**"
instructions: >-
Kotlin Multiplatform runtime consumed as a published library (explicit API mode).
Check:
(1) LOG FORMAT IS A WIRE PROTOCOL — the logcat output of DefaultRecompositionLogger is
parsed by the IDE plugin's LogcatParser. Header lines may only be extended with
TRAILING optional tokens (older parsers match ordered optional groups and ignore
trailing extras); changing/reordering existing tokens, prefixes (├─/└─, [param]/[state]),
or the `old → new` arrow encoding is a breaking protocol change and needs matching
parser updates plus compatibility tests in the IDE module.
(2) BINARY/SOURCE COMPAT — public API changes must be additive (new overloads or
defaulted parameters; keep legacy entry points delegating). RecompositionLogger
implementations in user code must keep compiling.
(3) EXPECT/ACTUAL — a change to one platform actual (jvmCommonMain/nonJvmMain/
nativeMain/androidMain/jvmMain/jsMain/wasmJsMain) usually needs the same change in ALL
of them; flag asymmetry, including divergent log output between platforms. A new KMP
target must join a family in the runtime's applyHierarchyTemplate block, otherwise it
silently loses the actuals the compiler plugin resolves (rememberRecompositionTracker,
recompositionNanoTime) and @TraceRecomposition becomes a no-op there.
(4) HOT PATH OVERHEAD — tracker code runs on every recomposition of instrumented
composables. When ComposeStabilityAnalyzer is disabled the path must allocate nothing
(early returns BEFORE building events/lists).
(5) CONCURRENCY — global tracker state can be hit from multiple composition threads;
require thread-safe structures. Android actuals must respect minSdk 21 (e.g. no
ConcurrentHashMap.computeIfAbsent, which needs API 24).
# ===== stability-gradle: Gradle plugin =====
- path: "stability-gradle/src/main/kotlin/**"
instructions: >-
Gradle plugin following the KotlinCompilerPluginSupportPlugin subplugin pattern. Check:
(1) AGP ISOLATION — com.android.* may ONLY be imported in AndroidStabilityTaskRegistrar
(AGP is compileOnly; consumers may have no AGP at all). Any AGP type reference in the
plugin entry class, base registrar, or JVM registrar is a NoClassDefFoundError for
KMP/JVM consumers — flag it as critical. Android detection must stay string-based
(plugins.hasPlugin("com.android.base")).
(2) LAZY CONFIGURATION — use Provider/TaskProvider/configureEach; no eager task
realization or .get() at configuration time outside providers. The repo relies on
org.gradle.configureondemand, so avoid cross-project coupling at configuration time.
(3) VERSION PIN — the hardcoded VERSION constant must equal gradle.properties
VERSION_NAME; flag any bump that touches one but not the other (and the
compose-stability-analyzer entry in gradle/libs.versions.toml used by the sample app).
(4) OPTION KEYS — SubpluginOption keys must exactly match the compiler plugin's
CommandLineProcessor option names.
(5) BASELINE COMPAT — .stability file format changes must keep stabilityCheck able to
read existing committed baselines, or explicitly call out the migration.
(6) Task-name matching heuristics (test detection, variant filtering) are
case-sensitivity traps; require unit tests for new matching rules.
# ===== stability-lint: Android Lint rules =====
- path: "stability-lint/src/**"
instructions: >-
Android Lint rules packaged into the runtime AAR's lint.jar. Check that detector
Issue registrations (id, severity, category) stay stable for suppression
compatibility, that the lint API level matches the pinned lintApi version, and that
detectors are defensive against unresolvable PSI/UAST (never throw from visitors).
# ===== compose-stability-analyzer-idea: IntelliJ plugin =====
- path: "compose-stability-analyzer-idea/src/main/**"
instructions: >-
IntelliJ/Android Studio plugin (separate IntelliJ Platform build, K2-mode IDE). Check:
(1) THREADING — PSI access only inside read actions (runReadAction /
ReadAction.compute); UI mutation only on EDT (invokeLater); long work in
Task.Backgroundable with checkCanceled; prefer chunked read actions over one giant
read action. Scheduled executors and listeners must be tied to a Disposable.
(2) RESOLUTION SAFETY — K2 Analysis API and resolveMainReference can throw in dumb
mode or partially-indexed projects: wrap in runCatching and degrade gracefully;
gate project scans on smart mode.
(3) PARSER COMPAT — LogcatParser must keep accepting BOTH legacy (no fq/auto tokens)
and current runtime log formats; new tokens are trailing-only. Require parser unit
tests covering old-runtime/new-IDE and new-runtime/old-IDE combos.
(4) INFERENCE PARITY — stability inference changes must mirror
stability-compiler's StabilityAnalyzerTransformer (and KNOWN_STABLE_TYPES sets must
stay in sync).
(5) PSI MUTATIONS — quick fixes must revalidate SmartPsiElementPointers, run inside
WriteCommandAction, and be conservative: when safety cannot be proven statically
(e.g. remember-hoisting), prefer not offering the fix over corrupting user code.
(6) plugin.xml — new services/actions/extensions must be registered consistently with
the existing patterns; tool-window tabs need disposers for background tasks.
# ===== compiler-tests: compiler test framework =====
- path: "compiler-tests/src/test/**"
instructions: >-
Kotlin compiler-test-framework suite. The .kt files under src/test/data are TEST
SOURCES (review them); the .txt goldens and generated JUnit classes are excluded from
review and must be produced by `generateTests` / `-Pupdate.test.data`, never
hand-edited. New compiler behavior (especially anything gated by a plugin option)
needs a directive-driven test (see StabilityTestDirectives) covering both the positive
case and the skip/exclusion matrix.
# ===== sample app =====
- path: "app/**"
instructions: >-
Sample/integration app only — not a production codebase. Composables here often
INTENTIONALLY demonstrate unstable patterns (var data classes, mutable collections,
@TraceRecomposition scenarios); do not suggest "fixing" intentional instability
examples. Focus on whether the sample still exercises the plugin end-to-end and on
build-script correctness. Note: app/build.gradle.kts resolves the published Gradle
plugin via gradle/libs.versions.toml, so DSL used here must exist in the version CI
publishes to Maven Local.
- path: "app-model/**"
instructions: >-
Tiny sample model module shared with the app; review only for build correctness.
# ===== build logic & versions =====
- path: "**/*.gradle.kts"
instructions: >-
Check plugin/dependency declarations go through gradle/libs.versions.toml, no
hardcoded credentials or plaintext secrets, and publishing/signing config keeps the
`-PRELEASE_SIGNING_ENABLED=false` local-development path working.
- path: "gradle/libs.versions.toml"
instructions: >-
The Kotlin version is load-bearing: the compiler plugin requires consumers to use the
EXACT same Kotlin version, so a Kotlin bump implies compiler-API review across
stability-compiler, a version-map update in README/docs, and usually a library version
bump. The compose-stability-analyzer version here is what the sample app resolves —
it must stay consistent with gradle.properties VERSION_NAME and the Gradle plugin's
VERSION constant.
- path: "build-logic/**"
instructions: >-
Shared build conventions, applied by every module as the
`compose-stability.conventions` plugin. Changes here fan out to every module; check for
configuration-time side effects and Gradle 9 compatibility. This is an included build
rather than buildSrc so its dependencies stay isolated — adding the Kotlin Gradle plugin
to a buildSrc classpath breaks the main build's version-carrying plugin aliases. Cross-project
access (rootProject, allprojects, subprojects) must not come back: it breaks Isolated
Projects, which is why this build exists (#107).
# ===== CI =====
- path: ".github/workflows/**"
instructions: >-
CI invariants: any job whose Gradle invocation configures :app needs the
"publish Gradle plugin to Maven Local" bootstrap step first (the sample app may use
plugin DSL newer than the latest Maven Central release); targeted single-module tasks
rely on configuration-on-demand to avoid configuring :app. The IDE plugin builds in a
SEPARATE Gradle invocation from compose-stability-analyzer-idea/ and needs the runtime
published to Maven Local first. Flag action version downgrades and any new step that
could leak secrets into logs.
# ===== docs =====
- path: "{README.md,docs/**}"
instructions: >-
User-facing documentation. Verify code snippets compile against the CURRENT DSL/API
(extension names, annotation parameters, task names), log-format examples match the
actual logger output, and the Kotlin version-mapping table stays consistent with
gradle/libs.versions.toml. Do not nitpick prose style.
# ── Static analysis tools ────────────────────────────────────────────────────
tools:
# Style/formatting is owned by Spotless in CI; keep style linters off to avoid
# duplicate noise.
detekt:
enabled: false
markdownlint:
enabled: false
# Secrets must never land in a public repo.
gitleaks:
enabled: true
# Workflow files are part of the release path; lint them.
actionlint:
enabled: true
yamllint:
enabled: true
chat:
auto_reply: true