attribute-dsl 0.2.0

Shared parser helpers for Rust attribute DSLs built from paths and dot-call chains.
Documentation
# 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`:

```rust,ignore
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:

```rust,ignore
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:

```rust,ignore
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:

```rust,ignore
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.