Problem: a bare call in a Dart file resolved against every imported
library. An `import 'a.dart' as p;` still bound `foo()` to a.dart's foo,
`hide` and `show` combinators were ignored, and a name re-exported through
a barrel library (`export 'impl.dart';`) never resolved.
Fix: record each Dart import/export directive with its `as` prefix and
show/hide lists. A bare name resolves only in libraries imported without a
prefix whose combinators let it through, plus that library's own exports
that also let it through (one level).
Test: tests/dart_imports.rs covers a prefixed, a hiding, a showing and a
barrelled import; it failed on the prefixed case before this change.
When several files declare the same type leaf name, rust_method keeps
only the impls of the type a call site means, asking each impl's file
which `Foo` it means. An impl in a third file written as
`impl crate:🅰️:Foo` resolved nothing (that file has no `Foo`
declaration or `use` binding), so its methods were dropped and
`x.run()` on an `a::Foo` read "member-not-found". It resolved before #5.
The extractor now records the impl's type path when it is written as
one (`impl_type_path`, generic arguments removed), the method index
keeps it, and the impl filter resolves that path to its declaring file
before falling back to the file's own view of the leaf name. Glob
imports (`use super::*`) are still not expanded; such an impl stays
unresolved rather than guessed.
Test: with `Foo` declared in a.rs and c.rs and `impl crate:🅰️:Foo` in
ext.rs, `x.run()` on `crate:🅰️:Foo` resolves to ext.rs's `run`; it
failed before this change.
imported_paths found the file node with a linear scan of all nodes and
then filtered all edges, for every Python/Dart file it built a set for:
O(files x (nodes + edges)) during resolution, about 10^10 comparisons
for 10k files and a million edges.
Imports edges are now indexed by source file on first use and the file
node is looked up by its stable id, as resolve_import already does. The
index is complete when first built: resolve_relationships resolves
every import before any call. Output is unchanged (all 124 tests pass).
Since #5 Python calls resolve only through import edges, but the
lexical importer could not produce those edges for the common forms:
- `from .util import helper` never matched (the regex needed a leading
letter), so the call went unresolved;
- `from pkg import f` looked up the stem "pkg" instead of
pkg/__init__.py;
- `from x.common import f` failed when y/common.py also existed, and
`from other.common import f` (a module the repository does not have)
resolved to y/common.py by basename.
Imports now resolve Python-specifically: leading dots are relative to
the importing package, and a dotted name maps to `a/b.py` or
`a/b/__init__.py` from the repository root or `src/`. Only a
single-component name (`import foo`) may still fall back to a unique
module basename; a dotted name never does. `from . import x` stays
unresolved (the module is in the import list, not the name).
Tests (both failed before): relative, package and duplicate-stem imports
resolve their calls to pkg/util.py, pkg/__init__.py and x/common.py;
an unknown dotted module does not bind to y/common.py.
Swift ran through the C-style lexical patterns, which never recognize
`func`. On a small file (`func realTarget()`, `func ghost()`, a class
method `caller` that calls `realTarget()` below a `/* ghost() */`
comment) the preview reported:
a.swift -> ghost (a.swift:2 declaration, a.swift:5 in a comment)
a.swift -> caller (its declaration line)
a.swift -> realTarget (its declaration line)
and missed the real call. Now:
caller -> realTarget (a.swift:7)
- Swift gets its own patterns: `func` declarations (with attributes and
modifiers), class/struct/enum/protocol/actor/extension declarations
(`class func` / `class var` are members, not classes), and imports.
- Block comments are masked across lines, nested as Swift allows, and a
`/*` inside a string literal does not open one. The masker is salvaged
from the unmerged language-parity branch (543bafc).
- Calls are attributed to their enclosing function through the existing
brace-scoped scopes, now that functions are recognized.
Test: tests/swift_preview.rs (functions and a class recognized, the call
attributed to `caller`, nothing from comments, nothing from the file
node); it failed before this change.
`check` treated any difference between stored and recomputed metrics as
a gate failure, so a model written by an older brick (without the
`metrics.resolution` field, or with an older formula) always failed,
even with every threshold met. CI checking an archived or cached model
broke on upgrade.
The gate already uses recomputed metrics, so a mismatch is now a
stderr warning. Only fields present in both copies are compared, so a
missing newer field does not count as a mismatch. Tampered metrics
still cannot pass: the existing test's recomputed cycle count fails the
gate, and it still reports "stored metrics".
Test: a freshly built model with `metrics.resolution` removed passes
`check --min-score 0`; it failed before this change.
The empty-model condition was written three times: a scan.rs
diagnostic, a helper in main.rs for `build`'s warning, and the same
helper for `check`'s failure. They could drift. model.rs now owns
`has_source_files` (and `Building::has_source_files`), used by all
three. No behaviour change; the empty-scan CLI test still passes.
Three import fixes from review of #5:
- sarif_uri_path sliced `&rest[i + 1..i + 3]` by byte index, so a `%`
followed by a multibyte character (`file:///src/%aé.c`) panicked the
whole build, and from_str_radix accepted `%+1` as byte 0x01. Escapes
are now decoded on bytes and only from two hex digits.
- Whether findings keep Fold's Symbolic lane was decided for the whole
report with all(): a merged SARIF log with one Fold run and one CodeQL
run demoted every Fold finding to Imported. The lane is now decided
per SARIF run (per report for native findings), and the diagnostic
names only the non-Fold producers.
- The rule that `..` after a symlinked directory follows the filesystem
applied only to relative paths; `/root/linkout/../src/main.rs` and its
file:// form still normalized lexically onto an in-repository file.
Absolute paths that exist now resolve through the filesystem too.
Tests (each failed before this change): percent-escape decoding without
panics, per-run lanes in a merged SARIF, and absolute/file:// paths
through a symlinked directory.