858 Commits
Author SHA1 Message Date
Martin Vogel fceb25d811 Merge pull request #2579 from lorenzozanee/fix/tsx-arrow-jsx-calls
fix(ts-lsp): resolve JSX calls from top-level arrow components
2026-10-20 19:39:38 +02:00
Martin Vogel 172c36191d Merge pull request #2623 from dianshu/fix/ts-bounded-lookup-main-20261013
fix(ts): bound recursive member and method lookup
2026-10-20 19:38:38 +02:00
Martin Vogel a22271570e Merge pull request #2677 from DeusData/feat/deploy-graph-gaps
feat(deploy): render Helm images, mark default-valued images, link crds and werf charts
2026-10-20 06:34:12 +02:00
Martin Vogel f0d34de56d Merge origin/main (4c80d89e) into fix/tsx-arrow-jsx-calls
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-20 04:57:39 +02:00
Martin Vogel 3867625c44 fix(ts-lsp): keep exported arrow consts out of the module lexical scope
Walking top-level arrow components also bound every exported `const`
declaration into the module root scope in pass 1. A root-scope binding
makes the JSX resolver fail closed and the exact same-module call path
skip the name, so a same-file `<Badge />` rendered from a function
component lost its CALLS edge (JSX carriers have no other resolver), and
calls such as `formatLabel()` fell back from lsp_ts_local to same_module.

Walking the arrow bodies does not need that binding, so drop it, and pin
both forms with a test that renders and calls an exported arrow const
from a function component and from an arrow component.

On excalidraw/excalidraw @ e1b7aacb the change keeps every edge it adds
over main (+270 CALLS, 0 removed; 6 more same-file JSX edges than with
the binding) and the 17 lsp_ts_local -> same_module downgrades are gone.

Also joins one declaration line that clang-format reflows.

