61 lines
8.6 KiB
Markdown
61 lines
8.6 KiB
Markdown
# Modular source core candidate
|
|
|
|
Status: pure source3 subsystem implemented and tested. This is not native project-editor, filesystem-save, REST-bundle, or final human-authoring acceptance. Includes retain the current declaration syntax; a separate usability review is evaluating more concise nested authoring.
|
|
|
|
## Delivered
|
|
|
|
- `oa_core::source_project`: serde `SourceBundle { entry, files }`, `ProjectLimits`, `CompiledSourceProject`, located diagnostics and derived `SourceIndex`.
|
|
- Shared source3 declaration parser/resolver and typed declaration writer in `language.rs`. Flat APIs and V1/V2 migration remain supported. Flat parsing explicitly rejects includes instead of reading a filesystem.
|
|
- Global forward references and duplicate alias/UUID detection across files, including project and placement identities. Errors refer to real file offsets; duplicates include the previous location. Engineering warning positions index each file once.
|
|
- Portable relative includes, root containment, canonical map keys, case collisions, repeated includes, cycles, missing/unreachable files, duplicate JSON file keys and aggregate admission checks.
|
|
- Generated identities are inserted into their original headers. Returned diagnostics/index address the resulting stabilized buffers. Caller drafts are never mutated.
|
|
- Canonical modules follow layers, work roots, behavior contexts and diagrams. Ports follow their owners; placements follow diagrams; relations follow their sources. Existing ownership is retained during model updates. Huge sets of independent roots consolidate by category rather than produce thousands of files.
|
|
- Model updates preserve authored comments, whitespace and surviving fields, change header/value tokens and alias uses, add new owner/root declarations and includes, and retain empty files after deletion. Every update recompiles and checks exact semantic equality before return.
|
|
|
|
## Consumer interface
|
|
|
|
```rust
|
|
use oa_core::source_project::{compile_bundle, format_bundle, update_bundle, ProjectLimits};
|
|
|
|
let compiled = compile_bundle(&draft_bundle, ProjectLimits::default())?;
|
|
// Adopt compiled.decoded.project as one Session change only after success.
|
|
// Retain compiled.bundle, not the original draft with omitted UUID clauses.
|
|
let updated = update_bundle(&compiled, &edited_project, ProjectLimits::default())?;
|
|
let canonical_export = format_bundle(&edited_project);
|
|
```
|
|
|
|
`ProjectLimits` contains file/depth/edge budgets and the existing `language::ParseLimits` as `model`. Defaults: 256 files, depth 32, 1,024 include edges, 64 MiB combined UTF-8 text; other semantic counts are caller policy. A server should substitute its current aggregate model budgets and retain its encoded request cap. Input and stabilized output must both fit the supplied limits.
|
|
|
|
The entry must be a root-level filename, normally `project.arcadia`; fragments inherit source3 and have no project/version wrapper. Paths are relative to the including file, normalized within the virtual root. `resolve_include(from, include)` exposes the same pure path rule. It checks the containing path too. All actual includes must be supplied explicitly in `files`; no host filesystem or network is consulted.
|
|
|
|
For native discovery, `inspect_includes(path, source, is_entry, limits)` uses the shared strict parser before referenced files are available. It returns normalized targets and exact directive spans, excluding comments and strings. A syntax failure returns located diagnostics and no partial include list; retain the draft and surface that error rather than scanning arbitrary strings. Cross-file resolution/engineering validation remain in `compile_bundle`. Inspection checks one document's syntax/bytes/records/include edges; the loader must enforce aggregate admission and physical ownership while traversing.
|
|
|
|
`SourceIndex.declarations` maps UUID to file and complete declaration span, including the project header under its UUID. `fields` maps `(UUID, top_level_field)` to its complete value span. `includes` holds each directive location and normalized target. Project header, body interior, and optional complete description-field spans support targeted metadata/include edits. Errors use original draft coordinates; successful compilation returns coordinates in stabilized text.
|
|
|
|
`CompiledSourceProject.decoded.migration` is `None` for source3 bundles. Legacy import remains `language::parse_with_report` / `persistence::decode_with_report`; retain that report in the importing UI, then explicitly export the migrated model into source3 modules. Do not independently migrate fragments or fabricate a migration report during subsequent source3 compilation.
|
|
|
|
## Comment-preserving update policy
|
|
|
|
The earlier whole-declaration canonicalization limitation is fixed. `update_bundle` derives language-specific editing positions from the existing validated AST and tokenizer. The shared V2 AST and migration behavior are unchanged; no alternate grammar, persistent syntax model or generic CST framework was added.
|
|
|
|
- Old/new canonical typed values identify semantic changes; surviving authored fields retain their exact text, field order, comments, omitted defaults and escape/number spelling. Header and scalar changes replace only the affected tokens. Reference aliases change without removing comments between `@` and the alias.
|
|
- New fields insert at the owning record using existing indentation/line endings. Omitted defaults stay omitted unless their semantic value changes. Constructor tag changes preserve shared nested fields.
|
|
- Removing a field, constructor or declaration erases its significant syntax tokens, retaining comments/whitespace as annotations in the parent record or file. Complete value-shape replacements retain the old value's comments next to the replacement. The updater does not guess how orphaned engineering notes should be reworded.
|
|
- Lists match unique referenced UUIDs, message-value `field` references, binding `referenced` identities, or literal values. Retained entries move with their inter-separator trivia; removed-entry comments remain in the enclosing list. Other/duplicate-key lists use positions. Trivia after a comma belongs to the next entry; trivia before a comma belongs to the previous entry. Separators are emitted before trailing line comments to keep syntax valid.
|
|
- Declaration identity is UUID-based; no alias/name heuristic silently treats a new UUID as an old record. Explicit UUID replacement removes/creates records while retaining removed-record comments as file annotations. Existing UUIDs and file ownership remain unchanged for retained records.
|
|
- `format_bundle` remains an explicit canonical export, not the update/save path. Keep compiled workspace snapshots for undo/redo; model-only undo cannot recover prior omissions or authored layout choices.
|
|
|
|
This production core correction does not itself establish complete human-authoring, project-editor or native save acceptance. Experimental nested grammar remains separate and unintegrated.
|
|
|
|
## Verification
|
|
|
|
- `cargo test -p oa-core`: **160 tests passed**, including 30 source-project tests.
|
|
- `cargo clippy -p oa-core --all-targets -- -D warnings`: passed.
|
|
- Owned Rust files formatted with `rustfmt --edition 2024 --config skip_children=true`.
|
|
|
|
The source-project tests cover cross-file typed-port/exchange references, Unicode syntax/structural diagnostics, duplicate declarations with related locations, include diamonds/cycles/missing/unreachable files, portable paths, aggregate byte/object/record/step/file/depth/edge budgets, JSON duplicate keys, UUID stabilization and adjacent tokens, declaration relocation, alias propagation, owner inheritance, new module includes, retained empty files, stale/invalid update rejection, canonical case collisions and bounded large-root output. Full demo equality covers behavior, artifacts, trace baselines and placements. Moving a placement changes only its owning view document.
|
|
|
|
Ten additional regressions verify exact CRLF/name/guard/project-metadata updates, Unicode escape spelling and comments after `@`, omitted defaults and field insertion, kind/constructor changes with removed-field comments, scalar/record value-shape replacements, reference and literal list changes, deleted-record comments, and nested scenario message-value edits/reordering by field identity. These tests check exact unchanged bytes or the retained comment set as appropriate, plus complete model equality and source ownership.
|
|
|
|
No native CUA, editor, server, project-directory loader/save journal, port metamodel or Session changes were performed in this subsystem. Those integration milestones remain open. `docs/language.rst` sections 6.1 and 7 distinguish implemented core behavior from these pending authoring/integration requirements; the obsolete source2 grammar production is corrected to source3.
|