Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion concepts/analyzers/rust.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,74 @@ definition selectors. Inspect any rule and its effective settings with:
fensu rule FPRSS010 --target rust
```

## Custom Rust rules

Custom Rust rules are authored in Python but run over immutable, serialized facts
owned by Fensu. Declare Rust applicability explicitly and use a typed `File` or
`Project` subject; raw `syn` and Cargo metadata objects are never exposed.

```python
from fensu import (
AnalyzerId,
Family,
Fault,
File,
RuleContext,
RustItemKind,
rule,
)


@rule(
code="XRS001",
family=Family.CUSTOM,
slug="legacy-service",
message="legacy service declaration",
analyzers=(AnalyzerId.RUST,),
cacheable=True,
)
def legacy_service(*, file: File, ctx: RuleContext) -> list[Fault]:
facts = ctx.rust.file(file)
if facts is None:
return []
return [
ctx.fault_at(location=item.location)
for item in facts.items
if item.kind is RustItemKind.STRUCT and item.name == "LegacyService"
]
```

Configure it through the standard custom-rule and selector keys:

```toml
[targets.rust]
analyzer = "rust"
roots = ["src"]
tests = []
tooling = []
rule_packs = ["rust"]
rule_modules = ["rules.rust"]
select = ["FPRS", "XRS001"]
```

`ctx.rust` includes Cargo workspace crates, targets and dependencies; selected Rust
files and module identities; declarations for functions, structs, enums, traits,
implementations, visibility and derives; parse failures; and statically provable
`use` targets. Resolution remains explicit when a target is external, crate-local
but not attributable to one file, or unresolved.

Project rules use `Project` and run once for the Rust target. They can combine
`ctx.project.tree` with `ctx.rust.crates` for workspace-wide dependency or layout
policy. Typed `rule_options`, warning tiers, selector ignores, path ignores and exact
exceptions use the same configuration as built-in rules.

Fensu starts the Python host only when configured custom-rule sources have an active
`X` selector that is not wholly covered by an ignore prefix. A Rust target with only
native selectors remains native and Python-free. Cacheable custom rules retain
separate file or project subjects and replay the tree or Rust-fact queries actually
observed by each invocation. Fact schema, parser contract, runtime, rule package and
typed options all participate in cache identity.

## Rule options

Adjust a rule under the target's standard `rule_options` table:
Expand Down Expand Up @@ -144,7 +212,8 @@ layout checks for explicit subtrees while preserving per-file checks.
## Cargo metadata and caching

Rust sources, Cargo manifests, an existing lockfile, and target configuration are
cache inputs. Fensu uses locked dependency resolution when `Cargo.lock` exists.
cache inputs. Selected custom-rule packages are cache inputs as well. Fensu uses
locked dependency resolution when `Cargo.lock` exists.
For a lock-free workspace, it reads declared dependencies without creating a
lockfile.

Expand Down
39 changes: 39 additions & 0 deletions reference/rule-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,28 @@ dynamic imports are not represented.
`ImportResolution`, and optional target node. Graph identities include analyzer and
source-kind ownership so they remain safe as additional analyzers gain graphs.

## `ctx.rust`

For Rust targets, a versioned immutable workspace fact view transferred from the
native analyzer. It contains no `syn` or Cargo metadata objects.

| Call | Returns | Purpose |
| --- | --- | --- |
| `crates` | `tuple[RustCrateFact, ...]` | All Cargo workspace package, target and dependency identities. |
| `files` | `tuple[RustFileFacts, ...]` | All selected Rust file, module, source, item and `use` facts. |
| `crate(identity)` | `RustCrateFact \| None` | One focused crate lookup by stable workspace identity. |
| `file(file_or_path)` | `RustFileFacts \| None` | One focused file lookup by `File` or `ProjectPath`. |

`RustItemFact` uses `RustItemKind` and `RustVisibility`, preserves derives and
implementation targets, and carries a stable `SourceLocation`. `RustUseFact`
preserves authored parts, source and target modules, optional target file and crate,
and a `RustUseResolution` of `RESOLVED`, `CRATE`, `EXTERNAL`, or `UNRESOLVED`.
`RustFileFacts.parse_error` remains explicit when source cannot be parsed.

Each broad or focused call records its answer for subject-aware cache replay. Use a
focused `file()` or `crate()` lookup when unrelated source or Cargo changes should
not invalidate a cached result.

## `ctx.text`, `ctx.syntax`, `ctx.relations`

Source text, opaque syntax identities, and syntax relationships for the current
Expand All @@ -137,6 +159,11 @@ file.
The zone protocols are `FactAnalysis`, `ProjectAnalysis`, `TextAnalysis`,
`SyntaxAnalysis`, and `RelationAnalysis`, all exported from `fensu`.

The table above describes the Python analysis zones. Serialized Rust rules use
`ctx.rust`, `ctx.project.tree`, `ctx.source`, and stable locations. `ctx.graph`,
`ctx.syntax`, and `ctx.relations` are unavailable because parser implementation
objects are not part of the Rust authoring contract.

## Fault construction

Construct diagnostics through the context so the rule's code, and optionally its
Expand Down Expand Up @@ -289,6 +316,18 @@ are frozen dataclasses; inspect exact fields with your editor's type information
| `ImportEdge` | Authored import plus explicit resolution result. |
| `ImportCycle` | One statically proven strongly connected component. |

**Rust facts**

| Model | Describes |
| --- | --- |
| `RustWorkspaceFacts` | Versioned workspace crates and selected Rust files. |
| `RustCrateFact` | Cargo package identity, manifest, library, targets and dependencies. |
| `RustTargetFact` | Stable Cargo target identity, kinds, source root and entry path. |
| `RustDependencyFact` | Cargo package/source name, dependency kinds and optional local crate. |
| `RustFileFacts` | Source, module identity, parse result, items and authored uses. |
| `RustItemFact` | Function, struct, enum, trait, implementation or module declaration. |
| `RustUseFact` | Authored `use` path and explicit resolution evidence. |

**Test facts**

| Model | Describes |
Expand Down
Loading