Refs #2559

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-20 04:57:14 +02:00
Martin Vogel 4c80d89edf Merge pull request #2713 from DeusData/fix/py-namespace-effect-allowlist
fix(python): a top-level call of a harmless same-module function keeps the package namespace
2026-10-20 04:54:32 +02:00
Martin Vogel 1b2238eea8 Merge origin/main (5a4af9c4) into fix/tsx-arrow-jsx-calls
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-20 04:20:09 +02:00
Martin Vogel 5a4af9c46f Merge pull request #1913 from ilyabrykau-orca/fix/go-method-receiver-qn
fix(extract): receiver-qualify Go method QNs
2026-10-20 04:16:17 +02:00
Martin Vogel 0e4ec8018d Merge main 28a6905c into fix/ts-bounded-lookup-main-20261013
Brings the branch onto current main. The only red in the PR's CI run,
incremental_deleted_spawner_drops_its_process, was a main-side failure at
the old base 56700bdb, fixed on main by 2317c2e7.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-20 01:01:17 +02:00
Martin Vogel 8781bbd29f Merge origin/main into fix/py-namespace-effect-allowlist
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-20 00:26:27 +02:00
Martin Vogel 28a6905c07 Merge pull request #2712 from DeusData/fix/py-namespace-string-future-facts
fix(python): docstrings and __future__ imports are no namespace barriers
2026-10-20 00:25:58 +02:00
Martin Vogel cd16ef8046 Merge fix/go-weak-selector-calls (#1907, with main 32445b20) into fix/go-method-receiver-qn
Brings main 32445b20 in through the refreshed #1907. No conflicts.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 22:29:34 +02:00
Martin Vogel 6856f09705 Merge origin/main (32445b20) into fix/go-weak-selector-calls
Conflict in tests/test_pipeline.c: this branch and #2703 (on main) each
registered two Go tests at the same place in the suite list; both pairs
are kept.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 22:29:14 +02:00
Martin Vogel 170fad6b65 Merge fix/py-namespace-string-future-facts (#2712) into fix/py-namespace-effect-allowlist
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 22:26:49 +02:00
Martin Vogel 32445b2001 Merge pull request #2706 from DeusData/fix/php-trait-flatten-index
fix(php): index trait methods by receiver while flattening (#1265)
2026-10-19 22:26:45 +02:00
Martin Vogel 93724ba36b Merge main d4980ad7 into fix/py-namespace-string-future-facts
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 07:49:58 +02:00
Martin Vogel f26da1aaf2 Merge pull request #2688 from DeusData/fix/issue-1692-aspnet-routes-v2
fix(routes): extract ASP.NET Core attribute routes (#1692)
2026-10-19 07:43:12 +02:00
Martin Vogel 3c2853e338 Merge main 0f6cc06b into fix/py-namespace-string-future-facts (#2704 landed)
tests/test_pipeline.c conflict: main moved the surface codec to v3 (#2703), this branch moved the Python facts payload to v2; the codec rows carry both (surface v3, py v2), plus the stale py v1 row this branch added.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 07:21:57 +02:00
Martin Vogel 0f6cc06ba2 Merge pull request #2704 from DeusData/fix/py-namespace-reexports-v2
fix(python): resolve names re-exported through package namespaces
2026-10-19 07:20:14 +02:00
Martin Vogel 41232687dd Merge pull request #2691 from DeusData/fix/py-nested-class-qn-v3
fix(python): walk a class nested in a class under its outer class
2026-10-19 06:11:17 +02:00
Martin Vogel e9b334e7a1 Merge remote-tracking branch 'origin/main' into fix/php-trait-flatten-index
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 06:05:01 +02:00
Martin Vogel 1e644b4414 fix(python): bound the module-path scan of the __go import check
WHY: the check read an import's module path with strcspn, which runs to a NUL, but a tree-sitter source slice need not be NUL-terminated: the first segment is now found with memchr inside the slice. The leading dots move into py_ns_leading_dots; written inline, cppcheck 2.20 (the CI version) took the loop to always end at the slice length and reported three knownConditionTrueFalse findings on the branches that follow it.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:56:15 +02:00
Martin Vogel 90bb6845d6 fix(python): a top-level call of a harmless same-module function keeps the namespace
A top-level call withdrew the whole namespace (UNKNOWN, reason EFFECT): sqlalchemy's sql/__init__.py ends with __go(locals()) and lost all 108 re-exports. The call is now allowed when the callee is the latest binding of its name, a proven same-module function with no star import or unknown effect since; every argument is a safe expression or a bare locals()/globals() the module does not rebind; and the body (nested scopes included) has no global/nonlocal and never names a parameter, a function or class the module defined earlier, the module's own name, or a name that reaches a namespace (globals, vars, locals, exec, eval, setattr, delattr, __import__, sys, importlib, __name__, __dict__, __globals__, __builtins__, builtins, __self__, inspect, f_globals, f_locals, f_back, gc). Each submodule of the package the body imports becomes a package attribute and is shadowed at the call; in a plain module the imports install nothing. Every other call stays a whole-namespace effect. The function table and verdicts live in the extraction scratch; each callee is checked once.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:56:15 +02:00
Martin Vogel 7dc07d97fd refactor(php): keep the trait index in the LSP arena
The class-field pass stored the address of a stack-local index in ctx for
the duration of the pass. It was restored before returning, but the
pattern is what cppcheck's autoVariables check rejects. The index now
lives in the call's arena; on an allocation failure it stays NULL and
flattening runs the full scan, as before.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:53:24 +02:00
Martin Vogel bf56fcfd14 Merge #2704 head 67e53d0e into fix/py-namespace-string-future-facts (pick up #2697)
cbm.h conflict: #2700's cbm_import_binds_runtime_name helper and the facts version 2 comment are adjacent; both kept.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:40:35 +02:00
Martin Vogel 728bb3b822 fix(python): a star import from __future__ is a parse barrier
The grammar rejects from __future__ import * as Python does, so the file carries an error node and its whole namespace is a PARSE unknown: a stronger barrier than the UNSUPPORTED statement the previous commit guarded for. That guard could never run and is dropped; the control asserts the parse barrier the parser actually yields.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:13:48 +02:00
Martin Vogel 67e53d0ead Merge origin/main into fix/py-namespace-reexports-v2 (pick up #2697)
py_lsp.c: #2697 moved py_lookup_attribute below the C3 code (own members, C3 order, then the depth-first walk) and declares it up front; the trivial definition this branch still carried next to its module-member lookup is dropped, the module-member block is kept, and the C3 section takes main's header.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:07:32 +02:00
Martin Vogel 27c330324d Merge pull request #2697 from DeusData/fix/py-attr-c3-mro
fix(python-lsp): look attributes up along the C3 method resolution order
2026-10-19 05:06:00 +02:00
Martin Vogel 240b24ae82 fix(python): docstrings and __future__ imports are no namespace barriers
The namespace facts proved only plain one-line strings safe, so every triple-quoted string statement (a module, class or attribute docstring) was an unknown EFFECT, and from __future__ import x was UNSUPPORTED. A barrier withdraws every name bound before it: sqlalchemy's sql/expression.py lost its 149 re-exports to the docstring after nullsfirst = nulls_first, and a docstring made an otherwise plain class unproven. A string literal now evaluates nothing in any quoting or prefix (r, b, u, rb), implicit concatenations included; an f-string with a replacement field stays an effect (__format__/__str__ may run code). from __future__ import x [as y] binds like a from-import of module __future__; a star import from __future__ is a syntax error and stays unsupported.

CBM_PY_NAMESPACE_FACTS_VERSION moves to 2. The version travels in the lsp_surface py payload and a payload of another version does not decode, so the first incremental run on an index of an older binary falls back to a full re-index (delta.rehydrate_failed -> CBM_PIPELINE_FORCE_FULL_REINDEX) instead of mixing old and new facts. The codec test now spells the current version and rejects a version-1 payload.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 05:00:19 +02:00
Martin Vogel 782ab752d9 Merge origin/main into fix/py-namespace-reexports-v2 (pick up #2700)
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 04:47:30 +02:00
Martin Vogel e6b47a393b Merge pull request #2700 from DeusData/fix/py-type-checking-imports-v2
fix(python): resolve annotations through TYPE_CHECKING imports (#1277)
2026-10-19 04:46:55 +02:00
Martin Vogel 2cee7a12e2 Merge remote-tracking branch 'origin/main' into fix/issue-1692-aspnet-routes-v2
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 04:40:49 +02:00
Martin Vogel 9adada0185 fix(php): index trait methods by receiver while flattening (#1265)
flatten_trait_into_class looked up each trait's methods by scanning every
function of the registry, and every flattened method appends more of them.
A file with many trait-using classes paid O(classes x functions), and the
scan grew with its own output.

The class-field pass now keeps a receiver -> function-id index, synced
incrementally as functions are registered, and flattening reads only the
trait's own entries registered before the current class. If the index
cannot be built, the previous full scan runs unchanged. Only entries
registered before flattening started are visited, so the output is
identical.

Tests: the work-counter tests for #1265 (100 -> 200 trait-using classes,
ratio gate 2.5) and #765 (trait collision shapes stay bounded) use the
existing test-only work ceiling.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 04:39:09 +02:00
Martin Vogel 4527fc731a Merge pull request #2702 from DeusData/fix/php-single-file-registry-finalize
fix(php): index the single-file LSP type registry
2026-10-19 04:37:17 +02:00
Martin Vogel 7b5e680f33 Merge origin/main into fix/py-namespace-reexports-v2 (pick up #2680, #2690, #2695, #2696)
py_lsp.c: the module-member lookup of this branch and the C3 super() lookup of #2696 were added at the same place; both are kept.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 03:59:33 +02:00
Martin Vogel c06465bae1 Merge pull request #2680 from DeusData/fix/py-relative-package-import
fix(python): from . import x names the importing package, not its parent
2026-10-19 03:24:43 +02:00
Martin Vogel c5b6f22ec6 Merge origin/main into fix/py-nested-class-qn-v3 (#2690 landed as 4a057e4e)
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 02:59:41 +02:00
Martin Vogel 4a057e4ec6 Merge pull request #2690 from DeusData/fix/py-decorated-nested-class
fix(python): extract a decorated class nested in a class body
2026-10-19 02:58:42 +02:00
Martin Vogel 1501cade36 Merge origin/main into fix/py-attr-c3-mro (#2696 landed as 5dc83ac9)
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 02:56:07 +02:00
Martin Vogel 5dc83ac9fa Merge pull request #2696 from DeusData/fix/py-super-c3-mro
fix(python-lsp): resolve super() through the C3 method resolution order
2026-10-19 02:55:13 +02:00
Martin Vogel 3ead775d0b fix(python): skip annotation-only imports without a new raw free
The memory-core linter counts raw allocator calls per file and fails when a
file grows. The TYPE_CHECKING change freed the copied local name of an
annotation-only import with a new raw free in two import-map builders.
build_import_map now asks the predicate on the name's span in the edge
properties before copying it (cbm_imports_local_span_binds_runtime_name,
which cbm_imports_local_binds_runtime_name now wraps), and the cross-LSP
builder routes an annotation-only name through its existing no-value path.
Same behaviour, no new raw allocator site.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 02:11:45 +02:00
Martin Vogel 7d92e749b3 Merge branch 'gq-l5/stack-a-1907' into gq-l5/stack-a-1913
Brings in the base branch with main 658639ec merged (#2685, Rust
generic-impl call scope), so this branch merges cleanly into main
again. No conflicts.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:56:36 +02:00
Martin Vogel 730a8747e8 Merge remote-tracking branch 'origin/main' into gq-l5/stack-a-1907
Brings in main 658639ec (#2685, Rust generic-impl call scope). One
conflict in tests/test_extraction.c: main's new F-R4 test and its
helper sit right before the flag-exempt test, whose comment this
branch rewrote (Go now sets is_method, so the guarded language is
Rust). Both are kept: main's block, then this branch's comment.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:43:57 +02:00
Martin Vogel 669911ce60 style(lsp): clang-format the work-ceiling macro
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:40:56 +02:00
Martin Vogel 7c3f50605b fix(python): give the alternative-branch shadow a valid reason
A namespace fact stream is checked by cbm_py_namespace_facts_valid, which
accepts a shadow only for the value, decorated, unproven-class and
unsupported reasons. The withdrawn TYPE_CHECKING re-export carried the
compound reason, so the whole stream was rejected and the package published
no names at all (a lazy-module package lost its TYPE_CHECKING exports). It
now carries the unsupported reason: the builder cannot tell which source the
name has at runtime. python_namespace_facts_type_checking_alternatives pins
both shapes as complete, valid streams.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:38:03 +02:00
Martin Vogel 24277c4037 fix(python): withdraw a TYPE_CHECKING re-export the else branch imports again
A package namespace read in the type-checker view takes the consequence of
`if TYPE_CHECKING:` as executed (lazy-module packages publish their names
there). The compat shape imports a name there and again in `else: try:
from runtime.place import name`: the module's runtime export comes from the
else branch, so publishing the TYPE_CHECKING source as the re-export target
was a guess. Every name an elif/else import binds now becomes a shadow fact
(the re-export is withdrawn, as for a later assignment); a star import or an
import form the builder does not read there makes the whole namespace
unknown. The branch is walked iteratively.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:07:11 +02:00
Martin Vogel 45b7279f6a fix(php): index the single-file LSP type registry
cbm_run_php_lsp never finalized its type registry, so every lookup during
single-file resolution scanned the stdlib plus every definition of the
file linearly: O(lookups x definitions), quadratic in the size of one
file. The cross-file path already indexes its registry.

The registry is now finalized with first-registered semantics (the first
registration of a duplicate QN wins), which keeps exactly the answers of
the linear scan, and re-indexed once after trait flattening adds methods.
The index lives in a scratch arena that dies with the call.

A test-only work ceiling (CBM_LSP_WORK_CEILING_HIT, seam builds only) lets
the work-counter test stop a reverted, unbounded loop deterministically
instead of hanging the runner; product builds have no ceiling.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 01:03:15 +02:00
Martin Vogel 62191225c5 fix(python): resolve names re-exported through package namespaces
A package `__init__.py` re-exports its submodules' names (`from .fields
import *`, `from .x import Orig as Renamed`), and callers reach them as
module attributes (`models.CharField()`) or through `from pkg import Name`.
The Python namespace facts already capture each module's top-level bindings
in order; nothing consumed them, so those calls fell to name guesses that
pick the first same-named definition under the package.

- Records: cbm_pxc_collect_all_defs replays each module's COMPLETE fact
  stream into re-export, star-import and `__all__` records next to its
  defs, including for an import-only `__init__.py` (zero defs). Records
  carry the raw module spec; the Python registry resolves it (relative
  exactly, absolute by unique scope tail, else unknown).
- Fold: the shared Python registry folds the records once, after finalize
  and before the seal, into a sorted per-module export table (binary
  search; no lookup in the registration loop). Order-deterministic; a
  cycle contributes what it has so far.
- States (conservative): an incomplete fact stream publishes nothing; a
  shadow, delete or whole-namespace unknown (a top-level try/if/with)
  withdraws the names it covers; a star whose source cannot be enumerated
  publishes nothing; a literal `__all__` restricts a star, else public
  names only.
- Consult: the Python LSP looks a module attribute up in the export table
  on a miss (calls, expression types, callable values) and when binding
  `from pkg import Y` where Y is no def of pkg.
- Namespace facts read a module-level `if TYPE_CHECKING:` consequence as
  executed: lazy-module packages publish their names there.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 00:55:58 +02:00
Martin Vogel 2455e75578 fix(python): a TYPE_CHECKING import the else branch rebinds stays unrecorded (#1277)
The compat shape imports a name under `if TYPE_CHECKING:` and again in the
else branch, usually inside try/except ImportError. The name is bound at
runtime there, so its TYPE_CHECKING import is no annotation-only import:
recording it flagged made every CALLS import map skip the name and lost the
calls and bases that bind through the runtime import (airflow mask_secret,
OpenLineageRedactor(SecretsMasker)). The imports of the elif/else branches
are collected (any depth, iteratively), every TYPE_CHECKING import whose
local name they bind is dropped with them, and a star import there drops the
whole block: those names keep the behaviour they had before #1277.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-19 00:26:43 +02:00
Martin Vogel 88bfceda0b Merge remote-tracking branch 'origin/main' into fix/issue-1692-aspnet-routes-v2
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-18 23:57:12 +02:00