Skip to main content

Crate ktrs_compose

Crate ktrs_compose 

Source
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

  1. rules/<rule>.rs: a unit struct implementing ComposeKtVisitor; messages are pub const strings with the trimIndent()ed text (lines joined by \n, no trailing newline).
  2. ktlint/<rule>_check.rs: pub fn <rule>_check() -> KtlintRule with upstream’s id and properties (ComposeProperty::String(&CUSTOM_MODIFIERS), …), and pub const CHECK = Some(<rule>_check). A check that overrides a visit method to gate it (Material2Check, PreviewNamingCheck, …) is a struct holding the rule and implementing ComposeKtVisitor itself, like ktlint::preview_naming_check. No shared file changes: rules/mod.rs, ktlint/mod.rs and the provider already list every rule.
  3. Goldens: cargo test -p ktrs-compose --release --test golden (GOLDEN_FILTER=<rule-dir>), then UPDATE_PASSING=1 to ratchet tests/golden-passing.txt.

§Kotlin -> Rust

  • PSI is ktrs_ast::psi over the mutable tree (its module docs have the conventions): x is KtFoo -> KtFoo::is(ast, n), x as? KtFoo -> KtFoo::cast(ast, n), getters drop get and take ast; expression results are bare NodeIds. KtAnnotated/KtModifierListOwner/KtCallableDeclaration receivers 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 Ast coerces to &Ast). Collect a Kotlin sequence into a Vec before reporting, unless a fix inside the loop edits the tree and the sequence is lazy upstream: then step a core::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 mutate ast).
  • config.getSet(key, emptySet()) -> config.get_set(key, &[]); a Kotlin Set<String> is a Vec<String> without duplicates (insertion order). Regexes are ktrs_lint::rules::internal::KotlinRegex (Java syntax, matches = full match).
  • element.text -> ast.text(n) or x.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 over getChildren(), 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: quoteIfNeeded on Latin-1 letters in setName, 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: the io/nlopez/compose/ entries’ names, CRC-32s and sizes.
ktlint
Port of compose-rules rules/ktlint: the KtlintRule adapter, its config, the .editorconfig properties, one *Check module per rule (each exports CHECK, None until 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’s compose_jar.rs. Per release: the published ktlint-compose-<release>-all.jar, and the Maven artifacts io.nlopez.compose.rules:ktlint + common-ktlint merged (as the ktlint Gradle plugin passes them; same bytecode, the -all JAR only relocates kotlin-compiler psiUtil calls: research/29).