Skip to content

feat(wdl-analysis)!: incremental analysis - #1101

Open
Serial-ATA wants to merge 24 commits into
stjude-rust-labs:mainfrom
Serial-ATA:incremental-analysis
Open

feat(wdl-analysis)!: incremental analysis#1101
Serial-ATA wants to merge 24 commits into
stjude-rust-labs:mainfrom
Serial-ATA:incremental-analysis

Conversation

@Serial-ATA

@Serial-ATA Serial-ATA commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Previously, any analysis request on a document would:

  1. Start from scratch
  2. Unconditionally invalidate all dependents

That made working with the LSP in large workspaces heavier than necessary.

This adds a new per-document AnalysisCache that gets populated with all items and a graph of their dependencies on the first pass, then incrementally edited on any later analysis requests.

The cache works off two layers of hashes: SignatureHash (name+inputs+outputs) and BodyHash (any body statements)

In the local document, a difference in either hash will mark the item as dirty. For imports, only SignatureHash differences are significant.

For example:

# greet.wdl
version 1.3

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    output {
        String greeting = read_string(stdout())
    }
}

# main.wdl
version 1.3

import "greet.wdl"

# `do_say_hello` depends on the "greet.wdl" import
workflow do_say_hello {
    call greet.say_hello { name = "John" }
}

Changing the signature of greet.say_hello would invalidate:

  • greet.say_hello
  • The "greet.wdl" import
  • main.do_say_hello

However, changing the body of greet.say_hello will only ever invalidate greet.say_hello.

Note that this is only incremental analysis. Each analysis request will still do a full validation pass.

Before submitting this PR, please make sure:

For external contributors:

  • You have read the contributing guide in its entirety.
  • You have not used AI on any parts of this pull request.
  • You have added a few sentences describing the PR here.
  • Your code builds clean without any errors or warnings.

For all contributors:

  • You have added tests (when appropriate).
  • You have added an entry in the CHANGELOG (when appropriate).
  • You have updated the README or other documentation to account for these changes (when appropriate).
  • You have made a PR to the next branch in the sprocket.bio repository (when appropriate).

For PRs containing lint rule changes:

  • You have updated any and all effected entries within RULES.md.
  • You have added a test case in crates/wdl-lint/tests/lints that covers every
    possible diagnostic emitted for the rule within the file where the rule
    is implemented.

@Serial-ATA
Serial-ATA force-pushed the incremental-analysis branch from 2f7be45 to ae068c5 Compare August 10, 2026 17:23
@Serial-ATA
Serial-ATA force-pushed the incremental-analysis branch 9 times, most recently from 3125f05 to 57c38c9 Compare August 13, 2026 17:45
@Serial-ATA
Serial-ATA marked this pull request as ready for review August 13, 2026 17:58
@Serial-ATA
Serial-ATA requested a review from a team as a code owner August 13, 2026 17:58
@Serial-ATA
Serial-ATA requested review from adthrasher and claymcleod and removed request for adthrasher August 13, 2026 17:58
@Serial-ATA
Serial-ATA force-pushed the incremental-analysis branch 3 times, most recently from 27fae76 to a7c471b Compare August 21, 2026 16:27
Previously, any analysis request on a document would:

1. Start from scratch
2. Unconditionally invalidate all dependents

That made working with the LSP in large workspaces heavier than necessary.

This adds a new per-document `AnalysisCache` that gets populated with all items and a graph of their dependencies on the first pass, then incrementally edited on any later analysis requests.

The cache works off two layers of hashes: `SignatureHash` (name+inputs+outputs) and `BodyHash` (any body statements)

In the local document, a difference in either hash will mark the item as dirty. For imports, only `SignatureHash` differences are significant.

For example:

```wdl
# greet.wdl
version 1.3

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    output {
        String greeting = read_string(stdout())
    }
}

# main.wdl
version 1.3

import "greet.wdl"

# `do_say_hello` depends on the "greet.wdl" import
workflow do_say_hello {
    call greet.say_hello { name = "John" }
}
```

