You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,7 +27,7 @@ If you're already familiar with LSP, `crates/djls-server/src/server.rs` is a goo
27
27
28
28
If you want to understand how templates get parsed, start in `crates/djls-templates/src/` — the lexer and a hand-written recursive descent parser live there.
29
29
30
-
If you're curious about how the server validates tags without a Django runtime, look at `crates/djls-project/src/specs/analysis/` — it extracts validation rules from Python templatetag source purely through static analysis. If anyone's tried this before, they and their project didn't make it out with their sanity intact because I've never come across one (and who says I'll make it out with mine?). It's early and rough, but it's one of the more interesting parts of the project.
30
+
If you're curious about how the server validates tags without a Django runtime, look at `crates/djls-project/src/templates/tags/analysis/` — it extracts validation rules from Python templatetag source purely through static analysis. If anyone's tried this before, they and their project didn't make it out with their sanity intact because I've never come across one (and who says I'll make it out with mine?). It's early and rough, but it's one of the more interesting parts of the project.
31
31
32
32
If you're interested in how parsing, extraction, and project knowledge come together to give templates *meaning*, start with `crates/djls-semantic/src/lib.rs` — that's where "is this tag valid here?" actually gets answered.
33
33
@@ -62,7 +62,7 @@ This crate should stay boring. It wires traits to concrete state and handles loc
62
62
63
63
### `crates/djls-project`
64
64
65
-
The project model. This crate owns mechanical facts about a Django project: the `Project` Salsa input, Python interpreter and search-path discovery, module resolution, Django settings extraction, template directories, template libraries, discovered template files, template origins/resolution, Python spec extraction, model graph extraction, and project refresh. It owns two tiers of source recognizers: pure recognizers in `extraction/`for Django settings values and template tag registrations, and Salsa-assisted recognizers in `specs/` for tag rules, block specs, filter arities, and Django model graphs.
65
+
The project model. This crate owns mechanical facts about a Django project: the `Project` Salsa input, Python interpreter and search-path discovery, module resolution, Django settings extraction, template directories, template libraries, discovered template files, template origins/resolution, template tag/filter extraction, model graph extraction, and project refresh. Its internals are organized by Django domain: `settings/`handles settings-source extraction and source resolution, `templates/` handles template origins, directories, libraries, registrations, tag rules, filter arities, and symbols, and `models/` handles Django model graph extraction.
66
66
67
67
`djls-project` depends on `djls-source` for filesystem/source access, but it does not depend on `djls-semantic`. That one-way boundary lets semantic analysis consume observed source facts without project discovery needing to know about template validation, scoping, or diagnostics.
68
68
@@ -100,7 +100,7 @@ This crate also owns:
100
100
101
101
**Architecture Invariant:** extraction currently only captures constraints on *static template syntax* — argument counts and literal keyword positions knowable at parse time. Many templatetag functions also validate *runtime values* (type checks, truthiness checks on resolved variables), but those guards depend on what template variables resolve to during rendering, which the server cannot currently determine. If type inference is added in the future ([#424](https://github.com/joshuadavidthomas/django-language-server/issues/424)), some of these runtime guards may become statically evaluable — possibly as a separate analysis layer, or as an extension of the extraction pipeline itself.
102
102
103
-
Project configuration, Python environment discovery, module resolution, and Python spec extraction live in `crates/djls-project/`. `Project` is a Salsa input holding the project root, interpreter path, Django settings module, resolver-owned `SearchPaths`, and manual tag-spec configuration. `djls-project` also owns the `TemplateLibraries` type that holds derived template tag library knowledge from Django settings, source files, and installed packages. Imperative refresh functions there synchronize external project state into Salsa inputs; tracked semantic queries then fuse those observed facts into validation data and other semantic facts.
103
+
Project configuration, Python environment discovery, module resolution, and source-derived Django facts live in `crates/djls-project/`. `Project` is a Salsa input holding the project root, interpreter path, Django settings module, resolver-owned `SearchPaths`, and manual tag-spec configuration. `djls-project` also owns the `TemplateLibraries` type that holds derived template tag library knowledge from Django settings, source files, and installed packages. Imperative refresh functions there synchronize external project state into Salsa inputs; tracked semantic queries then fuse those observed facts into validation data and other semantic facts.
104
104
105
105
### `crates/djls-ide`
106
106
@@ -158,7 +158,7 @@ Project refresh starts from the configured Django settings module. `djls-project
158
158
1. The `Project` input stores the project root, interpreter path, Django settings module, search paths, and manual tag-spec configuration.
159
159
2. Template directories come from the static settings projection and are exposed as tracked project queries.
160
160
3. Template libraries come from three source-derived places: configured `OPTIONS["libraries"]`, configured/default `OPTIONS["builtins"]`, and `templatetags` packages under installed apps.
161
-
4. Symbols for those libraries are collected from Python source with the registration scanner in `djls-project::extraction`; `djls-project::specs` reuses the same registration facts to extract validation rules and model graphs.
161
+
4. Symbols for those libraries are collected from Python source with the registration scanner in `djls-project::templates::registrations`; `djls-project::templates::{tags,filters}` reuse the same registration facts to extract validation rules and filter arities, while `djls-project::models` extracts Django model graphs.
162
162
5. Search-path roots for installed packages remain high-durability source roots, so package files are reread when refresh detects that external data changed.
163
163
164
164
Startup is now configuration read plus project refresh. There is no embedded inspector zipapp, no `django.setup()`, and no template-library disk cache in the server path.
Observed source facts and lookup facts — including Python source facts and **Template Resolution** — belong to `djls-project`; project meaning — fusion, validity, availability, diagnostics, and template-domain relationships — belongs to `djls-semantic`. Only `djls-project` parses Python source.
38
+
Observed source facts and lookup facts — including Python source facts and **Template Resolution** — belong to `djls-project`; project meaning — fusion, validity, availability, diagnostics, and template-domain relationships — belongs to `djls-semantic`. Only `djls-project` parses Python source. Inside `djls-project`, code is organized by Django domain (`settings`, `templates`, `models`) rather than by generic fact/extraction buckets.
39
39
_Avoid_: classifying ownership by whether a type's name sounds semantic
0 commit comments