Emit completion probes
Completion probes let an incomplete trailing dot produce rust-analyzer method completion inside an attribute token tree. Use them only when the macro emits the marker after a real typed receiver.
Handle a trailing dot
With the default options, Root::<_>.first(1). parses as a chain whose terminal
marker is raCompletionMarker:
use attribute_dsl::AttributeChain;
use quote::quote;
let chain: AttributeChain = syn::parse_str("Root::<_>.first(1).")?;
assert!(chain.has_completion_probe());
let completion = chain
.completion_marker()
.map(|marker| quote! { .#marker })
.unwrap_or_default();
Ok::<(), syn::Error>(())
Append completion after the application-owned constructor and parsed calls.
At that position, the missing marker method gives rust-analyzer a typed
receiver and allows it to offer the receiver’s methods at the original dot.
The explicit terminal syntax Root::<_>.raCompletionMarker represents the same
completion state.
Configure the marker
Use one stable Rust identifier when the consumer needs a custom marker:
use attribute_dsl::{AttributeChain, ChainParseOptions};
use quote::quote;
let options = ChainParseOptions::new().completion_marker("completeHere");
let chain = AttributeChain::parse_tokens_with_options(
quote!(Root::<_>.first(1).),
&options,
)?;
assert_eq!(
chain
.completion_marker()
.expect("the input ends with a probe")
.to_string(),
"completeHere"
);
Ok::<(), syn::Error>(())
An invalid identifier produces a syn::Error when trailing-dot recovery needs
to emit it. Custom ChainParseOptions apply to direct AttributeChain parsing;
the Parse implementations for entries, lists, and groups use the defaults.
Reject probe syntax
Disable completion probes when the macro accepts only complete chains or cannot emit a typed receiver:
use attribute_dsl::{AttributeChain, ChainParseOptions, CompletionProbeParsing};
use quote::quote;
let options = ChainParseOptions::new()
.allow_completion_probe(CompletionProbeParsing::Disabled);
let result = AttributeChain::parse_tokens_with_options(
quote!(Root::<_>.first(1).),
&options,
);
assert!(result.is_err());
Disabling probes rejects both trailing-dot recovery and an explicit terminal completion marker.
Preserve later list entries
Default completion recovery stops before a comma in ChainList, so later
entries remain available while one entry is incomplete:
use attribute_dsl::ChainList;
let list: ChainList = syn::parse_str(
"first = Root::<_>., second = Other::<String>",
)?;
assert!(list.entries()[0].chain().has_completion_probe());
assert_eq!(list.entries().len(), 2);
Ok::<(), syn::Error>(())
If parsing succeeds but rust-analyzer offers no methods, inspect the generated expression. The constructor and all preceding calls must resolve to the desired receiver type before the marker access.