Changing the signature of `greet.say_hello` would invalidate:

* `greet.say_hello`
* The `"greet.wdl"` import
* `main.do_say_hello`

However, changing the _body_ of `greet.say_hello` will only ever invalidate `greet.say_hello`.
@Serial-ATA
Serial-ATA force-pushed the incremental-analysis branch from a7c471b to 427b36e Compare August 21, 2026 16:36

@claymcleod claymcleod left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing I would most like to see added is a test that analyses a fixture cold, applies an edit sequence, and then asserts the result matches a fresh analysis of the same final text, because every defect I have commented on would have been caught by one and without it the design stays one unhashed field away from silent staleness. This also needs a rebase before it can land, since main has rewritten except_directive_valid.rs in the meantime.

Comment thread crates/wdl-analysis/src/handlers/common/docs.rs Outdated
Comment thread crates/wdl-analysis/src/graph.rs Outdated
Comment thread crates/wdl-analysis/src/document/v1.rs Outdated
Comment thread crates/wdl-analysis/src/document/cache.rs
Comment thread crates/wdl-analysis/src/document/cache/hash.rs
Comment thread crates/wdl-analysis/src/document/cache.rs
Comment thread crates/wdl-analysis/src/document/cache.rs Outdated
Comment thread crates/wdl-grammar/src/diagnostic.rs
Comment thread crates/wdl-analysis/src/document/v1.rs Outdated
Comment thread crates/wdl-analysis/src/document/v1.rs Outdated
# Conflicts:
#	crates/wdl-analysis/CHANGELOG.md
#	crates/wdl-analysis/src/validation.rs
#	crates/wdl-analysis/src/validation/known_rules.rs
#	crates/wdl-lint/src/rules/except_directive_valid.rs
@Serial-ATA Serial-ATA added the S-awaiting-revisions PR is awaiting revisions from the contributor. label Aug 25, 2026
# Conflicts:
#	crates/wdl-analysis/src/document.rs
#	crates/wdl-analysis/src/document/v1.rs
#	crates/wdl-engine/src/eval/v1/task.rs
@Serial-ATA
Serial-ATA force-pushed the incremental-analysis branch from ef33052 to be7870b Compare August 31, 2026 15:42
# Conflicts:
#	crates/wdl-analysis/src/document.rs
#	crates/wdl-analysis/src/document/v1.rs
#	crates/wdl-analysis/src/handlers/goto_definition.rs
#	crates/wdl-analysis/src/handlers/hover.rs
Since `{Struct,Enum}Ref` carry a clone of their definitions, but not the rest of the document, the LSP doc providers were returning nothing for their doc comments
@claymcleod claymcleod added S-awaiting-pass-CI PR is awaiting CI to pass. and removed S-awaiting-revisions PR is awaiting revisions from the contributor. labels Aug 31, 2026
No longer sharing the `analysis_diagnostics` from the document
@Serial-ATA Serial-ATA added S-awaiting-review PR is awaiting a review from a maintainer. and removed S-awaiting-pass-CI PR is awaiting CI to pass. labels Sep 1, 2026
@claymcleod claymcleod added S-awaiting-revisions PR is awaiting revisions from the contributor. and removed S-awaiting-review PR is awaiting a review from a maintainer. labels Sep 7, 2026
@Serial-ATA Serial-ATA added S-awaiting-review PR is awaiting a review from a maintainer. and removed S-awaiting-revisions PR is awaiting revisions from the contributor. labels Sep 7, 2026
# Conflicts:
#	crates/wdl-analysis/CHANGELOG.md
#	crates/wdl-analysis/src/document.rs
# Conflicts:
#	crates/wdl-analysis/src/graph.rs
#	crates/wdl-lsp/tests/requests/code_lens.rs
@peterhuene
peterhuene self-requested a review September 10, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-awaiting-review PR is awaiting a review from a maintainer.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants