Expand description
Port of mrmans0n/compose-rules (pin: tools/sync-compose-rules.sh), its ktlint flavour
(io.nlopez.compose.rules:ktlint): the rules of ComposeRuleSetProvider (rule set compose), run natively
when a ktlint run loads that release’s JAR (-R); every other rule set JAR goes to the real ktlint jar.
Layout mirrors upstream, one Rust file per Kotlin file and one fn per Kotlin fn in the same order: core =
rules/common/.../core (util/ = core/util), rules = rules/common/.../rules, ktlint = rules/ktlint
(the KtlintRule adapter, .editorconfig properties, the *Check modules, the provider).
§Porting a rule
rules/<rule>.rs: a unit struct implementingComposeKtVisitor; messages arepub conststrings with thetrimIndent()ed text (lines joined by\n, no trailing newline).ktlint/<rule>_check.rs:pub fn <rule>_check() -> KtlintRulewith upstream’s id and properties (ComposeProperty::String(&CUSTOM_MODIFIERS), …), andpub const CHECK = Some(<rule>_check). A check that overrides a visit method to gate it (Material2Check,PreviewNamingCheck, …) is a struct holding the rule and implementingComposeKtVisitoritself, likektlint::preview_naming_check. No shared file changes:rules/mod.rs,ktlint/mod.rsand the provider already list every rule.- Goldens:
cargo test -p ktrs-compose --release --test golden(GOLDEN_FILTER=<rule-dir>), thenUPDATE_PASSING=1to ratchettests/golden-passing.txt.
§Kotlin -> Rust
- PSI is
ktrs_ast::psiover the mutable tree (its module docs have the conventions):x is KtFoo->KtFoo::is(ast, n),x as? KtFoo->KtFoo::cast(ast, n), getters dropgetand takeast; expression results are bareNodeIds.KtAnnotated/KtModifierListOwner/KtCallableDeclarationreceivers of the util extensions are bare nodes:function.isComposable->is_composable(ast, function.node()). - Visitor hooks get
ast: &mut Ast; read through it freely (&mut Astcoerces to&Ast). Collect a Kotlin sequence into aVecbefore reporting, unless a fix inside the loop edits the tree and the sequence is lazy upstream: then step acore::util::psi_elements::ChildrenByClass. emitter.report(e, msg)->emitter.report(ast, e.node(), MSG, false);report(e, msg, true).ifFix { .. }->emitter.report(ast, e.node(), MSG, true).if_fix(|| { .. })(the closure may mutateast).config.getSet(key, emptySet())->config.get_set(key, &[]); a KotlinSet<String>is aVec<String>without duplicates (insertion order). Regexes arektrs_lint::rules::internal::KotlinRegex(Java syntax,matches= full match).element.text->ast.text(n)orx.text(ast);startOffset->ast.start_offset(n);parents,parentsWithSelf,siblings(forward, withItself)->ast.parents(n),ast.parents_with_self(n),ast.siblings_with_itself(n, forward, with_itself);findAllChildrenByClass<T>()->find_all_children::<T>(ast, n)(breadth first overgetChildren(), root included).- Where ktlint 1.8.0 (Kotlin 2.2.21) and 2.0.0-ALPHA-4 (Kotlin 2.4.10) PSI differ, pass
config.embedded_kotlin()(known:quoteIfNeededon Latin-1 letters insetName,getContextParameters).
Status, the parity gate and how to bump the pin: research/27-custom-rulesets-impl.md.
Re-exports§
pub use core::compose_kt_visitor::ComposeKtVisitor;pub use ktlint::compose_rule_set_provider::compose_rule_providers;
Modules§
- core
- Port of compose-rules
rules/common/.../core: the visitor, emitter and config interfaces the rules are written against, and the shared PSI helpers. - jar
- Recognizes a compose-rules (
io.nlopez.compose.rules) ktlint JAR whose release ktrs runs natively (ktrs_compose), by its contents: theio/nlopez/compose/entries’ names, CRC-32s and sizes. - ktlint
- Port of compose-rules
rules/ktlint: theKtlintRuleadapter, its config, the.editorconfigproperties, one*Checkmodule per rule (each exportsCHECK,Noneuntil ported) and the rule set provider. - rules
- Port of compose-rules
rules/common/.../rules: one module per rule (the unported ones are empty until their port lands, so porting a rule never edits this file).
Constants§
- COMPOSE_
RULES_ VERSION - The ported release.
- NATIVE_
JARS - (release, content fingerprint) of the ktlint JARs that run natively; the fingerprint is computed by
ktrs-cli’scompose_jar.rs. Per release: the publishedktlint-compose-<release>-all.jar, and the Maven artifactsio.nlopez.compose.rules:ktlint+common-ktlintmerged (as the ktlint Gradle plugin passes them; same bytecode, the-allJAR only relocates kotlin-compilerpsiUtilcalls: research/29).