diff --git a/CHANGELOG.md b/CHANGELOG.md index 6423a2e..4382bcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,132 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v2.0.0-rc.7] - 2026-09-11 + +The Java facade learns the view layer codeanalyzer-java 3.3.0–3.3.2 added, and the 2.0 line takes up +everything rc.6 shipped from `main` (the 3.2.0 text model and the sibling-analyzer pins) — this is +the first release cut from `release/2.0` that contains rc.6. + +### Added + +**Java view dispatches** (`python-sdk#404`, spec `codellm-devkit/.github` +`docs/design/specs/2026-09-11-java-view-templates-and-dispatch.md`). JSP, Facelets and Thymeleaf +templates are artifacts with `roles: ["view-template"]`, and the analyzer now says which code reaches +one. Three accessors on `JavaAnalysis`, both backends: + +- `get_view_dispatches(view=None) -> List[JViewDispatch]` — every resolved dispatch: the body node + that hands the request over (a `forward` / `include` / `sendRedirect` call, a `ModelAndView` + construction or `setViewName`, or a Spring controller's `return`) and the artifact it reaches, + with `via` naming the mechanism and `prov` the tier. `literal` and `dataflow` mean exactly one + target; `table` (3.3.1) is a may-dispatch over a static string table, one edge per entry, from + the same site. `view` filters by a segment-aligned suffix of the artifact's path. +- `get_view_dispatchers(path) -> List[JCallableOverview]` — the same edges resolved to the callables + that own the dispatching sites. +- `get_unresolved_view_dispatches() -> List[JViewDispatchUnresolved]` — what closed on nothing (a + variable target, a servlet URL, a view name matching two templates), with its reason and the tiers + attempted. JSON-only: the graph has no node for a target that resolved to nothing, so the Neo4j + backend refuses this one rather than answering `[]`. + +Two models, `JViewDispatch` and `JViewDispatchUnresolved`, on `JApplication.view_dispatches` / +`.view_dispatches_unresolved`; the Neo4j backend reads `J_DISPATCHES_TO` back into the former. + +One rule stated because it is the only one of its kind: **this layer is gated on the analyzer +generation.** The 3.1.0 config trio is probed by an always-present sibling key; 3.3.x added none — +both lists are written only when non-empty and the edge type is declared only once an edge exists — +so a pre-3.3.0 analysis is refused from `analyzer.version` (wire) / `analyzer_version` (graph) instead, +because `[]` off a 3.2.0 analysis would say "reaches no view" where the truth is that nothing looked. + +Measured on daytrader8 with 3.3.3: 37 edges at level 1–2 (3 `literal`, 34 `table`), 54 at level 4, +19 of 23 JSPs reached; the `TradeConfig.webUI` table's 17 on-disk pages all reached. + +### Changed + +- `codeanalyzer-java` pin `3.2.0` → **`3.3.3`** (the `java` extra and `[tool.backend-versions]`). + 3.3.0 adds the view-template role, `J_DISPATCHES_TO`, and `argument_expr` on `return` body nodes; + 3.3.1 the table tier; 3.3.2 narrows the Jakarta entrypoint finder to lifecycle methods, so + helpers taking servlet-typed parameters are no longer entrypoints and the interprocedural + config-use and view-dispatch tiers bind their parameters (daytrader8 entrypoint marks + 135 → 196: 21 helpers dropped, 82 `init`/`destroy`/`doFilter`/`onMessage` gained); 3.3.3 fixes + the `NullPointerException` 3.3.0–3.3.2 threw on any unbuilt project with a dispatch call, which + this SDK's `test_java_degradation.py` was the first to hit (codeanalyzer-java#265). +- `release/2.0` absorbed `main` at rc.6. + +### Verification + +The Java suite offline on both backends over a1 with the layer injected (edges, suffix filter, +dispatcher resolution, the JSON-only refusal on the graph, the pre-3.3.0 refusal, the empty answer +on a 3.3.x payload that reaches nothing, and the answered-once check across backends); the public +surface pins the three signatures; e2e against the 3.3.3 wheel on daytrader8 at level 1 and 2 +asserts the 37 edges, the 19 views, the three unresolved URLs and the 38 view-template artifacts. + +## [v2.0.0-rc.6] - 2026-09-10 + +The Java Neo4j backend stops being the lossy one about source text. Until now a graph-backed Java +analysis could answer *where* a node is far better than *what it says*: text existed only as +`:JCallable.code`, so a callable came back as its whole declaration where the local backend returned +the body block, a body node had no text at all, and a module-scope `locate` returned `""`. The +analyzer closed that gap in 3.2.0; this release takes it up, and moves the sibling pins to the +releases that closed the same gap for Python and TypeScript. + +### Breaking + +**The Java Neo4j attach floor moves to codeanalyzer-java 3.2.0.** A graph emitted by 3.1.x — served +silently until now — is refused at attach, naming what was found and the floor. + +The floor moves rather than degrading gracefully because the degradation would be silent and would +look like data. A 3.1.x graph has no `:JModule.source` and no byte offsets, so every text answer +would come back empty or as the old whole-declaration string, from accessors this release documents +as returning the same text as the local backend. An agent cannot tell "this node has no text" from +"this graph predates the property" — so the check belongs at attach, once, where it can say so. + +**Migration:** re-emit with `codeanalyzer-java 3.2.0 --emit neo4j`. Wipe the database first when the +graph predates 3.1.1, which moved the `can://` grammar. + +### Changed + +**Text is the same on both Java backends.** `JCallable.code`, `get_source`, `LocateResult.source` and +`describe` answer the same slice of the same file at every granularity — a callable's body block, a +type's or field's or local's declaration, a single statement or call site, and a module's whole text at +module scope. Each is a byte slice of `:JModule.source` taken at the node's own offsets, so the live +suites assert **equality** rather than `endswith` or "the same length". + +Three positions still have no text, on **both** backends and for the same reason each time — there is +nothing in the file to point at: an implicit compiler-generated `()`, an `@external` callable, and +a `resolve_value` ref (a `formal_in` vertex is a dataflow position, not a region of the file). +`module_source_unavailable` survives as a **data** diagnostic: it now fires on a module whose text the +analyzer could not read or decode, and on nothing else. + +Two removals fall out of it. `:JCallable.code` is no longer read — the slice replaces it — and +`body_end_byte` was never needed: across both committed fixtures, all 1,182 callables carrying both +spans end their body exactly where their declaration ends, because a Java declaration's last character +*is* its body's closing brace. That is asserted in the fixture builder rather than written down. + +**Analyzer pins move to `codeanalyzer-python==1.5.2` and `codeanalyzer-typescript==1.6.0`** +(`codeanalyzer-java` is already at 3.2.0). Both are Neo4j-projection-only conformance fixes: python +1.5.2 adds `:PyModule.source`, all six span properties wherever a span is declared, +`:PyVariable.value_json`, `:PyBodyNode.callee_signature`, `PY_IMPORTS.positions_json` and a span on +`PY_DECORATED_BY`; typescript 1.6.0 adds `:TSModule.source` and the four new span properties across ten +labels. Neither changes `analysis.json` — the TypeScript fixtures regenerated with the 1.6.0 wheel are +byte-identical to the 1.5.3 generation at all four levels apart from the `analyzer.version` stamp. + +**Neither sibling floor moves.** They stay 1.5.0 for Python and 1.5.2 for TypeScript: a floor move is +what would let the SDK *read* that new text, and that is uptake work the size of this release's Java +half, tracked in #396 and #391. The pin is what the SDK installs; the floor is what it requires of a +graph. Every sentence in the docs that read "the graph does not carry this" now says the SDK does not +read it, and names the issue that will. + +One thing does improve for free on a re-emitted Python graph: a call site's columns. The +reconstruction already reads `start_column` with a `-1` default, so 1.5.2 supplies real values and an +older graph still answers `-1` — data-driven, no version branch. + +### Verification + +The mocked, backend-contract and E2E tiers are green, and the Java E2E ran against the real 3.2.0 jar. +The **live** Java tiers — the ones that assert byte-for-byte equality across the two backends on +daytrader8 — assert the new behaviour but have not been run against a 3.2.0-emitted graph: the +verification corpus holds a 3.1.1 graph, which this release's own floor now refuses. Re-emitting it is +the outstanding verification debt, recorded rather than glossed. + ## [v2.0.0-rc.5] - 2026-09-10 Two changes, and they are the two halves of one question: what should happen when an analyzer ships diff --git a/CLAUDE.md b/CLAUDE.md index b6c1e3e..7f4fc42 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,9 +10,9 @@ an optional read-only Neo4j backend — selected by the *type* of the `backend=` | Language | Entry point | Local backend | Neo4j backend | Models | |----------|-------------|---------------|---------------|--------| -| Java | `CLDK.java(...)` (needs the `cldk[java]` extra) | `JCodeanalyzer` (the `codeanalyzer-java` 3.1.1 wheel's jar on its bundled JVM, subprocess, `-a 1..4` — no jar in this repo, no JDK download) | `JNeo4jBackend` (graphs emitted by ≥ 3.1.1, probed at attach) | `cldk/models/java/` (schema v2 mirror) + `projections.py` | +| Java | `CLDK.java(...)` (needs the `cldk[java]` extra) | `JCodeanalyzer` (the `codeanalyzer-java` 3.2.0 wheel's jar on its bundled JVM, subprocess, `-a 1..4` — no jar in this repo, no JDK download) | `JNeo4jBackend` (graphs emitted by ≥ 3.2.0, probed at attach) | `cldk/models/java/` (schema v2 mirror) + `projections.py` | | Python | `CLDK.python(...)` | `PyCodeanalyzer` (in-process `codeanalyzer-python`) | `PyNeo4jBackend` | re-exported from `codeanalyzer-python` | -| TypeScript (+ JavaScript modules) | `CLDK.typescript(...)` | `TSCodeanalyzer` (`codeanalyzer-typescript` 1.5.2 binary from the wheel, subprocess; `-a 1..4`, but `--emit neo4j` takes no `-a` and is always full depth) | `TSNeo4jBackend` (graphs emitted by ≥ 1.5.2; older refused at attach) | `cldk/models/typescript/` (schema v2 mirror) | +| TypeScript (+ JavaScript modules) | `CLDK.typescript(...)` | `TSCodeanalyzer` (`codeanalyzer-typescript` 1.6.0 binary from the wheel, subprocess; `-a 1..4`, but `--emit neo4j` takes no `-a` and is always full depth) | `TSNeo4jBackend` (graphs emitted by ≥ 1.5.2; older refused at attach) | `cldk/models/typescript/` (schema v2 mirror) | **Java, since leg 3a (#310):** the models are an `extra="forbid"` mirror of canonical schema v2, so a 1.x `analysis.json` (and a pre-3.0.1 Neo4j graph) is refused, not parsed; `get_call_graph()` keys diff --git a/cldk/analysis/commons/results.py b/cldk/analysis/commons/results.py index ac6bbcd..e90db54 100644 --- a/cldk/analysis/commons/results.py +++ b/cldk/analysis/commons/results.py @@ -275,9 +275,11 @@ class SliceNode(BaseModel): defined_in: For a ``global``, the module it is defined in (``"payment"``) — the same vocabulary as :attr:`ModuleRef.module_name`. ``None`` for everything else, whose defining scope is the enclosing callable in :attr:`callable`. - source: The text, when the backend can produce it; ``None`` when it cannot. The Neo4j graph - carries no text below callable granularity (see :class:`LocateResult`), so it is - ``None`` there for anything finer. + source: The text, when the backend can produce it; ``None`` when it cannot. Whether a + Neo4j graph carries text below callable granularity is the projection's choice, so it + depends on the language: Java's does since codeanalyzer-java 3.2.0 and answers the same + text as its local backend, Python's does not and is ``None`` there for anything finer + (see :class:`LocateResult`). ref: The analyzer's own id for this node — **opaque**. Pass it back; do not parse it, and do not build one. The one sanctioned use is :meth:`~cldk.analysis.python.backend.PythonAnalysisBackend.get_source`, and that diff --git a/cldk/analysis/java/backend.py b/cldk/analysis/java/backend.py index 3fb33af..2cace7b 100644 --- a/cldk/analysis/java/backend.py +++ b/cldk/analysis/java/backend.py @@ -109,6 +109,8 @@ JLocalVariable, JMethodDetail, JType, + JViewDispatch, + JViewDispatchUnresolved, ) from cldk.models.java.projections import JCallableOverview, JClassOverview from cldk.utils.exceptions.exceptions import CodeanalyzerExecutionException, CodeanalyzerUsageException, SelectorNotInGraph @@ -154,6 +156,29 @@ "codeanalyzer-java 3.1.0 or newer. get_config_keys() is unaffected: the keys a config artifact declares are read at every generation." ) +#: Why the three view-dispatch accessors refuse on an analysis that predates the pass. +#: codeanalyzer-java 3.3.0 (spec 2026-09-11, codeanalyzer-java#259) added the view-dispatch layer; +#: 3.3.1 (#261) its table tier. Unlike the 3.1.0 trio there is **no unconditional witness** for it: +#: both lists are written only when non-empty, ``J_DISPATCHES_TO`` is declared only once an edge +#: exists, and the release added no always-present key. So this is the one overlay decided from the +#: analyzer generation — ``analyzer.version`` on the wire, ``analyzer_version`` on the ``:JApplication`` +#: anchor — because the alternative, answering ``[]`` off a 3.2.0 analysis, would say "this +#: application reaches no view" where the truth is that nothing looked (D7). +VIEW_DISPATCH_UNAVAILABLE = ( + "the view-dispatch layer cannot be answered for application {app!r}: this analysis was produced by codeanalyzer-java {version}, and the " + "layer (view_dispatches, view_dispatches_unresolved, J_DISPATCHES_TO) exists only from 3.3.0. An empty answer here would say 'this " + "application reaches no view' where the truth is that nothing looked. Re-analyse, or re-emit your Neo4j graph, with codeanalyzer-java " + "3.3.0 or newer. get_artifacts() is unaffected." +) + +#: What the graph backend raises from ``get_unresolved_view_dispatches``: the projection carries no +#: node for a target that resolved to nothing, so the record is reachable from ``analysis.json`` only. +VIEW_DISPATCH_UNRESOLVED_JSON_ONLY = ( + "unresolved view dispatches for application {app!r} are not in the graph: codeanalyzer-java writes view_dispatches_unresolved into " + "analysis.json only (a target that resolved to no artifact has no node to project an edge to), so this backend cannot tell 'every " + "dispatch resolved' from 'the record is elsewhere'. Read them off the local codeanalyzer backend." +) + #: What ``get_external_symbols`` raises on a payload whose run never homed out-of-project call #: targets -- which is not the same fact as a project that calls nothing outside itself (D7). EXTERNAL_SYMBOLS_UNAVAILABLE = ( @@ -535,16 +560,16 @@ class JavaAnalysisBackend(AnalysisBackend[JApplication, JCompilationUnit, JType, # callable (:meth:`_body_nodes`), the text of one (:meth:`_body_source`), and whether call # sites resolve at all (:attr:`has_resolution_edges`). # - # WHAT STILL DIFFERS, AND IT IS THE DATA, NOT THE CODE. ``JCallable.code`` is the **body - # block** off ``analysis.json`` and the whole **declaration** off the Neo4j projection - # (codeanalyzer-java#176: the graph carries one line range per callable and no ``body_span``), - # so :meth:`get_source` and :attr:`LocateResult.source` return the declaration over Neo4j — - # stated on :meth:`JavaAnalysis.get_source`, in the lossiness table of - # ``docs/agent-api-reference.md``, and asserted by the live parity suite as - # ``neo.code.endswith(ref.code)``. A **module** carries no ``source`` at all there, so a - # module-scope :meth:`locate` answers ``""`` plus a ``module_source_unavailable`` diagnostic; - # and a body node has no text on either side of the graph, so it hydrates only locally. - # None of that is branched on: it falls out of what the models hold. + # WHAT STILL DIFFERS, AND IT IS THE DATA, NOT THE CODE. **Text no longer differs.** + # codeanalyzer-java 3.2.0 projects ``:JModule.source`` plus the byte offsets every node's text is + # a slice of, so :meth:`get_source`, :attr:`LocateResult.source` and a module-scope + # :meth:`locate` read the same characters on both backends and the live parity suite asserts + # ``neo.code == ref.code`` (it asserted ``neo.code.endswith(ref.code)`` while the graph carried + # the whole declaration and no ``body_span`` — codeanalyzer-java#176, fixed by the 3.2.0 text + # model, which is why ``JNeo4jBackend`` floors there). What is still thinner over Neo4j is the + # *set* of nodes, not their text: a body node has text only where the projection wrote offsets + # for it, and ``JCallable.body`` holds the ``call`` nodes only. None of that is branched on: it + # falls out of what the models hold. # # NO ``can://`` AND NO ORDINAL leaves this surface except in ``ref`` / ``node_id`` (E6/E7); # every error names what missed and suggests nothing (E8). @@ -655,9 +680,10 @@ def _locate_result(self, line: int, key: str, row: Optional[_Addressed], bodies: names = java_module_dotted(unit.package, unit.types) module_ref = ModuleRef(path=key, module_name=names[0] if names else None) if row is None: - # The graph carries no module ``source``, so the text a module-scope result would hand - # back does not exist there. Read off the data rather than off which backend is running: - # "" is never returned as if it were the file. + # Read off the data rather than off which backend is running: "" is never returned as + # if it were the file. Since codeanalyzer-java 3.2.0 the projection carries + # ``:JModule.source``, so this diagnostic fires on a module whose text is genuinely + # missing -- an unreadable or undecodable file -- and on nothing else. diagnostics = [Diagnostic(code="module_scope", message=f"line {line} is at module scope in {key}.")] if not unit.source: diagnostics.append(Diagnostic(code="module_source_unavailable", message=f"no source text is available for {key} on this backend.")) @@ -827,17 +853,17 @@ def get_source(self, node_id: str) -> str: statement or call site an alert landed on can be re-fetched, not just its enclosing callable. Round-tripped, never composed by the caller (E6). - **What comes back for a callable differs by backend, and the difference is the graph's.** - Off ``analysis.json`` it is the **body block**; off the Neo4j projection it is the whole - **declaration**, which ends with that body block — the graph carries one line range per - callable and no ``body_span`` (codeanalyzer-java#176). The relation is exact and total, and - the live parity suite asserts it rather than tolerating it. + **The same text on both backends**: the callable's body block, or the statement's own + region, sliced out of the module's text. Before codeanalyzer-java 3.2.0 the graph carried + one line range per callable, no ``body_span`` and no module text, so a callable came back as + the whole **declaration** and a body node not at all (codeanalyzer-java#176); 3.2.0 projects + ``:JModule.source`` plus byte offsets down to ``:JBodyNode``, and the live parity suite + asserts equality rather than tolerating a difference. Raises: KeyError: Nothing this backend holds is named by ``node_id``, or it names a node with - no recoverable text — an implicit callable (no span and no body at all), or, on the - Neo4j backend, any body node, since the graph carries no text below callable - granularity. The message names the reason. + no recoverable text — an implicit callable (no span and no body at all), or any + node the projection placed nowhere in a file. The message names the reason. """ found = self._sources_for([node_id]) if node_id not in found: @@ -908,11 +934,10 @@ def describe(self, nodes: Sequence[object]) -> List[SliceNode]: Afterwards ``source=None`` means exactly one thing: *this position exists and the backend has no text for it*. It never means "the lookup failed", because a ref naming nothing raises - instead. Which positions have no text differs by backend, honestly: a ``kind="callable"`` - node hydrates on both (as the declaration over Neo4j, the body block locally); a - ``parameter`` hydrates on neither, having no span in the analyzer's own model; a statement - or call site hydrates only locally, because the graph carries no text below callable - granularity. + instead. Which positions have no text no longer differs by backend: a ``kind="callable"`` + node and a statement or call site both hydrate on either, to the same slice of the same file + (codeanalyzer-java 3.2.0 carries byte offsets down to ``:JBodyNode``); a ``parameter`` + hydrates on neither, having no span in the analyzer's own model. Raises: KeyError: A ``ref`` names nothing this backend can find — a ref comes from this SDK, so @@ -1238,6 +1263,102 @@ def get_config_readers(self, key: str) -> List[JCallableOverview]: found[row.key] = row return [JCallableOverview.of(r.key, r.type, r.callable, path=r.path) for r in found.values()] + # -----[ the view-dispatch layer (codeanalyzer-java 3.3.0, python-sdk#404) ]----- + @abstractmethod + def _analyzer_generation(self) -> Tuple[int, int, int] | None: + """The ``(major, minor, patch)`` of the codeanalyzer-java that produced this analysis — + ``analyzer.version`` off the wire, ``analyzer_version`` off the ``:JApplication`` anchor — + or ``None`` when it cannot be read. The one version-shaped probe in this contract, and + :data:`VIEW_DISPATCH_UNAVAILABLE` says why it has to be one.""" + + def _view_overlay(self) -> Tuple[List[JViewDispatch], List[JViewDispatchUnresolved]]: + """This analysis's view-dispatch lists, or raise if the analyzer predates the pass. + + Raises: + CodeanalyzerExecutionException: The analysis was produced by codeanalyzer-java older + than 3.3.0, or by one whose version cannot be read (:data:`VIEW_DISPATCH_UNAVAILABLE`). + """ + generation = self._analyzer_generation() + if generation is None or generation < (3, 3, 0): + version = "unknown" if generation is None else ".".join(map(str, generation)) + raise CodeanalyzerExecutionException(VIEW_DISPATCH_UNAVAILABLE.format(app=self._application_name, version=version)) + app = self.get_application_view() + return list(app.view_dispatches or []), list(app.view_dispatches_unresolved or []) + + def _view_artifact_paths(self) -> Dict[str, str]: + """``artifact id -> repo-relative path`` for every inventoried artifact.""" + return {a.id: path for path, a in self.get_application_view().artifacts.items()} + + @staticmethod + def _view_matches(path: str, view: str) -> bool: + """Segment-aligned suffix match: ``quoteDataPrimitive.jsp`` and + ``src/main/webapp/quoteDataPrimitive.jsp`` both name the same artifact; ``DataPrimitive.jsp`` + names nothing. Never a substring (E8).""" + return path == view or path.endswith("/" + view) + + def get_view_dispatches(self, view: str | None = None) -> List[JViewDispatch]: + """Every view dispatch the analyzer resolved: a body node that hands the request to a view + template, and the artifact it reaches. + + Args: + view: Restrict to one view, matched as a segment-aligned suffix of the artifact's + repo-relative path (``home.jsp``, ``WEB-INF/jsp/home.jsp``, or the whole path). + ``None`` returns every edge. + + Returns: + :class:`~cldk.models.java.models.JViewDispatch`, sorted by ``(src, dst)``. ``prov`` is + the tier that closed the target — see the model's note on ``["table"]``, the one + many-per-site kind. Empty means the pass ran and resolved nothing. + + Raises: + CodeanalyzerExecutionException: See :meth:`_view_overlay`. + """ + dispatches, _ = self._view_overlay() + if view is None: + return dispatches + paths = self._view_artifact_paths() + return [d for d in dispatches if self._view_matches(paths.get(d.dst, ""), view)] + + def get_unresolved_view_dispatches(self) -> List[JViewDispatchUnresolved]: + """Every detected dispatch that closed on no artifact — a variable target, a servlet URL, + a view name matching two templates — kept first class so a page nobody can trace stays as + visible as one that resolves. + + Returns: + :class:`~cldk.models.java.models.JViewDispatchUnresolved`, sorted by + ``(site, reason, target)``; ``prov`` lists every tier attempted. + + Raises: + CodeanalyzerExecutionException: See :meth:`_view_overlay`; and on the Neo4j backend + always (:data:`VIEW_DISPATCH_UNRESOLVED_JSON_ONLY`), because the projection carries + no node for a target that resolved to nothing. + """ + _, unresolved = self._view_overlay() + return unresolved + + def get_view_dispatchers(self, path: str) -> List[JCallableOverview]: + """Overviews of every callable that dispatches to one view — :meth:`get_view_dispatches` + resolved from body nodes back to the callables that own them. + + Args: + path: The view's repo-relative path or any segment-aligned suffix of it, matched as in + :meth:`get_view_dispatches`. + + Returns: + One overview per distinct callable, in the addressing index's order; a callable that + reaches the view from several sites (or through a table's many entries) appears once. + Empty means nothing dispatches to it. + + Raises: + CodeanalyzerExecutionException: See :meth:`_view_overlay`. + """ + found: Dict[str, _Addressed] = {} + for edge in self.get_view_dispatches(path): + row = self._addressing.by_id.get(edge.src.rpartition("@")[0]) + if row is not None: + found[row.key] = row + return [JCallableOverview.of(r.key, r.type, r.callable, path=r.path) for r in found.values()] + # -----[ the type-kind leaf accessors (J-7) ]----- def get_interfaces(self) -> Dict[str, JType]: """Every interface, keyed by qualified name — the subset of :meth:`get_all_classes` whose @@ -1385,9 +1506,8 @@ def get_methods_with_annotations(self, annotations: List[str]) -> Dict[str, List Neither sibling language has this accessor, so it is designed rather than ported, and the pattern it follows is :meth:`JavaAnalysis.get_test_methods`: read the **analyzer's own** annotations off the model (``J_ANNOTATED_BY``; 26,162 edges on the reference graph) rather - than re-parsing a source string, so it answers identically on both backends -- a - Neo4j-backed analysis carries no module source at all, and the 1.x tree-sitter version - returned ``{}`` there. + than re-parsing a source string, so it answers identically on both backends -- the 1.x + tree-sitter version returned ``{}`` on any projection that carried no module text. Args: annotations: Annotation names, matched by the J-5 marker rule @@ -1405,10 +1525,8 @@ def get_methods_with_annotations(self, annotations: List[str]) -> Dict[str, List * ``class`` -- the declaring type's qualified name; * ``signature`` -- the callable's signature within that type; * ``method_name`` -- its simple name (the 1.x key, kept); - * ``body`` -- :attr:`~cldk.models.java.models.JCallable.code` (the 1.x key, kept). - Note this is the body block off ``analysis.json`` and the whole declaration off the - Neo4j projection, exactly as it is for :meth:`JavaAnalysis.get_test_methods`; it is a - documented property of the model, not a divergence introduced here. + * ``body`` -- :attr:`~cldk.models.java.models.JCallable.code` (the 1.x key, kept), + the body block on either backend since codeanalyzer-java 3.2.0. ``class`` and ``signature`` are new against 1.x, which returned the simple name alone. A simple name is not an address in Java -- 200 of daytrader8's 581 distinct signatures diff --git a/cldk/analysis/java/codeanalyzer/codeanalyzer.py b/cldk/analysis/java/codeanalyzer/codeanalyzer.py index 71496d6..c31e78e 100644 --- a/cldk/analysis/java/codeanalyzer/codeanalyzer.py +++ b/cldk/analysis/java/codeanalyzer/codeanalyzer.py @@ -161,6 +161,14 @@ def _recorded_verdict(verdict_file: Path, analysis_json_file: Path) -> List[Diag return None +def _semver(raw: object) -> Tuple[int, int, int] | None: + """``"3.3.2"`` → ``(3, 3, 2)``; anything that is not three integers is ``None``.""" + parts = str(raw or "").split("-", 1)[0].split(".") + if len(parts) != 3 or not all(p.isdigit() for p in parts): + return None + return int(parts[0]), int(parts[1]), int(parts[2]) + + class JCodeanalyzer(JavaAnalysisBackend): """Build and query the application view of a Java project by invoking codeanalyzer-java. @@ -187,6 +195,10 @@ class JCodeanalyzer(JavaAnalysisBackend): payload occupies the same pipe the log would. """ + def _analyzer_generation(self) -> Tuple[int, int, int] | None: + """``analyzer.version`` off the wire, as a comparable tuple; ``None`` if it is not a semver.""" + return _semver(self.analysis.analyzer.version) + def __init__( self, project_dir: Union[str, Path, None], diff --git a/cldk/analysis/java/java_analysis.py b/cldk/analysis/java/java_analysis.py index 75e3d58..614d586 100644 --- a/cldk/analysis/java/java_analysis.py +++ b/cldk/analysis/java/java_analysis.py @@ -72,6 +72,8 @@ JField, JMethodDetail, JType, + JViewDispatch, + JViewDispatchUnresolved, ) from cldk.models.java.projections import JCallableOverview, JClassOverview from cldk.models.python import PyArtifact, PyConfigKey, PyConfigRead, PyConfigUseEdge, PyDependency @@ -1949,6 +1951,47 @@ def get_config_readers(self, key: str) -> List[JCallableOverview]: """ return self.backend.get_config_readers(key) + # -----[ the view-dispatch layer (codeanalyzer-java 3.3.0) ]----- + def get_view_dispatches(self, view: str | None = None) -> List[JViewDispatch]: + """Return every resolved view dispatch: which body node hands the request to which view + template (JSP, Facelet, Thymeleaf) — a ``forward`` / ``include`` / ``sendRedirect`` call, a + ``ModelAndView`` construction or ``setViewName``, or a Spring controller's ``return``. + + Args: + view: When given, only edges whose view's repo-relative path ends with it, + segment-aligned (``home.jsp`` or ``WEB-INF/jsp/home.jsp``). + + Raises: + CodeanalyzerExecutionException: The analysis predates codeanalyzer-java 3.3.0, which is + where the pass exists; an older analysis is refused rather than answered ``[]``. + + See Also: + :meth:`get_view_dispatchers`: The same edges, resolved to their dispatching callables. + :meth:`get_unresolved_view_dispatches`: The dispatches this cannot show. + """ + return self.backend.get_view_dispatches(view) + + def get_unresolved_view_dispatches(self) -> List[JViewDispatchUnresolved]: + """Return every detected dispatch that closed on no view — a variable target, a servlet URL, + a view name matching two templates — with its reason and the tiers attempted. + + Raises: + CodeanalyzerExecutionException: The analysis predates codeanalyzer-java 3.3.0; or, on the + Neo4j backend, always — the record lives in ``analysis.json`` only. + """ + return self.backend.get_unresolved_view_dispatches() + + def get_view_dispatchers(self, path: str) -> List[JCallableOverview]: + """Return overviews of every callable that dispatches to the view at ``path``. + + Args: + path: The view's repo-relative path or any segment-aligned suffix of it. + + Raises: + CodeanalyzerExecutionException: As :meth:`get_view_dispatches`. + """ + return self.backend.get_view_dispatchers(path) + # -----[ the type-kind leaf accessors (J-7) ]----- def get_interfaces(self) -> Dict[str, JType]: """Return every interface in the project, keyed by qualified name. diff --git a/cldk/analysis/java/neo4j/neo4j_backend.py b/cldk/analysis/java/neo4j/neo4j_backend.py index 9a475d6..103b2cc 100644 --- a/cldk/analysis/java/neo4j/neo4j_backend.py +++ b/cldk/analysis/java/neo4j/neo4j_backend.py @@ -21,7 +21,7 @@ surface, answered over a live graph that ``codeanalyzer-java --emit neo4j`` populated out of band. This class never writes and needs neither the analyzer JAR, a JDK, nor the project sources. -**The graph it reads** (``schema.neo4j.json`` at the 3.1.1 tag, contract ``2.0.0``, verified +**The graph it reads** (``schema.neo4j.json`` at the 3.2.0 tag, contract ``2.0.0``, verified against the reference graph): ``:JApplication`` is keyed by **``id``** (``can://``; ``name`` survives as a display property with no uniqueness constraint) and stamps ``analyzer_version``; every project-owned node carries a ``can:///java/…`` ``id`` and the @@ -90,10 +90,13 @@ are not issued at all (:meth:`_overlay_rows`). **Lossiness** relative to the in-memory backend (the projection's, not this client's; see -:mod:`reconstruct` for the per-node detail): a module carries no ``source`` and no span, so -``JCompilationUnit.code`` is ``""`` and only a *callable's* text survives — as its whole -declaration, where the local backend's ``code`` is the body block; comments exist only as one -``docstring`` per declaration, so file-level comments are not projected at all +:mod:`reconstruct` for the per-node detail): **text is no longer part of it** — codeanalyzer-java +3.2.0 projects ``:JModule.source`` plus byte offsets, so every node's ``code`` is the same slice of +the same file the local backend reads, a callable's included (its ``body_span`` is rebuilt from +``body_start_byte``, so ``code`` is the body block on both backends); what remains missing is every +*column*, a slice for the 102 implicit ``()`` that were never written, and text below the +``call`` nodes of a body. Comments exist only as one ``docstring`` per declaration, so file-level +comments are not projected at all (:meth:`get_all_comments` and :meth:`get_comment_in_file` raise rather than answer with a smaller set claiming to be every comment); ``JCallable.body`` holds the ``call`` nodes only, without their ``arguments`` or end columns; ``cfg``/``cdg``/``ddg``/``summary``, ``param_in``/``param_out`` and @@ -131,6 +134,7 @@ JavaAnalysisBackend, duplicate_type_name, unhomed_endpoint, + VIEW_DISPATCH_UNRESOLVED_JSON_ONLY, ) from cldk.analysis.java.neo4j import reconstruct as R from cldk.models.java import JGraphEdges @@ -147,6 +151,8 @@ JCompilationUnit, JConfigRead, JConfigUse, + JViewDispatch, + JViewDispatchUnresolved, JDdgEdge, JDecorator, JEntrypointReport, @@ -205,15 +211,23 @@ class JNeo4jBackend(JavaAnalysisBackend): #: Relationship types every supported graph has; a graph missing any was emitted by another #: generation (a schema-v1 graph shares only ``J_CALLS``) and is refused at attach. _REQUIRED_RELATIONSHIP_TYPES: FrozenSet[str] = frozenset({"J_HAS_MODULE", "J_HAS_METHOD", "J_HAS_BODY_NODE", "J_CALLS"}) - #: The oldest codeanalyzer-java whose graph this backend serves. **3.1.1 exactly**, not - #: "3.0.1 or newer": 3.1.1 moved the application to the outermost segment of the ``can://`` + #: The oldest codeanalyzer-java whose graph this backend serves. **3.2.0 exactly** — the release + #: whose projection carries the canonical text model: ``:JModule.source`` plus the + #: ``start_byte``/``end_byte`` offsets every node's ``code`` is a slice of. This backend reads + #: text only that way (:func:`reconstruct.span`), so on a 3.1.x graph every ``code`` on every + #: node would be ``""`` — the silent empty this floor exists to refuse. + #: + #: *Why a version and not a data probe*, against the house rule that a probe reads the data: the + #: floor is a **generation** question, not a capability one, and the precedent is the reason 3.1.1 + #: was the floor before it. 3.1.1 moved the application to the outermost segment of the ``can://`` #: grammar every statement here scopes on, and 3.1.0 — which is in the wild — emits the old - #: ``can://java//…`` one. A 3.1.0 graph carries every relationship type + #: ``can://java//…`` one; a 3.1.0 graph carries every relationship type #: :meth:`_probe_schema` looks for and the contract-2.0.0 body-node shape, so it attaches - #: cleanly and then answers every prefix-scoped statement with zero rows. Refusing it by version - #: is the only thing between a caller and that silent empty. (3.0.0 stamped contract 2.2.0; - #: 3.0.1 holds 2.0.0 — the body-node shape every statement here reads.) - _ANALYZER_FLOOR = (3, 1, 1) + #: cleanly and then answers every prefix-scoped statement with zero rows. Version was the only + #: thing between a caller and that empty then, and ``:JModule.source`` is a fine capability probe + #: and a poor generation one now. (3.0.0 stamped contract 2.2.0; 3.0.1 holds 2.0.0 — the + #: body-node shape every statement here reads.) + _ANALYZER_FLOOR = (3, 2, 0) #: Set by :meth:`_probe_schema`; the class-level ``None`` is for the ``object.__new__`` seam. _analyzer_version: Tuple[int, int, int] | None = None #: The database's relationship types, read once by :meth:`_probe_schema` and reused by @@ -559,9 +573,7 @@ def _reconstruct(self) -> JApplication: # A module declares types only; ``kind`` is a ``Literal`` on :class:`JType`, so a # row that is not one is refused by the model. types[self._child_key(module_id, p)] = self._type(p, children, sites) - unit = R.compilation_unit(props, import_declarations=[i for e in imports.get(key, []) for i in R.imports(e)], types=types) - R.thread_code(unit, self._projected_code(children, module_id)) - symbol_table[key] = unit + symbol_table[key] = R.compilation_unit(props, import_declarations=[i for e in imports.get(key, []) for i in R.imports(e)], types=types) return JApplication( id=self._application_id, symbol_table=symbol_table, @@ -585,21 +597,35 @@ def _reconstruct(self) -> JApplication: # ``None`` and ``[]`` are different answers here: see :meth:`_overlay_rows`. config_uses=None if report is None else uses, config_reads_unresolved=None if report is None else reads, + # From 3.3.0 the edge is read whatever the application reaches (``[]`` is a real answer); + # before it the key stays ``None`` and the accessors refuse on the generation. The + # unresolved record is JSON-only and never rebuilt here -- see + # :meth:`get_unresolved_view_dispatches`. + view_dispatches=self._view_dispatch_rows() if (self._analyzer_version or (0, 0, 0)) >= (3, 3, 0) else None, ) - @staticmethod - def _projected_code(children: Dict[str, List[_Child]], module_id: str) -> Dict[str, str]: - """``callable id -> code`` for one module's subtree — what :func:`reconstruct.thread_code` - threads onto the callables so their ``code`` view reads the graph's text.""" - out: Dict[str, str] = {} - stack = [module_id] - while stack: - for rel, p, _ in children.get(stack.pop(), []): - if rel in ("J_DECLARES", "J_HAS_METHOD"): - stack.append(p["id"]) - if rel == "J_HAS_METHOD": - out[p["id"]] = p.get("code") or "" - return out + def _view_dispatch_rows(self) -> List[JViewDispatch]: + """``J_DISPATCHES_TO`` (codeanalyzer-java 3.3.0): the source is a body node under the id + prefix, the target an artifact reached from the application anchor — the two id spaces meet + on this edge exactly as they do on ``J_USES_CONFIG``.""" + rows = self._run( + "MATCH (:JApplication {id: $app_id})-[:HAS_ARTIFACT]->(a:Artifact)<-[d:J_DISPATCHES_TO]-(src) " + f"WHERE {_scoped('src')} RETURN src.id AS src, a.id AS dst, d.via AS via, d.prov AS prov ORDER BY src.id, a.id", + app_id=self._application_id, + prefix=self._scope_prefix, + ) + return [JViewDispatch(src=r["src"], dst=r["dst"], via=r["via"], prov=list(r["prov"] or [])) for r in rows] + + def _analyzer_generation(self) -> Tuple[int, int, int] | None: + """``analyzer_version`` off the ``:JApplication`` anchor, read once at attach by + :meth:`_probe_schema`.""" + return self._analyzer_version + + def get_unresolved_view_dispatches(self) -> List[JViewDispatchUnresolved]: + """Always raises: the record is JSON-only (:data:`VIEW_DISPATCH_UNRESOLVED_JSON_ONLY`). The + generation check runs first, so a pre-3.3.0 graph gets the more useful of the two reasons.""" + self._view_overlay() + raise CodeanalyzerExecutionException(VIEW_DISPATCH_UNRESOLVED_JSON_ONLY.format(app=self._application_name)) # ===================================================================================== # The reconstructed view and its index (both built on first use) @@ -697,7 +723,8 @@ def _callables(self) -> Dict[str, Tuple[JType, JCallable]]: _BODY_NODES = ( "UNWIND $prefixes AS p MATCH (b:JBodyNode) WHERE b.id STARTS WITH p " "OPTIONAL MATCH (b)-[:J_RESOLVES_TO]->(t) WHERE " + _scoped("t") + " " - "RETURN b.id AS id, b.kind AS kind, b.start_line AS s, b.end_line AS e, t.id AS callee" + "RETURN b.id AS id, b.kind AS kind, b.start_line AS s, b.end_line AS e, " + "b.start_byte AS sb, b.end_byte AS eb, t.id AS callee" ) def _body_nodes(self, callable_ids: Sequence[str]) -> Dict[str, Dict[str, JBodyNode]]: @@ -708,6 +735,12 @@ def _body_nodes(self, callable_ids: Sequence[str]) -> Dict[str, Dict[str, JBodyN Java ``can://`` id carries none (checked: 0 of daytrader8's 1,216 and ThingsBoard's 28,763 callables). That recovers the *callable*, which is all that is needed here; it does not recover the local body key, and nothing tries to. + + Each node is then threaded to the compilation unit that callable was declared in, which is + what makes :meth:`_body_source` a real slice: these nodes are built outside the containment + tree, so :meth:`JCompilationUnit.model_post_init` never sees them. A callable with no unit + (an ``@external``, which stays in scope by design) leaves its nodes unthreaded, and + :meth:`_body_source` answers ``None`` for them. """ ids = list(dict.fromkeys(callable_ids)) if not ids: @@ -715,15 +748,34 @@ def _body_nodes(self, callable_ids: Sequence[str]) -> Dict[str, Dict[str, JBodyN out: Dict[str, Dict[str, JBodyNode]] = {} for row in self._run(self._BODY_NODES, prefixes=[f"{i}@" for i in ids], prefix=self._scope_prefix): node_id = row["id"] - out.setdefault(node_id.partition("@")[0], {})[node_id] = R.body_node({"kind": row["kind"], "start_line": row["s"], "end_line": row["e"], "callee": row["callee"]}, None) + owner = node_id.partition("@")[0] + node = R.body_node( + {"kind": row["kind"], "start_line": row["s"], "end_line": row["e"], "start_byte": row["sb"], "end_byte": row["eb"], "callee": row["callee"]}, + None, + ) + node._unit = self._unit_of(owner) + out.setdefault(owner, {})[node_id] = node return out + def _unit_of(self, callable_id: str) -> JCompilationUnit | None: + """The compilation unit a callable was declared in, or ``None`` when it has no file — which + is every ``@external`` callable, and nothing else.""" + owner = self._callables.get(callable_id) + return None if owner is None else self._application.symbol_table.get(self._file_of.get(owner[0].qualified_name, "")) + def _body_source(self, node: JBodyNode) -> str | None: - """See :meth:`JavaAnalysisBackend._body_source`. Always ``None``: ``:JBodyNode`` carries a - line range and no text, and ``:JModule`` carries no ``source`` to slice one out of, so this - projection has nothing below callable granularity. Substituting the enclosing callable's - declaration would be a wrong answer rather than a missing one.""" - return None + """See :meth:`JavaAnalysisBackend._body_source` — a real slice of the owning module's + ``source``, off the ``start_byte``/``end_byte`` codeanalyzer-java 3.2.0 projects on a + ``:JBodyNode`` and the unit :meth:`_body_nodes` threaded on. + + ``None`` — never ``""`` — for the two nodes that have no text here: one the projection wrote + no offsets for (6,726 of the reference graph's 13,544 carry them; the synthetic port + vertices stand for no source at all) and one whose callable has no file. An empty string + would claim the node's text *is* empty, which is the wrong answer rather than a missing one. + """ + if node._unit is None or node.span is None or node.span.bytes[0] < 0: + return None + return node.code or None @property def has_resolution_edges(self) -> bool: @@ -1291,11 +1343,10 @@ def get_all_constructors(self, qualified_class_name: str) -> Dict[str, JCallable return {sig: c for sig, c in klass.callables.items() if c.is_constructor} def get_method(self, qualified_class_name: str, qualified_method_name: str) -> JCallable | None: - """The callable, or ``None``. Two fields differ from the in-memory backend's, because the - projection differs: ``code`` is the whole **declaration** (the graph carries one line range - per callable and no ``body_span``), where the in-memory backend's is the body block; and - ``body`` holds the ``call`` nodes **only** — about 30% of the graph's body nodes (4,006 of - daytrader8's 13,436) — which is what ``call_sites`` is a view over.""" + """The callable, or ``None``. One field differs from the in-memory backend's, because the + projection differs: ``body`` holds the ``call`` nodes **only** — about 30% of the graph's + body nodes (4,006 of daytrader8's 13,436) — which is what ``call_sites`` is a view over. + ``code`` is the same body block on both since codeanalyzer-java 3.2.0.""" klass = self.get_class(qualified_class_name) return klass.callables.get(qualified_method_name) if klass is not None else None diff --git a/cldk/analysis/java/neo4j/reconstruct.py b/cldk/analysis/java/neo4j/reconstruct.py index ed71297..f3cfbc5 100644 --- a/cldk/analysis/java/neo4j/reconstruct.py +++ b/cldk/analysis/java/neo4j/reconstruct.py @@ -14,11 +14,12 @@ # limitations under the License. ################################################################################ -"""Rebuild the ``cldk.models.java`` (schema v2) models from codeanalyzer-java 3.0.1 Neo4j node and -edge property maps. +"""Rebuild the ``cldk.models.java`` (schema v2) models from codeanalyzer-java Neo4j node and edge +property maps. Pure functions: they take the flat property dictionaries the analyzer's Neo4j projection wrote -(``schema.neo4j.json`` at the 3.0.1 tag is the authority for what each label carries) and return +(``schema.neo4j.json`` at the 3.2.0 tag -- the attach floor -- is the authority for what each label +carries; schema v2 itself landed at 3.0.1) and return the same pydantic objects the in-memory :class:`~cldk.analysis.java.codeanalyzer.JCodeanalyzer` returns. :class:`~cldk.analysis.java.neo4j.JNeo4jBackend` fetches the rows and assembles the containment tree; the per-node shape lives here. @@ -29,29 +30,31 @@ ``False`` in the contract, and reading one with a ``False`` default is not a default hiding drift. Every non-boolean property the contract declares on a label is read with ``props[...]``. +**Text is one blob per file, sliced by byte offsets** -- the canonical schema's model since v2, and +what codeanalyzer-java 3.2.0 finally projects. ``:JModule.source`` carries the whole file (141 of 141 +modules on the 3.2.0 reference graph) and every other node's ``code`` is +``source[start_byte:end_byte]``, which is what :meth:`JCompilationUnit.slice` does. Offsets are +projected on ``:JField`` (659/659), ``:JVariable`` (863/863), ``:JType`` (152/152), ``:JCallable`` +(1,127/1,229, plus ``body_start_byte`` on 1,097) and ``:JBodyNode`` (6,726/13,544); the annotation +*application*'s offsets ride ``J_ANNOTATED_BY`` (817 edges). The 102 callables without offsets are +**exactly** the synthesized implicit ``()`` -- never written, so there is no text to want -- +which is why no callable's text is reachable through a projected ``:JCallable.code`` and not through +a slice: this module reads that property no longer, and :func:`span` is the only text path. + What the projection does **not** carry, and therefore comes back at the model's own empty default (measured against the live graph, not assumed): -* **``JModule.source``** -- the graph stores each *callable's* own text in ``JCallable.code`` and - nothing else, so a reconstructed :class:`JCompilationUnit` has ``source=""``. Its ``span`` is - unknown too (``:JModule`` carries no lines at all), so it rehydrates as the model's own ``-1``. - A callable is pointed at the text the graph did project through :func:`thread_code`; every other - node's ``code`` is ``""``. -* **every column and every byte offset** -- the projection writes ``start_line`` and ``end_line`` - and no position within a line, and no offset into a ``source`` it does not carry. Both are - reported as :data:`_UNKNOWN` (``-1``), the model's own "not known", on every node: a ``0`` would - read as column one and offset zero, which is a position, and a wrong one. **One exception, and it - is deliberate:** a :class:`JCallableParameter` comes back with the analyzer's own columns *and* - byte offsets, because the projection serialises the whole parameter list into - ``:JCallable.parameters_json`` and it round-trips exactly (see :func:`parameters`). Those byte - offsets index the module ``source`` the graph does not carry, so they locate the parameter in the - file on disk and nothing this backend can hand you; ``JCallableParameter.code`` is unreachable on - either backend (a parameter is never threaded to its compilation unit, so slicing raises rather - than returning a silent empty). -* **``JCallable.body_span``** -- the graph projects one line range per callable, the *declaration* - span. So ``JCallable.code`` here is the whole declaration (``public void f() {…}``), where the - local backend's is the body block (``{…}``); ``code_start_line`` is the declaration's first line, - which is the body block's first line too except where the opening brace sits on a later line. +* **every column** -- the projection writes ``start_line``/``end_line`` and no position within a + line, so both columns are :data:`_UNKNOWN` (``-1``) on every node: a ``0`` would read as column + one, which is a position and a wrong one. **One exception, and it is deliberate:** a + :class:`JCallableParameter` comes back with the analyzer's own columns, because the projection + serialises the whole parameter list into ``:JCallable.parameters_json`` and it round-trips exactly + (see :func:`parameters`). Its byte offsets index the same module ``source`` as everything else, but + a parameter is never threaded to its compilation unit, so ``JCallableParameter.code`` raises on + either backend rather than returning a silent empty. +* **a module without ``source``** -- an unreadable or non-UTF-8 file. Nothing in the reference graph + is one, and the degradation is per *file* rather than per node: every node in that module slices + an empty string and reports ``""`` (see :func:`compilation_unit`). * **comments** -- there are no ``:JComment`` nodes (0 in the reference graph). A type, callable, field, enum constant and record component carries a single ``docstring`` property holding its javadoc, rebuilt here as a one-element ``comments`` list; a non-javadoc comment on a declaration, @@ -59,8 +62,9 @@ * **``JCallable.body``** -- only the ``call`` nodes are rebuilt (what ``call_sites`` is a view over), which is roughly **30%** of what the graph holds (4,006 of daytrader8's 13,436 ``:JBodyNode``); the ``entry``/``exit``/``statement``/``branch``/``loop``/``return`` nodes and the - parameter lattice are not. A call site's ``arguments`` (body-key references) and both columns are - not projected either. + parameter lattice are not. A call site's ``arguments`` (body-key references) are not projected + either. The 6,818 synthetic vertices of the port lattice carry no offsets and want none: none of + them stands for source text. * **``JBodyNode.callee``** (226 populated on the committed daytrader8 ``-a 4`` fixture, 0 here) -- the ``can://`` id of the resolved callee. The projection puts that edge on ``J_RESOLVES_TO``, which this module reads into ``callee_signature`` instead, and an id has no home on the public surface @@ -71,13 +75,13 @@ to a call site. It follows from the comment gap above: the graph has no comment node to attach. * ``cfg`` / ``cdg`` / ``ddg`` / ``summary`` (``None``: 3b reads them per callable on demand), ``type_parameters``, ``JCompilationUnit.comments``, ``JApplication.param_in`` / ``param_out`` / - ``external_symbols``, and a decorator's / import's / enum constant's / record component's span. + ``external_symbols``, and an import's / enum constant's / record component's span. """ from __future__ import annotations import json -from typing import Any, Dict, List, Mapping, Optional +from typing import Any, Dict, List, Mapping, Optional, Tuple from cldk.models.java.models import ( JArtifact, @@ -101,63 +105,66 @@ Props = Mapping[str, Any] -class _ProjectedText: - """Stands in for the owning :class:`JCompilationUnit` on a callable, so its ``code`` view reads - the text the graph projected for it. - - ``:JModule`` carries no ``source``, so a reconstructed unit can slice nothing; ``:JCallable`` - carries its own ``code``. The models reach the unit only through the private ``_unit`` - back-reference, and only for :meth:`JCompilationUnit.slice` and ``package`` -- so pointing a - callable at one of these is what turns ``JCallable.code`` from an empty slice into that text - (see :func:`thread_code`). - """ - - __slots__ = ("_code", "package") - - def __init__(self, code: str, package: str) -> None: - self._code, self.package = code, package - - def slice(self, span: JSpan) -> str: - """The callable's whole projected text: the graph keeps one text per callable, not the - module source the span would index into.""" - return self._code - - -def thread_code(unit: JCompilationUnit, code: Mapping[str, str]) -> None: - """Point every callable in ``unit`` at its projected text, keyed by node id. - - Runs after the unit is validated, because :meth:`JCompilationUnit.model_post_init` threads - itself onto every node it owns and would otherwise win. - """ - - def walk(t: JType) -> None: - for c in t.callables.values(): - c._unit = _ProjectedText(code.get(c.id, ""), unit.package) - for local in c.types.values(): - walk(local) - for nested in t.types.values(): - walk(nested) - - for top in unit.types.values(): - walk(top) - - # ---------------------------------------------------------------------------------------------- # leaves # ---------------------------------------------------------------------------------------------- -#: The model's own "not known". The graph stores ``start_line``/``end_line`` and nothing else, so -#: every column, every byte offset, and the whole span of a node it carries no lines for, are *not -#: projected* -- reported as this rather than as a ``0``, which would read as "column one, offset -#: zero" and index into a ``source`` that is ``""``. +#: The model's own "not known". The graph stores no column anywhere, and no byte offset on the +#: nodes listed in the module docstring -- reported as this rather than as a ``0``, which would read +#: as "column one, offset zero", a position and a wrong one. _UNKNOWN = -1 +def _byte_offsets(props: Props) -> Tuple[int, int]: + """``(start_byte, end_byte)`` -- the slice of the owning module's ``source`` this node's text is + -- or ``(-1, -1)`` when the projection carries no offsets for it. + + **Both or neither.** A half-known pair is the one shape that reads as data rather than as a gap: + ``(b0, -1)`` slices from ``b0`` to one byte before the end of the file, a wrong answer where + ``(-1, -1)`` is an empty one. + """ + b0, b1 = props.get("start_byte"), props.get("end_byte") + return (_UNKNOWN, _UNKNOWN) if b0 is None or b1 is None else (b0, b1) + + def span(props: Props) -> Optional[JSpan]: - """The line-only span the projection carries, or ``None`` when it carries no lines (an implicit - callable). Both columns and both byte offsets are :data:`_UNKNOWN`: the graph projects neither - (see the module docstring).""" + """The node's span, or ``None`` when the projection places it nowhere at all (an implicit + callable, which was never written). + + Lines are the graph's own; **columns are never projected** and stay :data:`_UNKNOWN`; byte + offsets come from ``start_byte``/``end_byte``, which codeanalyzer-java 3.2.0 writes on every + node whose text is a slice of its module's ``source``. Offsets without lines still make a span + -- that is the ``J_ANNOTATED_BY`` edge, which locates the annotation *application* the shared + ``:JAnnotation`` node cannot (see :func:`decorator`). + """ start, end = props.get("start_line"), props.get("end_line") - return None if start is None or end is None else JSpan(start=(start, _UNKNOWN), end=(end, _UNKNOWN), bytes=(_UNKNOWN, _UNKNOWN)) + offsets = _byte_offsets(props) + if start is None or end is None: + if offsets == (_UNKNOWN, _UNKNOWN): + return None + start = end = _UNKNOWN + return JSpan(start=(start, _UNKNOWN), end=(end, _UNKNOWN), bytes=offsets) + + +def body_span(props: Props) -> Optional[JSpan]: + """The callable's **body block**: ``body_start_byte`` opens it and the callable's own + ``end_byte`` closes it. + + ``None`` when either is absent -- an abstract or interface method has no body, an implicit + ``()`` was never written -- which is what makes :attr:`JCallable.code` fall back to the + declaration span, exactly as it does off ``analysis.json``. + + *The closing offset is measured, not assumed.* The projection carries no ``body_end_byte``, and + across both committed fixtures (``analysis_json/v2/{a1,a4}``, 1,182 callables carrying both + spans) there is **no callable** whose ``body_span.bytes[1]`` differs from its ``span.bytes[1]`` + -- a Java method declaration's last character *is* its body's closing brace. Lines: + ``body_start_line`` where the projection carries one, else :data:`_UNKNOWN`, and + :attr:`JCallable.code_start_line` falls back to the declaration's first line then; the end line + is the declaration's, which closes that same brace. + """ + b0, b1 = props.get("body_start_byte"), props.get("end_byte") + if b0 is None or b1 is None: + return None + return JSpan(start=(props.get("body_start_line", _UNKNOWN), _UNKNOWN), end=(props.get("end_line", _UNKNOWN), _UNKNOWN), bytes=(b0, b1)) def _unknown_span() -> JSpan: @@ -173,9 +180,14 @@ def docstring(props: Props) -> List[JComment]: def decorator(node: Props, edge: Props) -> JDecorator: - """An annotation use from its ``:JAnnotation`` node (keyed by name) and the ``J_ANNOTATED_BY`` - edge's ``arguments`` (the source spellings).""" - return JDecorator(name=node["name"], args=list(edge.get("arguments") or [])) + """An annotation use, from its ``:JAnnotation`` node (keyed by name) and the ``J_ANNOTATED_BY`` + edge's own properties: the ``arguments`` (the source spellings) and the application's position. + + The span rides the **edge** because the node cannot hold it: ``:JAnnotation`` is shared + vocabulary, deduped across every use site in the application, so it has no single position. The + edge carries the offsets and no lines, which is why :func:`span` builds a span from offsets + alone.""" + return JDecorator(name=node["name"], args=list(edge.get("arguments") or []), span=span(edge)) def field(props: Props, decorators: List[JDecorator]) -> JField: @@ -238,10 +250,9 @@ def body_node(props: Props, callee_signature: Optional[str]) -> JBodyNode: ``:JBodyNode`` at all; those figures are measured on the same analyzer's JSON, where the spans the key would have to agree with do exist.) """ - start, end = props.get("start_line"), props.get("end_line") return JBodyNode( kind=props["kind"], - span=None if start is None or end is None else JSpan(start=(start, _UNKNOWN), end=(end, _UNKNOWN), bytes=(_UNKNOWN, _UNKNOWN)), + span=span(props), callee=props.get("callee"), method_name=props.get("method_name"), receiver_expr=props.get("receiver_expr"), @@ -303,6 +314,7 @@ def callable_( is_entrypoint=bool(props.get("is_entrypoint", False)), entrypoint_frameworks=list(props.get("entrypoint_frameworks") or []), span=span(props), + body_span=body_span(props), ) @@ -337,14 +349,22 @@ def type_( def compilation_unit(props: Props, *, import_declarations: List[JImport], types: Dict[str, JType]) -> JCompilationUnit: + """The file, and with it the one text blob every node under it slices its own ``code`` out of + (:meth:`JCompilationUnit.slice`). + + ``source`` is read with ``.get`` -- **the deliberate exception** to this module's rule that every + non-boolean property the contract declares is read with ``props[...]``. A module the analyzer + could not read or could not decode carries no text, and that has to mean "no text for this whole + file", every node in it reporting ``""``, rather than an attach that raises over one file. + """ return JCompilationUnit( id=props["id"], package=props["package"], - source="", + source=props.get("source") or "", content_hash=props.get("content_hash"), imports=import_declarations, types=types, - span=_unknown_span(), + span=span(props) or _unknown_span(), ) diff --git a/cldk/analysis/python/neo4j/neo4j_backend.py b/cldk/analysis/python/neo4j/neo4j_backend.py index 86a63f2..acfe427 100644 --- a/cldk/analysis/python/neo4j/neo4j_backend.py +++ b/cldk/analysis/python/neo4j/neo4j_backend.py @@ -75,10 +75,14 @@ dangling reference and is silently dropped by the writer. Those edges never reach Neo4j, so the call graph here can be missing a small fraction of external-target edges. This is a producer bug, not a query bug. -* **Projection-lossy fields** (inherent to what the graph stores — see :mod:`reconstruct`): comments +* **Projection-lossy fields** (what this backend reads back — see :mod:`reconstruct`): comments collapse to a single docstring (module-level comments dropped); ``PyVariableDeclaration.value`` and - its column span, plus per-binding import detail, are not recoverable; the order of ``call_graph`` + its column span, plus per-binding import detail, come back empty; the order of ``call_graph`` edges and a callable's ``call_sites`` / ``local_variables`` is positional, not insertion order. + All but the comments stopped being the graph's limit at codeanalyzer-python 1.5.2, which projects + ``:PyVariable.value_json``, all six span properties wherever a span is declared, and + ``PY_IMPORTS.positions_json``; taking them up is python-sdk#396, and the floor stays 1.5.0 until + it does, so a served graph may not carry them either. Everything else round-trips identically to ``PyCodeanalyzer``. """ diff --git a/cldk/analysis/python/neo4j/reconstruct.py b/cldk/analysis/python/neo4j/reconstruct.py index 165377b..0172a6b 100644 --- a/cldk/analysis/python/neo4j/reconstruct.py +++ b/cldk/analysis/python/neo4j/reconstruct.py @@ -29,10 +29,19 @@ * Comments collapse to a single ``docstring`` string. We rebuild one ``PyComment(is_docstring=True)``; non-docstring comments, multiplicity and positions are not recoverable. Module-level comments are not projected at all, so ``PyModule.comments`` comes back empty. -* ``PyVariableDeclaration.value`` and ``start_column`` / ``end_column`` are not projected (only - ``initializer`` and the line span are), so they rehydrate as ``None`` / ``-1``. +* ``PyVariableDeclaration.value`` rehydrates as ``None`` and its columns as ``-1``: this module + reads ``initializer`` and the line span only. * ``PyModule.imports`` are reconstructed from the *aggregated* ``PY_IMPORTS`` edges (per-binding alias pairing and positions are lost). + +The last two were the projection's limits until codeanalyzer-python 1.5.2, which added +``:PyModule.source``, all six span properties (``start_column`` / ``end_column`` / ``start_byte`` / +``end_byte`` beside the line pair) wherever a span is declared, ``:PyVariable.value_json``, +``:PyBodyNode.callee_signature``, ``PY_IMPORTS.positions_json`` and a span on ``PY_DECORATED_BY``. +Reading them is python-sdk#396; until it lands they are the *backend's* limits, not the graph's, and +the attach floor stays 1.5.0, so a served graph may well not carry them. The one that already flows +free is a call site's columns -- :func:`callsite` reads them with a ``-1`` default, so a 1.5.2 graph +supplies them and an older one does not. """ from __future__ import annotations @@ -129,10 +138,12 @@ def callsite(props: Props, *, callee_signature: str | None = None) -> PyCallsite 1.4.0 emits one call site as a body node (#120), not a dedicated ``:PyCallSite`` label — the graph carries ``method_name`` / ``receiver_expr`` / ``receiver_type`` / ``return_type`` / - ``is_constructor_call`` and the line span, same as before. It does not project - ``argument_types`` or ``start_column``/``end_column`` — those fall back to their existing - empty/``-1`` defaults below, the same "projection-lossy field" shape as everything else in - this module. + ``is_constructor_call`` and the line span, same as before. ``argument_types`` is not projected at + all and falls back to its empty default below, the same "projection-lossy field" shape as + everything else in this module. ``start_column`` / ``end_column`` are read with a ``-1`` + default, so they are real on a graph emitted by codeanalyzer-python 1.5.2 or newer (which + projects all six span properties) and ``-1`` on anything older -- the floor is 1.5.0, so both + shapes are served. ``callee_signature`` is NOT one of ``props`` (the call node itself carries no such property — callee resolution lives on the separate ``PY_RESOLVES_TO`` edge to the resolved target, a @@ -168,8 +179,9 @@ def external_symbol(props: Props) -> PyExternalSymbol: def body_node(props: Props) -> BodyNode: """Rebuild a :class:`BodyNode` from a ``:PyBodyNode`` node's properties. - Line-only ``span``: the projection writes ``start_line`` / ``end_line`` and nothing finer, so - the columns and UTF-8 ``bytes`` offsets rehydrate as ``0`` — the same projection-lossy shape as + Line-only ``span``: this function reads ``start_line`` / ``end_line`` and nothing finer, so + the columns and UTF-8 ``bytes`` offsets rehydrate as ``0`` (codeanalyzer-python 1.5.2 projects + them; taking them up is python-sdk#396) — the same projection-lossy shape as :func:`callsite`, and the reason ``LocateResult.span`` documents which of its fields are real per backend. ``span`` stays ``None`` when the node carries no lines at all: the emitter prunes them from synthetic analysis vertices (``@entry`` / ``@exit`` / ``@formal_in:N``), which have no diff --git a/cldk/analysis/typescript/neo4j/neo4j_backend.py b/cldk/analysis/typescript/neo4j/neo4j_backend.py index ca5765d..1888204 100644 --- a/cldk/analysis/typescript/neo4j/neo4j_backend.py +++ b/cldk/analysis/typescript/neo4j/neo4j_backend.py @@ -16,7 +16,8 @@ """Neo4j-backed TypeScript analysis backend (read-only Cypher client) on the codeanalyzer-typescript schema-v2 graph vocabulary -- 1.2.0's ``can://`` grammar with the application moved outermost in -1.5.1, through the 1.5.2 pin. +1.5.1, through the 1.6.0 pin (the graph floor stays 1.5.2 -- the pin is what the SDK installs, +the floor what it requires of a graph). A drop-in alternative to :class:`TSCodeanalyzer`: the same query surface, every method answered by Cypher over a live graph that ``codeanalyzer-typescript --emit neo4j`` populated out of band. This diff --git a/cldk/analysis/typescript/neo4j/reconstruct.py b/cldk/analysis/typescript/neo4j/reconstruct.py index 5e84ab7..531270d 100644 --- a/cldk/analysis/typescript/neo4j/reconstruct.py +++ b/cldk/analysis/typescript/neo4j/reconstruct.py @@ -26,12 +26,19 @@ What the projection does **not** carry, and therefore comes back at the model's empty default (verified against the schema and the live graph, not assumed): -* ``TSModule.source`` -- the graph stores each node's own ``code`` text and its line span, never - the module text or byte offsets. A reconstructed node's ``span`` is therefore line-only +* ``TSModule.source`` -- this module reads each node's own ``code`` text and its line span, and + neither the module text nor byte offsets. A reconstructed node's ``span`` is therefore line-only (columns ``0``) with ``bytes = (0, len(code))``, and its private ``_source`` is set to its own ``code`` so the model's ``code`` property reads the text the graph projected for that node (``None`` when the graph carries none). A module is assembled with ``model_construct`` so the module-level source threading (which would overwrite that with ``""``) does not run. + + Since codeanalyzer-typescript 1.6.0 the graph *does* carry ``:TSModule.source`` (the whole file, + ``""`` only for an empty one) plus ``start_column`` / ``end_column`` / ``start_byte`` / + ``end_byte`` on all ten spanned labels, so this is the backend's ceiling now rather than the + projection's -- python-sdk#391 is taking it up, and the attach floor stays 1.5.2 meanwhile, so a + served graph may carry none of it. ``:TSCallable.code`` is kept upstream precisely because this + path reads it (codeanalyzer-typescript#204). * ``TSCallable.comments``, ``type_parameters``, ``overload_signatures``, ``body``, ``cfg``/``cdg``/``ddg``/``summary`` -- ``:TSCallable`` projects none of them; the call view is answered from ``:TSBodyNode {kind:'call'}`` by the backend's call-site accessors, not stored on diff --git a/cldk/models/java/__init__.py b/cldk/models/java/__init__.py index 586be98..9eab335 100644 --- a/cldk/models/java/__init__.py +++ b/cldk/models/java/__init__.py @@ -29,6 +29,8 @@ JGraphEdges, JImport, JType, + JViewDispatch, + JViewDispatchUnresolved, ) from .projections import JCallableOverview, JClassOverview @@ -46,6 +48,8 @@ "JGraphEdges", "JImport", "JType", + "JViewDispatch", + "JViewDispatchUnresolved", "JCallableOverview", "JClassOverview", "CRUDOperationType", diff --git a/cldk/models/java/models.py b/cldk/models/java/models.py index 240fe65..35f27b1 100644 --- a/cldk/models/java/models.py +++ b/cldk/models/java/models.py @@ -19,7 +19,8 @@ The wire is one containment tree: ``JAnalysis{analyzer, application}`` → ``JApplication{symbol_table{path → JCompilationUnit}, call_graph, param_in, param_out, artifacts, -dependencies, config_uses, config_reads_unresolved, entrypoint_report}`` → +dependencies, config_uses, config_reads_unresolved, view_dispatches, view_dispatches_unresolved, +entrypoint_report}`` → ``JCompilationUnit{types{name → JType}}`` → ``JType{fields{}, callables{signature → JCallable}, types{}}`` → ``JCallable{body{}, cfg, cdg, ddg, summary, types{}}``. Every node carries a ``can://`` ``id`` and a ``kind``; a unit carries its full ``source`` once and every node's text is a @@ -83,10 +84,10 @@ class JSpan(_Base): sums over ``getBytes(UTF_8)``). **``-1`` in any position means "not known", never zero.** A span rebuilt from the Neo4j - projection carries real lines and ``-1`` for both columns and both byte offsets, because the - graph writes ``start_line``/``end_line`` and nothing else -- a ``0`` there would read as column - one, offset zero, which is a position, and a wrong one. Off ``analysis.json`` every position is - the analyzer's own. + projection carries real lines and real byte offsets -- codeanalyzer-java 3.2.0 writes both -- and + ``-1`` for both columns, which the graph does not write at all; a ``0`` there would read as + column one, which is a position, and a wrong one. Off ``analysis.json`` every position is the + analyzer's own. """ start: Tuple[int, int] @@ -455,12 +456,12 @@ def code(self) -> str: and ``TreesitterJava.get_calling_lines`` were written against; the declaration slice (``span``) only when there is no body (abstract / interface methods). - That holds for a callable read from ``analysis.json``. One read from the Neo4j projection - instead carries the whole **declaration** — the graph projects one line range per callable - and no ``body_span`` — so its ``code`` starts at ``public …`` and *ends with* what this - property would return. Likewise :attr:`body` there holds the ``call`` nodes only, about 30% - of the graph's body nodes, so :attr:`call_sites` is complete and nothing else about the - body is. + It holds on both backends: codeanalyzer-java 3.2.0 projects ``body_start_byte``, so a + callable rebuilt from the Neo4j graph slices the same body block out of the same + ``:JModule.source`` (before 3.2.0 it carried the whole declaration, which is the floor + ``JNeo4jBackend`` now refuses below). What still differs there is :attr:`body`, which holds + the ``call`` nodes only — about 30% of the graph's body nodes — so :attr:`call_sites` is + complete and nothing else about the body is. """ return self._slice(self.body_span or self.span) @@ -469,13 +470,14 @@ def code_start_line(self) -> int: """The file line :attr:`code` starts on: the body block's first line, or the declaration's when there is no body. - **It differs by backend wherever the opening brace does not sit on the declaration's first - line** — 398 of daytrader8's 1,216 callables. The Neo4j projection carries one line range - per callable and no ``body_span``, so this is the *declaration's* first line there and the - *body block's* here, exactly as :attr:`code` is the declaration there and the body block - here. The two agree on every callable whose ``{`` is on the signature's own line. + **The body span's own first line, when it is known.** Off ``analysis.json`` it always is. + The Neo4j projection carries the body block as byte offsets, so :attr:`code` is the body + block on both backends, but a ``body_start_line`` beside them is not guaranteed — where it is + absent this falls back to the declaration's first line, which is the body block's too except + where the opening brace sits on a later line (398 of daytrader8's 1,216 callables). ``-1`` + only when the callable has no span at all: an implicit ``()``, which has no text. """ - if self.body_span is not None: + if self.body_span is not None and self.body_span.start[0] != -1: return self.body_span.start[0] return self.start_line @@ -861,6 +863,44 @@ class JConfigRead(_Base): prov: List[str] = [] +class JViewDispatch(_Base): + """One resolved view dispatch (codeanalyzer-java 3.3.0, spec 2026-09-11 § 4): the body node that + hands the request to a view template and the :class:`JArtifact` it reaches. + + ``src`` is the dispatching body node's id (``@:``) — a + ``RequestDispatcher.forward`` / ``include`` or ``sendRedirect`` call, a ``ModelAndView`` + construction or ``setViewName``, or a Spring controller's ``return``; ``dst`` is the artifact's + ``can:///artifact/`` id. ``via`` names the mechanism (``forward | include | redirect | + view-name | navigation``) and ``prov`` the tier that closed the target: ``["literal"]`` is a string + at the site, ``["dataflow"]`` a local or parameter traced over the L3/L4 substrate — both mean + exactly one target — and ``["table"]`` (3.3.1, § 4.5) a lookup into a static string table, which + is a **may-dispatch**: one edge per entry of the table, from the same site. Kept ``str`` rather + than ``Literal`` on purpose, as :class:`JConfigRead.reason` is: ``navigation`` is reserved and + unemitted today, and a closed type here would break on the analyzer release that fills it.""" + + src: str + dst: str + via: str + prov: List[str] = [] + + +class JViewDispatchUnresolved(_Base): + """A detected dispatch that closed on no artifact — first class, so a page nobody can trace stays + as visible as one that resolves. ``target`` is the decoded literal when there was one and + ``None`` for ``reason="non-literal"``; ``reason`` is ``non-literal`` / ``no-such-artifact`` (a + servlet URL, a ``*.faces`` route, a file outside the repository) / ``ambiguous`` (a view name + matching two templates); ``prov`` lists every tier attempted. ``callee`` is the dispatching + callee's ``@external`` id for a call site and the enclosing callable's id for a ``return`` site. + **JSON-only**: the projection has no node for a target that resolved to nothing.""" + + site: str + callee: str + target: Optional[str] = None + via: str + reason: str + prov: List[str] = [] + + class JApplication(_Base): """The application root. ``call_graph``/``param_in``/``param_out`` are absent below the level that computes them — empty here, never ``None``. @@ -888,6 +928,12 @@ class JApplication(_Base): config_uses: Optional[List[JConfigUse]] = None config_reads_unresolved: Optional[List[JConfigRead]] = None entrypoint_report: Optional[JEntrypointReport] = None + #: The 3.3.0 view-dispatch layer. ``None`` here means only "the key is absent": 3.3.x writes both + #: lists only when non-empty, so — unlike the 3.1.0 trio — no key on the wire is unconditional and + #: the backends decide "predates the pass" from the analyzer generation instead + #: (:data:`~cldk.analysis.java.backend.VIEW_DISPATCH_UNAVAILABLE`). + view_dispatches: Optional[List[JViewDispatch]] = None + view_dispatches_unresolved: Optional[List[JViewDispatchUnresolved]] = None def model_post_init(self, __context: Any) -> None: for path, unit in self.symbol_table.items(): diff --git a/docs/agent-api-reference.md b/docs/agent-api-reference.md index 460deb8..e10d132 100644 --- a/docs/agent-api-reference.md +++ b/docs/agent-api-reference.md @@ -46,8 +46,9 @@ disconnected old copy that the new application-prefix delete cannot reach. ## TypeScript -Status: leg 2.5b (`codeanalyzer-typescript` 1.5.2 pinned; graphs emitted by 1.5.2 or newer -served — see the floor below). What attaches +Status: leg 2.5b (`codeanalyzer-typescript` 1.6.0 pinned; graphs emitted by 1.5.2 or newer +served — the pin is what the SDK installs and the floor what it requires, two numbers that move +independently; see the floor below). What attaches today is the **1.x accessor surface** — symbol table, classes / interfaces / enums / type aliases / namespaces, methods, fields, call graph, call sites, decorators, externals, synthesized callables, the four bulk accessors and the repository-artifact layer — on both backends. @@ -154,12 +155,12 @@ documented empty comes back. | `get_application_view().param_in` / `.param_out` | empty — leg 2.5a reads **no** dataflow overlay (2.5b does). `.config_reads` and `.unresolved_imports` are empty for their own reasons: the config-read edge carries no `site`, so the view's entries would not be the ones in-process holds (`get_unresolved_config_reads()` is where they are reachable), and no accessor reads `TS_UNRESOLVED_IMPORT`. `.artifacts` / `.dependencies` / `.config_uses` **are** populated, from the same rows the dedicated accessors return | | `TSCallable.comments`, `type_parameters`, `overload_signatures`, `body`, `cfg`/`cdg`/`ddg`/`summary` | empty. `parameters` are populated from `parameters_json` on a 1.4.0 graph | | `TSEnumMember.value`; `TSModule.source` / `imports` / `comments`; decorator positions; a call site's `method_name`, receiver and argument facets | empty / `None`. `TSModule.exports` **is** populated from `exports_json`; `imports` stay empty on a rebuilt module — they live on edges the containment fetch does not walk, and `get_imports()` is what reads them | -| `code` on any node | the text the graph projected for that node, on a line-only span (columns `0`) | +| `code` on any node | the text the graph projected for that node, on a line-only span (columns `0`). codeanalyzer-typescript 1.6.0 added `start_column` / `end_column` / `start_byte` / `end_byte` to every spanned label; this backend does not read them yet (#391) | | `get_call_targets(sig)` | an unresolved call site contributes `""` (in-memory: the call's `method_name`) | | `get_synthesized_callables()` | keyed by the anonymous node's own id (the analyzer's older compatibility key is JSON-only) | -| `locate(path, line)` at module scope | `source == ""` plus a second `module_source_unavailable` diagnostic — `:TSModule` carries no `source`. In-memory: the module's text | -| `get_source(node_id)` for a **body-node** id | **raises `NotImplementedError`** — the graph carries no text below callable granularity. In-memory: the span's slice | -| `LocateResult.span` columns and byte offsets | placeholders; lines are real on both backends | +| `locate(path, line)` at module scope | `source == ""` plus a second `module_source_unavailable` diagnostic. `:TSModule` **does** carry `source` since codeanalyzer-typescript 1.6.0 — this backend does not read it yet (#391), and the graph floor is 1.5.2, so a served graph may legitimately not have it either. In-memory: the module's text | +| `get_source(node_id)` for a **body-node** id | **raises `NotImplementedError`** — this backend resolves no text below callable granularity: `:TSBodyNode` projects no `code`, and the module source plus byte offsets that would let it slice one (1.6.0) are unread (#391). In-memory: the span's slice | +| `LocateResult.span` columns and byte offsets | placeholders; lines are real on both backends. Carried by a 1.6.0 graph, unread here (#391) | | `get_entrypoint_coverage()` | the anchor's `entrypoint_report_json` string, parsed — same report as in-memory, no lossiness. A graph without the property answers `entrypoint_report_unavailable` rather than empty-but-clean fields | Two more hold on **both** backends. `get_entrypoint_classes()` covers **classes only**: the wire @@ -238,8 +239,9 @@ Java-specific facts: accessors** — `get_callables_overview`, `get_method_bodies`, `get_decorated_callables`, `get_callsites_for`, `get_external_symbols`, `get_entrypoints` / `get_entrypoint_classes` / `get_entrypoint_coverage`, `get_artifacts` / `get_dependencies` / `get_config_keys` / -`get_config_uses` / `get_unresolved_config_reads` / `get_config_readers`, and `get_interfaces` / -`get_enums` / `get_enum_members` / `get_records`. Five rules: +`get_config_uses` / `get_unresolved_config_reads` / `get_config_readers`, `get_view_dispatches` / +`get_unresolved_view_dispatches` / `get_view_dispatchers`, and `get_interfaces` / `get_enums` / +`get_enum_members` / `get_records`. Six rules: - **`get_entrypoint_coverage` reads the report from codeanalyzer-java 3.1.0 on.** 3.1.0 (codeanalyzer-java#235) emits the entrypoint pass's own coverage record — `entrypoint_report` on @@ -253,6 +255,19 @@ accessors** — `get_callables_overview`, `get_method_bodies`, `get_decorated_ca count of syntactically-marked callables is not a coverage record. The marks themselves are real and unambiguous — 133 callables and 66 types of daytrader8's 1,216 and 149, 1,501 callables and 904 types of ThingsBoard's — and `get_entrypoints` / `get_entrypoint_classes` return those. +- **`get_view_dispatches` reads codeanalyzer-java 3.3.0's view layer, and is the one accessor + gated on the analyzer generation.** JSP, Facelets and Thymeleaf templates are `:Artifact` nodes + with `roles: ["view-template"]`, and a `J_DISPATCHES_TO` edge (`view_dispatches[]` on the wire) + runs from the body node that hands the request over — a `forward` / `include` / `sendRedirect` + call, a `ModelAndView` construction or `setViewName`, or a Spring controller's `return` — to the + artifact it reaches, with `via` naming the mechanism and `prov` the tier: `literal` and + `dataflow` mean exactly one target, `table` (3.3.1) is a may-dispatch over a static string table, + one edge per entry. `get_view_dispatchers(path)` resolves the sites to their callables; + `get_unresolved_view_dispatches()` is the JSON-only record of what closed on nothing, so the + Neo4j backend refuses it rather than answering `[]`. Unlike the 3.1.0 trio there is no + always-present key to probe, so a pre-3.3.0 analysis is refused from `analyzer.version` / + `analyzer_version`. On daytrader8 with 3.3.3: 37 edges at level 1–2 (3 literal, 34 table), 54 at + level 4, 19 of 23 JSPs reached. - **A marker matches an annotation by simple name.** `get_decorated_callables(["Test"])`, `["@Test"]` and `["org.junit.Test"]` are the same query: the Java wire carries an annotation's simple name, so both sides are compared on the segment after the last `.` with a leading `@` @@ -307,8 +322,8 @@ java = CLDK.java(backend=Neo4jConnectionConfig( application_name="daytrader8")) ``` -**Analyzer floor: codeanalyzer-java 3.1.1** (the pin is `[tool.backend-versions]` in -`pyproject.toml` and is ahead of the floor; `--emit neo4j` always runs at level 4 and +**Analyzer floor: codeanalyzer-java 3.2.0** (the pin is `[tool.backend-versions]` in +`pyproject.toml` and is equal to the floor; `--emit neo4j` always runs at level 4 and forces external calls). Attaching to a graph refuses rather than answering empty, and the message names what it found and the floor: @@ -316,15 +331,21 @@ names what it found and the floor: | --- | --- | | no `J_HAS_MODULE` / `J_HAS_METHOD` / `J_HAS_BODY_NODE` / `J_CALLS` (a pre-3.0.1 Java graph, a graph from another language's analyzer, an empty database) | refused — `GraphSchemaMismatch`, naming the missing types and the ones found | | no `:JApplication {id: can://}` | refused — that root is the anchor every statement walks out from, so a wrong application would make every answer empty | -| `analyzer_version` below 3.1.1, unreadable, or absent | refused | -| 3.1.1 and newer | served, silent | - -3.1.1 moved the application to the outermost segment of the `can://` grammar -(`can:///java//…`, was `can://java//…`) and made `@external` ids language-neutral -(`can:///@external/…`). A 3.1.0 graph has every relationship type and the right body-node -shape, and still answers every prefix-scoped statement with zero rows, so it is refused rather than -served. **Migration:** re-emit with `codeanalyzer-java>=3.1.1 --emit neo4j`, wiping the database -first — old and new ids do not collide. +| `analyzer_version` below 3.2.0, unreadable, or absent | refused | +| 3.2.0 and newer | served, silent | + +3.2.0 is the release whose projection carries the canonical text model: `:JModule.source` holds each +file whole, and a `start_byte`/`end_byte` pair reaches `:JType`, `:JField`, `:JVariable`, +`:JCallable` (plus `body_start_byte`) and `:JBodyNode`, so every node's text is a slice of its own +module. A 3.1.x graph carries text as `:JCallable.code` and no byte offsets at all, so on it every +*other* node's `code` rebuilds as `""` — served silently as though the file held nothing — which is +why it is refused rather than degraded. Two generations earlier, 3.1.1 moved the application to the +outermost segment of the `can://` grammar (`can:///java//…`, was `can://java//…`) and +made `@external` ids language-neutral (`can:///@external/…`); a 3.1.0 graph has every +relationship type and the right body-node shape and still answers every prefix-scoped statement with +zero rows. **Migration:** re-emit with `codeanalyzer-java>=3.2.0 --emit neo4j`. Wipe the database +first when the graph predates 3.1.1 — those ids do not collide with the current ones, so the two +generations would coexist rather than overwrite. Locally the same rule applies to the cache: an `analysis.json` with no `schema_version` (1.x output) is refused with a re-run message, not parsed into an empty application. @@ -344,14 +365,13 @@ last two from codeanalyzer-java 3.1.0; they raise on an older analysis rather th and issuing no new Cypher. Note what each one is: `get_imports()` is the project's **distinct sorted set** of import targets (the projection aggregates a module's imports per target, so file order is not recoverable); `get_variables()` is **local variables only**, keyed by the -`"."` call-graph key and ordered by `(line, name)` because `:JLocal` carries a -line-only span (fields are `get_fields`, parameters are `get_method_parameters`, and an unexpected +`"."` call-graph key and ordered by `(line, name)` because `:JLocal` carries no +column (fields are `get_fields`, parameters are `get_method_parameters`, and an unexpected keyword raises `TypeError` rather than being ignored); `get_class_hierarchy()` reads each declaration's own `base_types`/`interfaces` rather than `J_EXTENDS`/`J_IMPLEMENTS`, which is why library supertypes are in it — those two relationships join **8** of daytrader8's type pairs where the declarations join **103**; `get_methods_with_annotations()` keys by the spelling you passed and -its `body` is `JCallable.code`, so it is the body block in-process and the whole declaration over -the graph; `get_call_targets()` is simple-name matching with no overload resolution (use the call +its `body` is `JCallable.code`, the body block on either backend; `get_call_targets()` is simple-name matching with no overload resolution (use the call graph for what actually runs); `get_calling_lines()` is absolute **file** lines. **Three accessors still raise `NotImplementedError`** — `get_service_entry_point_classes` / `get_service_entry_point_methods`, which the **§4 erratum** in @@ -369,24 +389,26 @@ names its upstream issue where there is one: (`p.Outer.m(int).$anon$0`). External callees are not in this graph. - **CRUD accessors raise** (`codeanalyzer-java#187`): schema v2 carries no CRUD enrichment, and an empty list would read as "this application touches no database". -- **Over Neo4j, `JCallable.code` is the whole declaration**, not the body block (upstream - `codeanalyzer-java#176`), `code_start_line` is the declaration's first line rather than the body - block's (they differ on 398 of daytrader8's 1,216 callables), a module carries no `source` at all, - and every column and byte offset is `-1` — "not known", never zero. Line numbers are exact. The - one exception is a `JCallableParameter`, which round-trips out of `:JCallable.parameters_json` - with the analyzer's own columns *and* byte offsets; those offsets index a module `source` this - backend does not carry, so they locate the parameter in the file on disk and nothing else. -- **`get_source` inherits that difference, and so does `LocateResult.source`.** For a callable it is - the **body block** on the `analysis.json` backend and the whole **declaration** over Neo4j; the - relation is exact and total — the declaration *ends with* the body block — and asserted on all - 1,117 body-bearing callables of daytrader8 by the live suite, so either text can be relied on for - what it is. For a **body node** (the statement or call site `locate` returns in `node_id`) there - is text only on the `analysis.json` backend: `:JBodyNode` carries a line range and no text, and - there is no module `source` to slice one out of, so `get_source` raises over Neo4j and `describe` - leaves `source=None` — never the enclosing declaration standing in for it. A **module-scope** - `locate` over Neo4j is `source=""` plus a `module_source_unavailable` diagnostic. A - `resolve_value` ref (a `formal_in` vertex) has no text on either backend: it is a dataflow - position, not a region of the file. +- **Over Neo4j, every column is `-1`** — "not known", never zero. Line numbers and byte offsets + are exact: the projection writes `start_line`/`end_line` and a `start_byte`/`end_byte` pair, and + no column anywhere. A `JCallableParameter` is the one node whose columns are real, round-tripping + out of `:JCallable.parameters_json` with the analyzer's own span. +- **Text is the same on both backends since codeanalyzer-java 3.2.0.** `JCallable.code`, `get_source`, + `LocateResult.source` and `describe` all answer the same slice of the same file, at every + granularity: a callable's **body block**, a type's or field's or local's declaration, a single + statement or call site, and a module's whole text at module scope. Each is sliced out of + `:JModule.source` by the node's own byte offsets, so equality — not `endswith`, not "the same + length" — is what the live suite asserts, on all 1,117 body-bearing callables of daytrader8. + Before 3.2.0 the graph carried one line range per callable and text only as `:JCallable.code`, so + a callable came back as the whole **declaration** (which *ends with* the body block), + `code_start_line` was the declaration's first line rather than the body block's, a body node had + no text at all, and a module-scope `locate` was `""` plus a `module_source_unavailable` + diagnostic (upstream `codeanalyzer-java#176`). Three cases still have no text, on **both** + backends and for the same reason each time — nothing in the file to point at: an implicit + callable (a compiler-generated `()`), an `@external` callable, and a `resolve_value` ref (a + `formal_in` vertex is a dataflow position, not a region of the file). `module_source_unavailable` + survives as a *data* diagnostic: it fires on a module whose text the analyzer could not read or + decode, which on a 3.2.0 graph of daytrader8 is none of the 141. - **Over Neo4j, `cfg`/`cdg`/`ddg`/`summary` are `None` and `param_in`/`param_out` are empty at every level**, and re-ingesting will not change that: `--emit neo4j` already forces level 4, so the analyzer computed them — this leg simply does not project them back out (leg 3b reads the @@ -505,9 +527,13 @@ class LocateResult: | between two callables | same as module scope; it never snaps to the nearest callable | | file not analysed | diagnostic `file_not_in_graph` — distinct from a file that doesn't exist | -**Gotcha:** over Neo4j, module-scope `source` is empty and carries `module_source_unavailable`. -`:PyModule` nodes genuinely do not store source text. The local backend returns it. Do not read -an empty `source` as "no code there". +**Gotcha:** on **Python and TypeScript** over Neo4j, module-scope `source` is empty and carries +`module_source_unavailable`; the local backend returns it. Do not read an empty `source` as "no code +there". The graph stopped being the reason: `:PyModule.source` lands in codeanalyzer-python 1.5.2 and +`:TSModule.source` in codeanalyzer-typescript 1.6.0, and these two backends do not read it yet +(#396, #391). **Java** is the one that does, since codeanalyzer-java 3.2.0: module-scope `source` is +the file's text on both of its backends, and the diagnostic is left for a module whose text the +analyzer could not read. --- @@ -956,7 +982,7 @@ Any accessor may attach these. They exist so an empty result is never ambiguous. | --- | --- | | `module_scope` | the position is real, but outside any callable | | `file_not_in_graph` | the file was not analysed — not "does not exist" | -| `module_source_unavailable` | this backend cannot supply module text (Neo4j) | +| `module_source_unavailable` | the backend cannot supply module text — Python and TypeScript over Neo4j always (#396, #391); Java only where the analyzer could not read the file | | `entrypoint_report_unavailable` | **you cannot tell whether an empty entrypoint list is real** | | `level_too_low` | the graph lacks the analysis level this question needs — *unanswerable, not negative* | | `graph_schema_mismatch` | analyzer/graph generation mismatch (raised, not attached) | diff --git a/docs/design/specs/2026-09-10-java-3.2.0-text-model.md b/docs/design/specs/2026-09-10-java-3.2.0-text-model.md new file mode 100644 index 0000000..edd28b1 --- /dev/null +++ b/docs/design/specs/2026-09-10-java-3.2.0-text-model.md @@ -0,0 +1,142 @@ +# Java 3.2.0 text model: the Neo4j projection catches up to its own JSON + +**Status:** decided 2026-09-10. Single repo (`python-sdk`), one work item, `2.0.0rc6`. + +## Contract-Impact Triage + +**Does this change the schema v2 output? No — it makes the Java Neo4j projection *conform* to it.** + +The canonical schema has mandated this text model since v2 was written +(`cldk-devtools/skills/designing-cldk-changes/references/canonical-schema.md`): + +> Source text is stored **once per file, on the module node**, as `source`, and every node's text is +> a **slice** of it. […] To make slicing O(1), **spans carry byte/char offsets** alongside +> `line:col`. […] it subsumes any per-callable `code` field. + +`module.source` is listed there as **level 1, cardinality 1** — mandatory. `span` is +`{start, end, bytes}`, which is `JSpan` in `cldk/models/java/models.py` already. + +**Measured, not assumed:** `analysis.json` has conformed since **3.1.0**. The committed a4 fixture +(`tests/resources/java/analysis_json/v2/a4/analysis.json.gz`, `analyzer.version == "3.1.0"`) carries +`module.source` (8792 bytes on the first module), `span.bytes` on module / type / callable, a +`body_span` with its own byte pair, and **no `code` key on a callable at all**. The local backend +therefore already implements the consumer rule: `_Spanned._slice(span)` → `JCompilationUnit.slice` +→ `source_bytes[b0:b1].decode("utf-8")`. + +So the flat `start_byte` / `end_byte` / `body_start_byte` properties in 3.2.0 are the **Neo4j +projection flattening `span.bytes`** (Neo4j has no nested properties), not new schema fields. That +`grep start_byte cldk/models/` returns nothing is correct and stays correct. + +| Change type | Analyzers | SDKs | Docs | +| --- | --- | --- | --- | +| Schema v2 **conformance** (text model) | `codeanalyzer-java` 3.2.0 (done upstream) | `python-sdk` — Neo4j path only | `docs/agent-api-reference.md` | + +**Local `JCodeanalyzer`: zero changes.** The entire change is +`cldk/analysis/java/neo4j/{neo4j_backend,reconstruct}.py`. + +### What 3.2.0 projects + +Carries literal text: `:JModule.source` (whole file, 141/141), `:Artifact.source` (242/242, +truncated at `--artifact-text-max-bytes`, default 262144; absent under `--no-artifact-text`), +`:JCallable.code` (1127 rows, retained as a courtesy and **not** a general rule). + +Sliceable, via `start_byte`/`end_byte` into the owning module's `source`: `:JField` 659/659, +`:JVariable` 863/863, `:JType` 152/152; `:JCallable` 1127/1229 with `body_start_byte` on 1097; +`:JBodyNode` 6726/13544. The annotation *application*'s position rides `J_ANNOTATED_BY` +(817 edges with `start_byte` + `_k`). + +Never text, and each already accounted for on this side: + +| Category | Rows | Why the SDK is unaffected | +| --- | --- | --- | +| synthetic body vertices (`actual_in`/`formal_in`/`entry`/`exit`/`actual_out`/`formal_out`) | 6818 | `reconstruct` rebuilds only `call` nodes (~30%); the port lattice is not rebuilt at all | +| `@external` callables | 1205 | no module, no file — and they stay **in scope** by design (`can:///`, not `can:///java/`), so they must degrade, never raise | +| synthesized implicit `()` | 102 | already `is_implicit`, projected only when true; never written in source, so no text exists to want | +| `:JAnnotation` / `:JPackage` / `:ConfigKey` / `:JApplication` | 480 | shared-vocabulary nodes, deduped across use sites, so no single position | + +`1229 - 1127 = 102` — the callables without offsets are **exactly** the implicit constructors. There +is no callable whose text `:JCallable.code` can supply and a slice cannot. + +## Decisions + +**D1 — the analyzer floor moves to 3.2.0.** `_ANALYZER_FLOOR` (`neo4j_backend.py:216`) goes from +`(3, 1, 1)` to `(3, 2, 0)`. The mechanism already exists: `_probe_schema` reads +`:JApplication.analyzer_version` and refuses below the floor, naming what it found. + +*Cost, recorded because it was weighed and accepted:* a 3.1.x graph is refused at attach rather than +answering with `""` text and an honest lossiness note. Every live Java Neo4j suite needs its graph +re-emitted by 3.2.0 before it can run — they are `skipif`-gated on `CLDK_TEST_NEO4J_*`, so the +offline suite stays green either way, but the live evidence is unavailable until the re-emit. + +*Why a version check and not a data probe*, given the house rule that a probe reads the data: the +floor is a **generation** question, not a capability one. `_probe_schema`'s docstring already +records the precedent — a 3.1.0 graph carries every relationship type the probe looks for and then +answers every prefix-scoped statement with zero rows, so version was the only thing between a caller +and a silent empty. `:JModule.source` is a fine capability probe and a poor generation probe. + +**D2 — Java only; the siblings are follow-ups.** `codeanalyzer-python` and `codeanalyzer-typescript` +are non-conformant the same way, and the SDK compensates for each with a documented fiction: + +| Analyzer | The compensation | +| --- | --- | +| `codeanalyzer-typescript` | `typescript/neo4j/reconstruct.py:91` fabricates `bytes=(0, len(code))` — an offset into the *node's own text*, not into the module source; `_with_code` at `:94` | +| `codeanalyzer-python` | `python/neo4j/neo4j_backend.py:2075` — `source=cprops.get("code") or ""` | + +Both get their own issue on their own repo once this lands. No epic: they ship on their own clocks +and share no PR with this change. + +**D3 — one work item, `2.0.0rc6` off `release/2.0`.** One PR closes it; the rungs are checkboxes. + +**D4 — the graph stops reading `:JCallable.code`.** Slice only. This is what closes the parity +divergence: `cldk/analysis/java/backend.py:538-544` compares the two backends with +`neo.code.endswith(ref.code)` *because* the graph's `code` is the whole declaration where the local +backend's is the body block. With `body_start_byte` the graph slices the body block too, and the +assertion becomes an equality. + +`_ProjectedText` (`reconstruct.py:104-123`) — the stand-in whose `slice()` deliberately ignores the +span — is deleted, and with it `thread_code` and `_projected_code` (`neo4j_backend.py:591-602`). + +## Work + +- [ ] `_ANALYZER_FLOOR` → `(3, 2, 0)`, docstring rewritten to say what 3.2.0 is the floor *for*. +- [ ] `reconstruct.span()` reads `start_byte`/`end_byte` into `JSpan.bytes`; `_UNKNOWN` survives only + for the nodes that genuinely carry no offsets. +- [ ] `:JModule.source` threaded onto the reconstructed `JCompilationUnit`. Read as + `props.get("source", "")`, **the deliberate exception** to the contract that every non-boolean + property is read with `props[...]`: an unreadable or non-UTF-8 file means "no text for this + whole file", degrading per module rather than raising per node. +- [ ] `JCallable.body_span` rebuilt from `body_start_byte`. **Measure first** whether the callable's + own `end_byte` closes the body block; the briefing gives no `body_end_byte`, and guessing + silently truncates or over-reads every method body. +- [ ] Delete `_ProjectedText`, `thread_code`, `_projected_code`. +- [ ] `J_ANNOTATED_BY.start_byte` + `_k` → the annotation application's span. +- [ ] `backend.py:538-544`: `endswith` → equality, with the reason updated. +- [ ] `conftest.py:89` fake-driver default `analyzer_version` → `"3.2.0"`; the + `test_java_schema_probe.py` above/below parametrizations and its `match="3.1.1 or newer"`. +- [ ] Rewrite the four measured lossiness entries in `reconstruct.py`'s module docstring + (`:35-39`, `:40-49`, `:51-53`) and the matching text in `neo4j_backend.py:94-98` and + `docs/agent-api-reference.md`. Each was measured against a live graph; each is re-measured, not + edited by inference. +- [ ] Pin `codeanalyzer-java==3.2.0` (`pyproject.toml:46`, `:89`). `release.yml` fetches + `releases/tags/v` and requires exactly `codeanalyzer-.jar`, so the pin is the only + place the jar version is stated. + +## Caveats + +- **`body_end_byte` is not in the projection's inventory.** Assuming the declaration's `end_byte` + closes the body is plausible and unverified. Measure it. +- **`:JModule.source` has no truncation flag.** `:Artifact.source` has `text_truncated` and + `extraction`; a module has neither in the inventory. If a large file can be truncated silently, a + slice past the cut reads as empty rather than as unavailable — the one failure shape that looks + like data instead of a gap. Confirm upstream before trusting a slice's tail. +- **`:JBodyNode` is 6726/13544 — under half.** The guard is not decoration. `reconstruct` rebuilds + only `call` nodes today, so the exposure is smaller than the ratio suggests, but the rule holds: + check the offsets exist, never assume them from the node kind. + +## Definition of done + +The offline suite is green with no live server. A 3.1.2 graph is refused at attach by version, +naming the floor. On a re-emitted 3.2.0 daytrader8 graph: `JField` / `JVariable` / `JType` / +`JBodyNode` return real text where they returned `""`; a method body off the graph **equals** the +same method body off `analysis.json`; and a callable with no offsets (an implicit `()`) and an +`@external` callable both return an empty text without raising. diff --git a/pyproject.toml b/pyproject.toml index dc5e92c..d489d08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cldk" -version = "2.0.0-rc.5" +version = "2.0.0-rc.7" description = "The official Python SDK for Codellm-Devkit." readme = "README.md" license = { text = "Apache-2.0" } @@ -35,15 +35,15 @@ dependencies = [ "tree-sitter-java==0.23.5", "tree-sitter-python==0.23.6", "tree-sitter-javascript==0.23.1", - "codeanalyzer-python==1.5.1", - "codeanalyzer-typescript==1.5.3", + "codeanalyzer-python==1.5.2", + "codeanalyzer-typescript==1.6.0", ] [project.optional-dependencies] # The Neo4j-backed analysis backends (read-only; no analyzer is invoked). neo4j = ["neo4j>=5.14,<7"] # The local Java backend: the analyzer wheel carries the jar and a bundled JVM (jdk4py). -java = ["codeanalyzer-java==3.1.2"] +java = ["codeanalyzer-java==3.3.3"] # Everything. `codeanalyzer-python` and `codeanalyzer-typescript` are still hard # dependencies; #340 moves them here, and this list grows when it does. all = ["cldk[java]", "cldk[neo4j]"] @@ -86,9 +86,9 @@ include = [ ] [tool.backend-versions] -codeanalyzer-java = "3.1.2" -codeanalyzer-python = "1.5.1" -codeanalyzer-typescript = "1.5.3" +codeanalyzer-java = "3.3.3" +codeanalyzer-python = "1.5.2" +codeanalyzer-typescript = "1.6.0" ######################################## # Tool configurations diff --git a/tests/analysis/java/conftest.py b/tests/analysis/java/conftest.py index 7b6db63..bb7bcad 100644 --- a/tests/analysis/java/conftest.py +++ b/tests/analysis/java/conftest.py @@ -86,7 +86,7 @@ class FakeDriver: the ``:JApplication {id}`` anchor testable by behaviour rather than by grepping the statement.""" - def __init__(self, rel_types=V2_RELATIONSHIP_TYPES, responder=None, analyzer_version="3.1.1", application_name=None) -> None: + def __init__(self, rel_types=V2_RELATIONSHIP_TYPES, responder=None, analyzer_version="3.2.0", application_name=None) -> None: self.rel_types = set(rel_types) self.analyzer_version = analyzer_version self.application_name = application_name diff --git a/tests/analysis/java/test_java_addressing.py b/tests/analysis/java/test_java_addressing.py index 71a8ea6..7a6ee75 100644 --- a/tests/analysis/java/test_java_addressing.py +++ b/tests/analysis/java/test_java_addressing.py @@ -82,8 +82,9 @@ def _local(payload: str) -> JCodeanalyzer: class _BodyNodeResponder: """The two statements the graph backend issues in the offline suites: the per-callable body-node fetch (leg 3b Task 1) and the port-lattice probe (Task 2). Both are answered out of the same - fixture, in the graph's own vocabulary (a global ``id``, ``kind``, a line-only span and the - ``J_RESOLVES_TO`` target's id as ``callee``), so the rows are shaped like the projection's + fixture, in the graph's own vocabulary (a global ``id``, ``kind``, the span's lines *and* byte + offsets -- codeanalyzer-java 3.2.0 projects both -- and the ``J_RESOLVES_TO`` target's id as + ``callee``), so the rows are shaped like the projection's rather than like the model's -- and the probe's answer is the fixture's own fact, not a constant: it is ``True`` exactly when some ``formal_in`` of the payload has an outgoing dependence edge, which is what the graph would report. @@ -105,7 +106,15 @@ def __init__(self, application: JApplication) -> None: def _walk(self, t) -> None: for c in t.callables.values(): self.rows[c.id] = [ - {"id": java_body_node_id(c.id, key), "kind": n.kind, "s": n.start_line if n.span else None, "e": n.end_line if n.span else None, "callee": n.callee} + { + "id": java_body_node_id(c.id, key), + "kind": n.kind, + "s": n.start_line if n.span else None, + "e": n.end_line if n.span else None, + "sb": n.span.bytes[0] if n.span else None, + "eb": n.span.bytes[1] if n.span else None, + "callee": n.callee, + } for key, n in c.body.items() ] for local in c.types.values(): @@ -402,18 +411,15 @@ def test_describe_accepts_a_locate_result(both): assert described[0].kind == found.body.kind -def test_a_body_node_hydrates_only_where_the_text_exists(analysis_json): - """The documented ``get_source`` divergence, on the finer grain: the local backend slices the - statement out of the module's real text; the graph carries none below callable granularity, so - the position is *found* and its source is ``None`` — never the enclosing declaration.""" +def test_a_body_node_hydrates_the_same_statement_on_both_backends(analysis_json): + """The ``get_source`` divergence that 3.2.0 closes, on the finest grain: the local backend slices + the statement out of the module's real text, and so does the graph now that the projection + carries the body node's own byte offsets. Not "the same length" or "contained in" — the same + string, because both are the same slice of the same file.""" local, graph = _local(analysis_json), _graph(analysis_json) found = next(r for line in range(600, 700) if (r := local.locate(TRADE_DIRECT_FILE, line)).body is not None) - assert local.describe([found])[0].source - assert graph.describe([found])[0].source is None - assert local.get_source(found.node_id) - with pytest.raises(KeyError) as e: - graph.get_source(found.node_id) - assert "no recoverable source" in str(e.value) + assert local.describe([found])[0].source == graph.describe([found])[0].source != None + assert local.get_source(found.node_id) == graph.get_source(found.node_id) def test_describe_answers_a_ref_resolve_value_just_minted(both): diff --git a/tests/analysis/java/test_java_addressing_live.py b/tests/analysis/java/test_java_addressing_live.py index 5c91f2b..12de057 100644 --- a/tests/analysis/java/test_java_addressing_live.py +++ b/tests/analysis/java/test_java_addressing_live.py @@ -32,17 +32,17 @@ CLDK_TEST_JAVA_CACHE=/path/to/dir \ # a level-4 reference analysis.json uv run pytest tests/analysis/java/test_java_addressing_live.py -**The two tolerances, each with its cause, both asserted rather than skipped:** - -* ``LocateResult.source`` and :meth:`get_source` on a callable are the **body block** locally and - the whole **declaration** over Neo4j, which *ends with* it (codeanalyzer-java#176: the graph - carries one line range per callable and no ``body_span``). Asserted as ``endswith``. -* Every column and byte offset is ``-1`` over Neo4j -- the projection writes ``start_line`` / - ``end_line`` and nothing else -- so spans are compared on their **lines**. - -A body node's *source* is not a tolerance but a documented absence: the graph carries no text below -callable granularity, so :meth:`describe` fills it locally and leaves it ``None`` over Neo4j, and -that is asserted too. +**The one tolerance, asserted rather than skipped:** every column is ``-1`` over Neo4j -- the +projection writes ``start_line`` / ``end_line`` and byte offsets, and no column anywhere -- so spans +are compared on their **lines**, and their byte offsets are compared for equality. + +**Text is no longer a tolerance.** codeanalyzer-java 3.2.0 projects ``:JModule.source`` plus a +``start_byte``/``end_byte`` pair down to the body nodes, so ``LocateResult.source``, +:meth:`get_source` and :meth:`describe` are asserted **equal** on both backends -- the same slice of +the same file, at every granularity including a single statement. Before 3.2.0 the graph carried one +line range per callable and no ``body_span``, this suite asserted ``endswith`` on a callable, and a +body node's source was ``None`` over Neo4j (codeanalyzer-java#176). That is the divergence the 3.2.0 +floor exists to have closed. Read-only, like every other Neo4j suite here. """ @@ -154,17 +154,20 @@ def test_locate_many_agrees_on_every_callable_and_every_module(backends): assert a.body is None or a.body.callee is None or a.body.callee == b.body.callee, where assert (a.span.start[0], a.span.end[0]) == (b.span.start[0], b.span.end[0]), where if a.callable is not None: - assert b.source.endswith(a.source), f"{where}: the graph's text is the declaration, which must end with the body block" + assert b.source == a.source, f"{where}: the two backends sliced different text out of the same file" with_body += a.body is not None assert with_body > 100, "no position landed on a body node; the comparison proved nothing about them" -def test_a_module_scope_result_says_the_graph_has_no_module_text(backends): +def test_a_module_scope_result_carries_the_module_text_on_both_backends(backends): + """``module_source_unavailable`` is a *data* diagnostic, not a backend one: it fires when the unit + carries no ``source``, which on a 3.2.0 graph is no unit at all (141/141 carry it). A graph that + lost a file's text would still say so here, and say it per module.""" ref, neo = backends path = next(iter(ref.get_symbol_table())) assert [d.code for d in ref.locate(path, 1).diagnostics] == ["module_scope"] - assert [d.code for d in neo.locate(path, 1).diagnostics] == ["module_scope", "module_source_unavailable"] - assert neo.locate(path, 1).source == "" and ref.locate(path, 1).source + assert [d.code for d in neo.locate(path, 1).diagnostics] == ["module_scope"] + assert neo.locate(path, 1).source == ref.locate(path, 1).source != "" def test_the_body_node_ids_are_the_ones_the_graph_carries(backends): @@ -275,18 +278,19 @@ def test_get_source_holds_the_documented_relation_on_every_callable(backends): for key, row in sorted(ref._addressing.by_key.items()): if row.callable.is_implicit: continue - assert neo.get_source(key).endswith(ref.get_source(key)), key + assert neo.get_source(key) == ref.get_source(key), key compared += 1 assert compared == 1117, compared -def test_describe_fills_a_callable_on_both_and_a_body_node_only_locally(backends): +def test_describe_fills_the_same_text_on_both_backends(backends): + """A callable and a single statement, both granularities: 3.2.0 puts byte offsets on the body + nodes too, so ``describe`` no longer answers ``None`` over Neo4j where it answers text locally.""" ref, neo = backends found = next(r for r in ref.locate_many(_positions(ref)) if r.body is not None) - assert ref.describe([found])[0].source - assert neo.describe([found])[0].source is None + assert neo.describe([found])[0].source == ref.describe([found])[0].source != None node = ref.resolve_callable(found.callable.signature, in_class=found.type.signature) - assert neo.describe([node])[0].source.endswith(ref.describe([node])[0].source) + assert neo.describe([node])[0].source == ref.describe([node])[0].source def test_has_resolution_edges_is_true_on_a_graph_emitted_the_documented_way(backends): diff --git a/tests/analysis/java/test_java_e2e.py b/tests/analysis/java/test_java_e2e.py index 5a75958..a7048f5 100644 --- a/tests/analysis/java/test_java_e2e.py +++ b/tests/analysis/java/test_java_e2e.py @@ -94,3 +94,24 @@ def test_call_graph_nodes_are_fqn_dot_signature_strings(analysis): # J-8/#8: absolute file lines, sorted — not offsets into ``JCallable.code``, which is a # different string on each backend. assert data["calling_lines"] == sorted(data["calling_lines"]) and all(n > 0 for n in data["calling_lines"]) + + +def test_view_dispatches_reach_daytrader8s_jsps(analysis): + """codeanalyzer-java 3.3.x (python-sdk#404): at level 1 and 2 the literal tier closes 3 sites + and the table tier (3.3.1) 34 more -- every page in ``TradeConfig.webUI`` that exists on disk, + from ``TradeConfigServlet``'s two sites -- so 37 edges reach 19 of daytrader8's 23 JSPs. The + call-graph tier that binds ``TradeServletAction.requestDispatch`` runs at level 4 only, which + these two levels do not reach. Measured off the 3.3.3 jar, not off the SDK.""" + edges = analysis.get_view_dispatches() + assert len(edges) == 37 + assert {(e.via, tuple(e.prov)) for e in edges} == {("forward", ("literal",)), ("include", ("literal",)), ("include", ("table",))} + assert len({e.dst for e in edges}) == 19 + assert [d.key for d in analysis.get_view_dispatchers("PingServlet2Jsp.jsp")] == [ + "com.ibm.websphere.samples.daytrader.web.prims.PingServlet2Jsp.doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)" + ] + unresolved = analysis.get_unresolved_view_dispatches() + assert {u.reason for u in unresolved} == {"no-such-artifact", "non-literal"} + assert {u.target for u in unresolved if u.reason == "no-such-artifact"} == {"welcome.faces", "/servlet/PingServlet2IncludeRcv", "/servlet/PingServlet2ServletRcv"} + views = {p for p, a in analysis.get_artifacts().items() if "view-template" in a.roles} + assert len(views) == 38 and all(p.endswith((".jsp", ".xhtml")) for p in views) + diff --git a/tests/analysis/java/test_java_entrypoints_live.py b/tests/analysis/java/test_java_entrypoints_live.py index 07e57aa..2b7b99f 100644 --- a/tests/analysis/java/test_java_entrypoints_live.py +++ b/tests/analysis/java/test_java_entrypoints_live.py @@ -186,9 +186,9 @@ def test_method_bodies_and_call_sites_are_keyed_the_same_way(backends): ref, neo = backends keys = sorted(o.key for o in ref.get_callables_overview()) assert set(ref.get_method_bodies(keys)) == set(neo.get_method_bodies(keys)), "the two disagree about which callables have text" - # The text itself differs by backend exactly as ``get_source`` does (codeanalyzer-java#176): - # the graph's ``code`` is the whole declaration, which ends with the body block. - assert all(neo.get_method_bodies(keys)[k].endswith(ref.get_method_bodies(keys)[k]) for k in ref.get_method_bodies(keys)) + # The text is the same on both since 3.2.0: the same body block, sliced out of the same + # ``:JModule.source`` (it was the whole declaration over Neo4j -- codeanalyzer-java#176). + assert neo.get_method_bodies(keys) == ref.get_method_bodies(keys) a, b = ref.get_callsites_for(keys), neo.get_callsites_for(keys) assert set(a) == set(b) == set(keys) # Sorted, not in list order: the graph projects no **column** for a body node, so two calls on diff --git a/tests/analysis/java/test_java_neo4j_backend.py b/tests/analysis/java/test_java_neo4j_backend.py index b3f7139..e364564 100644 --- a/tests/analysis/java/test_java_neo4j_backend.py +++ b/tests/analysis/java/test_java_neo4j_backend.py @@ -40,22 +40,26 @@ **The tolerances, each with its cause** (nothing here is a tolerance because it was inconvenient; see :mod:`cldk.analysis.java.neo4j.reconstruct` for the projection's side of each): -* ``JCompilationUnit.source`` is ``""`` — a module's text is not projected at all. -* ``JCallable.code`` is the whole **declaration**, the local backend's is the **body block**: the - projection carries one line range per callable, the declaration's, and no ``body_span``. The - relation is exact and total, so it is asserted rather than skipped: - ``neo.code.endswith(ref.code)``. ``code_start_line`` therefore agrees except where the opening - brace sits below the declaration's first line. ``calling_lines`` used to shift by that same - prefix and no longer do: they are absolute file lines, which both backends can spell, so they - are asserted equal on every edge rather than tolerated. +* **Text is not a tolerance any more.** codeanalyzer-java 3.2.0 projects the whole file as + ``:JModule.source`` and a ``start_byte``/``end_byte`` pair on the nodes under it, so + ``JCompilationUnit.source`` and every ``code`` are asserted **equal**, not related: both sides are + the same slice of the same file. Before 3.2.0 ``JCallable.code`` was the whole declaration against + the local backend's body block and this suite asserted ``neo.code.endswith(ref.code)`` + (codeanalyzer-java#176); that is the divergence the 3.2.0 floor exists to have closed. + ``calling_lines`` are absolute file lines, which both backends can spell, so they are asserted + equal on every edge. +* ``JCompilationUnit.comments`` is ``[]``: comment *nodes* are still not projected, so a unit's own + comment list is empty even though the text they were cut from is now present. A type's and a + callable's javadoc rides its own property and is asserted. * Order within one source line is not recoverable: a field, a local variable and a call site carry a line but no column in the graph, so a declaration's ``field_declarations`` and ``local_variables`` are compared as multisets. Annotation order is not recoverable at all - (``J_ANNOTATED_BY`` carries only ``arguments``), so ``annotations`` is compared as a multiset. -* **Every column and every byte offset is ``-1``** on every node, not ``0``: the projection writes - ``start_line``/``end_line`` and nothing else, so a position within a line and an offset into a - ``source`` the graph does not carry are *not known*. The sentinel is asserted, not skipped, on - types, callables, fields and call sites — a ``0`` would read as column one, offset zero. + (``J_ANNOTATED_BY`` carries ``arguments`` and the application's own byte offsets, not an index), + so ``annotations`` is compared as a multiset. +* **Every column is ``-1``** on every node, not ``0``: the projection writes ``start_line``/ + ``end_line`` and byte offsets and no column anywhere, so a position *within* a line is not known. + The sentinel is asserted, not skipped, on types, callables, fields and call sites — a ``0`` would + read as column one. Byte offsets are the opposite case and are asserted equal. * ``imports`` are aggregated per import target, so a file's import order is not recoverable; the set is. * ``get_all_docstrings`` reports the javadoc of each file's *declarations* — type, callable, field, @@ -75,6 +79,8 @@ import pytest +from cldk.utils.exceptions.exceptions import CodeanalyzerExecutionException + logging.getLogger("neo4j").setLevel(logging.ERROR) NEO4J_URI = os.environ.get("CLDK_TEST_NEO4J_URI", "bolt://localhost:7687") @@ -159,7 +165,8 @@ def test_symbol_table_parity(backends): other = st_n[key] assert (other.file_path, other.package, other.content_hash) == (unit.file_path, unit.package, unit.content_hash) assert sorted(other.imports) == sorted(unit.imports), f"{key}: import set differs" - assert other.source == "" and other.comments == [] # documented: not projected + assert other.source == unit.source, f"{key}: the module text is the same file on both backends" + assert other.comments == [] # documented: comment nodes are not projected def test_application_view_parity(backends): @@ -194,7 +201,8 @@ def test_type_parity(backends): assert (o.is_entrypoint_class, o.qualified_name, o.parent_type, o.name) == (t.is_entrypoint_class, t.qualified_name, t.parent_type, t.name), name assert (o.start_line, o.end_line) == (t.start_line, t.end_line), name assert (o.start_column, o.end_column) == (-1, -1), f"{name}: a column the graph does not carry must be -1, not 0" - assert o.span.bytes == (-1, -1), f"{name}: a byte offset into a source the graph does not carry must be -1, not 0" + assert o.span.bytes == t.span.bytes, f"{name}: the byte offsets differ, so the two backends are not slicing the same text" + assert o.code == t.code, f"{name}: the declaration text differs" assert _annotations(o) == _annotations(t), name assert sorted(o.fields) == sorted(t.fields) and sorted(o.callables) == sorted(t.callables) and sorted(o.types) == sorted(t.types), name assert sorted(o.nested_type_declarations) == sorted(t.nested_type_declarations), name @@ -210,7 +218,8 @@ def test_field_parity(backends): assert [f.name for f in fr] == [f.name for f in fn], name for a, b in zip(fr, fn): assert (b.id, b.type, b.modifiers, b.initializer, b.start_line, b.end_line) == (a.id, a.type, a.modifiers, a.initializer, a.start_line, a.end_line), f"{name}.{a.name}" - assert (b.start_column, b.end_column) == (-1, -1) and b.span.bytes == (-1, -1), f"{name}.{a.name}: columns and byte offsets are not projected" + assert (b.start_column, b.end_column) == (-1, -1), f"{name}.{a.name}: columns are not projected" + assert (b.span.bytes, b.code) == (a.span.bytes, a.code), f"{name}.{a.name}: the field text differs" assert _annotations(b) == _annotations(a), f"{name}.{a.name}" assert b.variables == a.variables and b.variable_initializers == a.variable_initializers @@ -228,7 +237,8 @@ def test_callable_parity(backends): assert (o.is_implicit, o.is_entrypoint, o.is_constructor, o.is_static) == (m.is_implicit, m.is_entrypoint, m.is_constructor, m.is_static), where assert (o.start_line, o.end_line) == (m.start_line, m.end_line), where if o.span is not None: # absent on the implicit callables, on both backends - assert (o.start_column, o.end_column) == (-1, -1) and o.span.bytes == (-1, -1), f"{where}: columns and byte offsets are not projected" + assert (o.start_column, o.end_column) == (-1, -1), f"{where}: columns are not projected" + assert o.span.bytes == m.span.bytes, f"{where}: the declaration's byte offsets differ" assert o.thrown_exceptions == m.thrown_exceptions and o.cyclomatic_complexity == m.cyclomatic_complexity, where assert sorted(o.referenced_types) == sorted(m.referenced_types) and sorted(o.accessed_fields) == sorted(m.accessed_fields), where assert (o.refs is None) == (m.refs is None), where @@ -238,11 +248,10 @@ def test_callable_parity(backends): # Local variables: same multiset; within-line order is not recoverable. key = lambda v: (v.name, v.type, v.initializer, v.start_line) assert sorted(map(key, o.variable_declarations)) == sorted(map(key, m.variable_declarations)), where - # ``code``: identical without a body, otherwise the body block behind its declaration. - if m.code: - assert o.code.endswith(m.code), where - else: - assert o.code == "", where + # ``code``: the same body block, sliced out of the same ``:JModule.source``. Equality is + # what 3.2.0 buys -- ``endswith`` was the pre-3.2.0 relation (codeanalyzer-java#176). + assert o.code == m.code, where + assert o.code_start_line == m.code_start_line, where def test_parameter_parity(backends): @@ -401,6 +410,11 @@ def test_artifact_layer_parity(backends): # ``test_java_entrypoints_live.py`` states that lossiness and pins the counts. assert sorted((u.src, u.dst, tuple(u.prov)) for u in neo.get_config_uses()) == sorted((u.src, u.dst, tuple(u.prov)) for u in ref.get_config_uses()) assert {(r.callee, r.key, r.reason) for r in neo.get_unresolved_config_reads()} == {(r.callee, r.key, r.reason) for r in ref.get_unresolved_config_reads()} + # The 3.3.0 view-dispatch layer: identical resolved edges; the unresolved record is JSON-only, + # which the graph backend states by refusing rather than by an empty list. + assert [(d.src, d.dst, d.via, tuple(d.prov)) for d in neo.get_view_dispatches()] == [(d.src, d.dst, d.via, tuple(d.prov)) for d in ref.get_view_dispatches()] + with pytest.raises(CodeanalyzerExecutionException): + neo.get_unresolved_view_dispatches() # The Java wire's own artifact models carry two fields the shared Py* ones have no home for. assert sorted(neo.application.artifacts) == sorted(ref.application.artifacts) assert {p: (a.text_truncated, a.sha256) for p, a in neo.application.artifacts.items()} == {p: (a.text_truncated, a.sha256) for p, a in ref.application.artifacts.items()} diff --git a/tests/analysis/java/test_java_neo4j_multi_application_scope.py b/tests/analysis/java/test_java_neo4j_multi_application_scope.py index 1a629bb..81bc95f 100644 --- a/tests/analysis/java/test_java_neo4j_multi_application_scope.py +++ b/tests/analysis/java/test_java_neo4j_multi_application_scope.py @@ -81,21 +81,61 @@ def edge(self, src: str, rel: str, dst: str, **props: Any) -> None: _PARAMS_JSON = '[{"name":"%s","type":"java.lang.String","modifiers":[],"decorators":[],"is_variadic":false}]' +#: The two files the fixture graph projects, one ``:JModule.source`` each (codeanalyzer-java 3.2.0). +#: Every byte offset below is *derived* from these by :func:`_bytes`, and every ``start_line`` matches +#: the line the text is really on -- a fixture whose offsets were counted by hand would pin the +#: arithmetic to itself rather than to the file. +_WIDGET_SOURCE = """package shared; + +public class Widget { + private int %(tag)s_attr; + + public String render(String %(tag)s) { + int %(tag)s_var = 1; return helper(); + } + + static class Inner { + void ping() { + } + } +} +""" + +_HELPER_SOURCE = """package shared; + +class Helper { + static String help() { + return "%(tag)s help"; + } +} +""" + + +def _bytes(src: str, text: str, through: str = "") -> Tuple[int, int]: + """``(start_byte, end_byte)`` of ``text`` in ``src``, extended to the end of the first ``through`` + after it. Both files are ASCII, so a character index *is* a UTF-8 byte offset here.""" + b0 = src.index(text) + return b0, (src.index(through, b0 + len(text)) + len(through) if through else b0 + len(text)) + def _build() -> _Graph: g = _Graph() g.node("Named", ["JAnnotation"], name="Named") g.node("java.util", ["JPackage"], name="java.util") for app, tag in ((APP_A, "alpha"), (APP_B, "beta")): - app_id = g.node(f"can://{app}", ["JApplication"], name=app, schema_version="2.0.0", analyzer_name="codeanalyzer-java", analyzer_version="3.1.1") - # Both applications declare the same two repo-relative paths -- the key collision. - mod = g.node(f"can://{app}/java/{SHARED_MODULE}", ["JModule"], file_key=SHARED_MODULE, package="shared", content_hash=f"{tag}hash") + app_id = g.node(f"can://{app}", ["JApplication"], name=app, schema_version="2.0.0", analyzer_name="codeanalyzer-java", analyzer_version="3.2.0") + widget_src, helper_src = _WIDGET_SOURCE % {"tag": tag}, _HELPER_SOURCE % {"tag": tag} + # Both applications declare the same two repo-relative paths -- the key collision. The two + # ``source`` blobs are what every slice below is taken out of, so a leak reads as the other + # application's identifier inside the text, not merely as a wrong count. + mod = g.node(f"can://{app}/java/{SHARED_MODULE}", ["JModule"], file_key=SHARED_MODULE, package="shared", content_hash=f"{tag}hash", source=widget_src) g.edge(app_id, "J_HAS_MODULE", mod) g.edge(mod, "J_IMPORTS", "java.util", spellings=[f"java.util.{tag.title()}List"], is_static=None) - helper_mod = g.node(f"can://{app}/java/{OTHER_MODULE}", ["JModule"], file_key=OTHER_MODULE, package="shared", content_hash=f"{tag}helper") + helper_mod = g.node(f"can://{app}/java/{OTHER_MODULE}", ["JModule"], file_key=OTHER_MODULE, package="shared", content_hash=f"{tag}helper", source=helper_src) g.edge(app_id, "J_HAS_MODULE", helper_mod) # shared.Widget in both applications, same qualified name, different members. + cls_bytes = _bytes(widget_src, "public class Widget", "\n}") cls = g.node( f"{mod}/Widget", ["JSymbol", "JType"], @@ -106,10 +146,17 @@ def _build() -> _Graph: interfaces=["shared.Face"], docstring=f"{tag} class doc", start_line=3, - end_line=40, + end_line=14, + start_byte=cls_bytes[0], + end_byte=cls_bytes[1], ) g.edge(mod, "J_DECLARES", cls) g.edge(cls, "J_ANNOTATED_BY", "Named", arguments=[f'"{tag}"']) + # ``code`` is still projected (3.2.0 retains it) and is the whole *declaration*; nothing in + # the SDK reads it any more, and the body-block assertions below go red if anything starts. + decl_bytes = _bytes(widget_src, f"public String render(String {tag})", "\n }") + body_bytes = _bytes(widget_src, "{\n int", "\n }") + assert body_bytes[1] == decl_bytes[1], "a Java declaration's last character is its body's closing brace" method = g.node( f"{cls}/{METHOD_SIG}", ["JSymbol", "JCallable"], @@ -120,22 +167,40 @@ def _build() -> _Graph: return_type="java.lang.String", parameters_json=_PARAMS_JSON % tag, modifiers=["public"], - code=f"public String render(String {tag}) {{ return helper(); }}", + code=widget_src[decl_bytes[0] : decl_bytes[1]], docstring=f"{tag} method doc", cyclomatic_complexity=1, referenced_types=[f"shared.{tag.title()}"], accessed_fields=[f"shared.Widget.{tag}_attr"], start_line=6, end_line=8, + start_byte=decl_bytes[0], + end_byte=decl_bytes[1], + body_start_byte=body_bytes[0], ) g.edge(cls, "J_HAS_METHOD", method) ctor = g.node(f"{cls}/()", ["JSymbol", "JCallable"], name="", signature="()", kind="constructor", is_implicit=True) g.edge(cls, "J_HAS_METHOD", ctor) - field = g.node(f"{cls}#field#{tag}_attr", ["JField"], name=f"{tag}_attr", type="int", modifiers=["private"], start_line=4, end_line=4) + field_bytes = _bytes(widget_src, f"private int {tag}_attr;") + field = g.node(f"{cls}#field#{tag}_attr", ["JField"], name=f"{tag}_attr", type="int", modifiers=["private"], start_line=4, end_line=4, start_byte=field_bytes[0], end_byte=field_bytes[1]) g.edge(cls, "J_HAS_FIELD", field) - nested = g.node(f"{cls}/Inner", ["JSymbol", "JType"], name="Inner", kind="class", modifiers=["static"], start_line=20, end_line=30) + nested_bytes = _bytes(widget_src, "static class Inner {", "\n }") + nested = g.node(f"{cls}/Inner", ["JSymbol", "JType"], name="Inner", kind="class", modifiers=["static"], start_line=10, end_line=13, start_byte=nested_bytes[0], end_byte=nested_bytes[1]) g.edge(cls, "J_DECLARES", nested) - nested_m = g.node(f"{nested}/ping()", ["JSymbol", "JCallable"], name="ping", signature="ping()", kind="method", code=f"{tag} inner code", start_line=21, end_line=22) + ping_bytes = _bytes(widget_src, "void ping() {", "\n }") + nested_m = g.node( + f"{nested}/ping()", + ["JSymbol", "JCallable"], + name="ping", + signature="ping()", + kind="method", + code=widget_src[ping_bytes[0] : ping_bytes[1]], + start_line=11, + end_line=12, + start_byte=ping_bytes[0], + end_byte=ping_bytes[1], + body_start_byte=_bytes(widget_src, "{\n }")[0], + ) g.edge(nested, "J_HAS_METHOD", nested_m) local = g.node(f"{method}/$anon$0", ["JSymbol", "JType"], name="$anon$0", kind="class", start_line=7, end_line=7) g.edge(method, "J_DECLARES", local) @@ -143,14 +208,30 @@ def _build() -> _Graph: # callable, so this collides with the one above unless the callable is part of the key. ctor_local = g.node(f"{ctor}/$anon$0", ["JSymbol", "JType"], name="$anon$0", kind="class", start_line=5, end_line=5) g.edge(ctor, "J_DECLARES", ctor_local) - var = g.node(f"{method}#{tag}_var@7", ["JVariable"], name=f"{tag}_var", type="int", initializer="1", start_line=7, end_line=7) + var_bytes = _bytes(widget_src, f"int {tag}_var = 1;") + var = g.node(f"{method}#{tag}_var@7", ["JVariable"], name=f"{tag}_var", type="int", initializer="1", start_line=7, end_line=7, start_byte=var_bytes[0], end_byte=var_bytes[1]) g.edge(method, "J_DECLARES_VAR", var) # A helper the method calls, in the other module, plus one external target. - helper_cls = g.node(f"{helper_mod}/Helper", ["JSymbol", "JType"], name="Helper", kind="class", start_line=1, end_line=9) + helper_cls_bytes = _bytes(helper_src, "class Helper {", "\n}") + helper_cls = g.node(f"{helper_mod}/Helper", ["JSymbol", "JType"], name="Helper", kind="class", start_line=3, end_line=7, start_byte=helper_cls_bytes[0], end_byte=helper_cls_bytes[1]) g.edge(helper_mod, "J_DECLARES", helper_cls) - helper = g.node(f"{helper_cls}/help()", ["JSymbol", "JCallable"], name="help", signature="help()", kind="method", code=f"{tag} help", start_line=2, end_line=3) + help_bytes = _bytes(helper_src, "static String help()", "\n }") + helper = g.node( + f"{helper_cls}/help()", + ["JSymbol", "JCallable"], + name="help", + signature="help()", + kind="method", + code=helper_src[help_bytes[0] : help_bytes[1]], + start_line=4, + end_line=6, + start_byte=help_bytes[0], + end_byte=help_bytes[1], + body_start_byte=_bytes(helper_src, "{\n return")[0], + ) g.edge(helper_cls, "J_HAS_METHOD", helper) + call_bytes = _bytes(widget_src, "helper();") call = g.node( f"{method}@7:12", ["JBodyNode"], @@ -165,6 +246,8 @@ def _build() -> _Graph: argument_expr=[], start_line=7, end_line=7, + start_byte=call_bytes[0], + end_byte=call_bytes[1], ) g.edge(method, "J_HAS_BODY_NODE", call) g.edge(call, "J_RESOLVES_TO", helper) @@ -440,7 +523,7 @@ def _backend() -> JNeo4jBackend: # ===================================================================================== -# The fake graph is what a 3.1.1 graph is +# The fake graph is what a 3.2.0 graph is # ===================================================================================== def test_the_fake_graph_carries_no_module_property_and_no_v1_vocabulary(): assert GRAPH.nodes and not any("_module" in props for _, props in GRAPH.nodes.values()) @@ -497,8 +580,9 @@ def test_get_all_classes_covers_nested_and_local_types_of_this_application_only( def test_get_method_and_parameters_resolve_inside_the_application_only(): backend = _backend() method = backend.get_method(CLASS_FQN, METHOD_SIG) - assert method is not None and method.code.endswith("return helper(); }") + assert method is not None and method.code == "{\n int alpha_var = 1; return helper();\n }", "code is the body block, sliced out of :JModule.source" assert "alpha" in method.code and "beta" not in method.code + assert method.code_start_line == 6 and method.start_line == 6 assert [p.name for p in backend.get_method_parameters(CLASS_FQN, METHOD_SIG)] == ["alpha"] assert backend.get_method(CLASS_FQN, "noSuchMethod()") is None assert backend.get_all_methods_in_class(CLASS_FQN) == {METHOD_SIG: method} @@ -516,7 +600,7 @@ def test_call_graph_keys_by_fqn_and_signature_and_drops_externals(): graph = _backend().get_call_graph() assert set(graph.edges) == {(f"{CLASS_FQN}.{METHOD_SIG}", "shared.Helper.help()")} assert all("can://" not in n for n in graph.nodes) - assert graph.nodes[f"{CLASS_FQN}.{METHOD_SIG}"]["method_detail"].method.code.startswith("public String render(String alpha)") + assert "alpha_var" in graph.nodes[f"{CLASS_FQN}.{METHOD_SIG}"]["method_detail"].method.code, "the call-graph node's text came from application B" edge = graph.edges[f"{CLASS_FQN}.{METHOD_SIG}", "shared.Helper.help()"] assert edge["type"] == "CALL_DEP" and edge["weight"] == 1 @@ -565,9 +649,10 @@ def test_the_addressing_surface_answers_from_this_application_only(): assert node.ref.startswith(f"can://{APP_A}/") assert "alpha" in backend.get_source(node.callable) assert backend.resolve_value("alpha", within="Widget.render").ref == f"{node.ref}@formal_in:0" - # The graph carries no text below callable granularity: the position is found, its source is - # ``None`` -- never application B's, and never the enclosing declaration standing in for it. - assert backend.describe([found])[0].source is None + # Text reaches below callable granularity since 3.2.0: the body node carries its own offsets, so + # its source is its own slice -- never application B's, and never the enclosing declaration + # standing in for it. A body node the projection places nowhere still describes as ``None``. + assert backend.describe([found])[0].source == "helper();" def test_the_task_three_surface_answers_from_this_application_only(): @@ -583,7 +668,7 @@ def test_the_task_three_surface_answers_from_this_application_only(): "shared.Widget.Inner.ping()", "shared.Helper.help()", }, "the projection is the addressing domain of *this* application" - assert backend.get_method_bodies(list(keys))[f"{CLASS_FQN}.{METHOD_SIG}"].endswith("return helper(); }") + assert backend.get_method_bodies(list(keys))[f"{CLASS_FQN}.{METHOD_SIG}"].endswith("return helper();\n }") assert "beta" not in "".join(backend.get_method_bodies(list(keys)).values()) assert [s.method_name for s in backend.get_callsites_for([f"{CLASS_FQN}.{METHOD_SIG}"])[f"{CLASS_FQN}.{METHOD_SIG}"]] == ["help"] assert [o.key for o in backend.get_decorated_callables(["Named"])] == [], "the annotation is on the type, not the callable" diff --git a/tests/analysis/java/test_java_neo4j_scale.py b/tests/analysis/java/test_java_neo4j_scale.py index b5ec99a..6c48e32 100644 --- a/tests/analysis/java/test_java_neo4j_scale.py +++ b/tests/analysis/java/test_java_neo4j_scale.py @@ -135,10 +135,12 @@ def test_get_test_methods_answers_off_the_graph(backend): """The accessor daytrader8 cannot exercise at all: it ships zero ``@Test`` methods, so ``{}`` there is correct whatever the implementation does. ThingsBoard carries thousands. - The 1.x implementation re-parsed each ``JCompilationUnit.source`` with Tree-sitter, and this - projection carries no module source (``source=""`` on every unit), so it returned ``{}`` here — - an empty reading as "this application has no tests" on an application with 3,354 annotated - callables. The annotations are in the graph on ``J_ANNOTATED_BY``, which is what is read now. + The 1.x implementation re-parsed each ``JCompilationUnit.source`` with Tree-sitter, which + returned ``{}`` on any projection that carried no module source — an empty reading as "this + application has no tests" on an application with 3,354 annotated callables. The annotations are + in the graph on ``J_ANNOTATED_BY``, which is what is read now. Since codeanalyzer-java 3.2.0 the + projection does carry ``:JModule.source``, but that is text for slicing, not a parse target: this + accessor still reads the edge, so it cannot regress to re-parsing a file that may be absent. """ from cldk.analysis.java.java_analysis import _TEST_ANNOTATIONS diff --git a/tests/analysis/java/test_java_public_surface.py b/tests/analysis/java/test_java_public_surface.py index 6bfaef2..ec80182 100644 --- a/tests/analysis/java/test_java_public_surface.py +++ b/tests/analysis/java/test_java_public_surface.py @@ -105,6 +105,9 @@ "get_config_uses": "(self, key: 'str | None' = None) -> 'List[PyConfigUseEdge]'", "get_unresolved_config_reads": "(self) -> 'List[PyConfigRead]'", "get_config_readers": "(self, key: 'str') -> 'List[JCallableOverview]'", + "get_view_dispatches": "(self, view: 'str | None' = None) -> 'List[JViewDispatch]'", + "get_unresolved_view_dispatches": "(self) -> 'List[JViewDispatchUnresolved]'", + "get_view_dispatchers": "(self, path: 'str') -> 'List[JCallableOverview]'", "get_interfaces": "(self) -> 'Dict[str, JType]'", "get_enums": "(self) -> 'Dict[str, JType]'", "get_enum_members": "(self, qualified_enum_name: 'str') -> 'List[JEnumConstant]'", diff --git a/tests/analysis/java/test_java_schema_probe.py b/tests/analysis/java/test_java_schema_probe.py index 7a86d27..2753cd1 100644 --- a/tests/analysis/java/test_java_schema_probe.py +++ b/tests/analysis/java/test_java_schema_probe.py @@ -83,20 +83,23 @@ def test_probe_refuses_a_python_graph_naming_the_missing_java_types(fake_driver) assert "PY_CALLS" in str(e.value) -@pytest.mark.parametrize("raw", ["3.0.0", "3.0.1", "3.0.2", "3.0.3", "3.1.0"]) +@pytest.mark.parametrize("raw", ["3.0.0", "3.0.1", "3.0.2", "3.0.3", "3.1.0", "3.1.1", "3.1.2"]) def test_probe_refuses_a_graph_below_the_analyzer_floor(fake_driver, raw): - """Every generation below 3.1.1 is refused, naming the version found and the floor. + """Every generation below 3.2.0 is refused, naming the version found and the floor. - Two of these are the ones that matter, and both declare every relationship type the fingerprint + Three of these are the ones that matter, and all declare every relationship type the fingerprint asks for, so the fingerprint passes and the version stamp is the only signal: * ``3.0.0`` -- the vocabulary is there but it stamped contract 2.2.0 with a different body-node - id grammar (J-9, the reason 3.0.1 was the floor). - * ``3.1.0`` -- **the release immediately below the floor**, and the one the floor exists for. - Its ids are ``can://java//…``: the application prefix every statement here scopes on - matches none of them, so it attaches cleanly and answers everything with zero rows.""" + id grammar (J-9, the reason 3.0.1 was the first floor). + * ``3.1.0`` -- ids are ``can://java//…``, so the application prefix every statement here + scopes on matches none of them: it would attach cleanly and answer everything with zero rows. + That is what the 3.1.1 floor existed for. + * ``3.1.2`` -- **the release immediately below the floor**, and the one this floor exists for. It + projects text as ``:JCallable.code`` and no byte offsets at all, so every other node's ``code`` + would rebuild as ``""`` -- served, silently, as though the file held nothing.""" fake_driver.analyzer_version = raw - with pytest.raises(GraphSchemaMismatch, match=rf"{raw}.*3\.1\.1 or newer"): + with pytest.raises(GraphSchemaMismatch, match=rf"{raw}.*3\.2\.0 or newer"): JNeo4jBackend._from_driver(fake_driver, application_name="daytrader8") @@ -114,15 +117,15 @@ def test_probe_refuses_when_the_version_cannot_be_read(fake_driver, raw, found): because serving it would be the silent-empty defect with no signal -- and the message says which of the three it found.""" fake_driver.analyzer_version = raw - with pytest.raises(GraphSchemaMismatch, match="3.1.1 or newer") as e: + with pytest.raises(GraphSchemaMismatch, match="3.2.0 or newer") as e: JNeo4jBackend._from_driver(fake_driver, application_name="daytrader9") assert found in str(e.value) -@pytest.mark.parametrize("raw", ["3.1.1", "3.1.2", "3.2.0", "4.0.0"]) +@pytest.mark.parametrize("raw", ["3.2.0", "3.2.1", "3.3.0", "4.0.0"]) def test_probe_serves_every_generation_from_the_floor_up_silently(fake_driver, caplog, raw): - """The other direction of the floor: 3.1.1 -- the release that put the application outermost -- - is served, and so is anything above it.""" + """The other direction of the floor: 3.2.0 -- the release whose projection carries the canonical + text model -- is served, and so is anything above it.""" fake_driver.analyzer_version = raw with caplog.at_level(logging.INFO, logger="cldk.analysis.java.neo4j.neo4j_backend"): backend = JNeo4jBackend._from_driver(fake_driver, application_name="daytrader8") diff --git a/tests/analysis/java/test_java_v1_accessors_live.py b/tests/analysis/java/test_java_v1_accessors_live.py index edf8dca..ec89d1f 100644 --- a/tests/analysis/java/test_java_v1_accessors_live.py +++ b/tests/analysis/java/test_java_v1_accessors_live.py @@ -159,14 +159,18 @@ def test_the_import_set_is_smaller_than_the_per_file_declarations(backends): # ---- get_variables ---------------------------------------------------------------------------- def test_the_local_variables_agree_name_type_and_line(backends): - """``J_DECLARES_VAR`` carries a **line-only** span, so the columns and byte offsets are - placeholders over the graph exactly as they are everywhere else on this surface; everything - that is a fact about the variable agrees.""" + """``:JVariable`` carries no column, so those stay placeholders over the graph exactly as they + are everywhere else on this surface; its **byte offsets** are real since codeanalyzer-java 3.2.0 + (863 of daytrader8's 863 locals carry them) and are asserted equal. ``JLocalVariable.code`` + raises on **both** backends and is not asserted: ``_thread_type`` threads a type's fields, + callables and body nodes into the compilation unit and not a callable's locals, so neither side + has a unit to slice -- the same answer from the same model, not a projection gap.""" ref, neo = backends local, graph = ref.get_variables(), neo.get_variables() assert set(local) == set(graph) and len(local) == DT_CALLABLES for key, declared in local.items(): assert [(v.name, v.type, v.start_line, v.initializer) for v in declared] == [(v.name, v.type, v.start_line, v.initializer) for v in graph[key]], key + assert [v.span.bytes for v in declared] == [v.span.bytes for v in graph[key]], f"{key}: the two backends place the same local at different bytes" assert sum(1 for v in local.values() if v) == DT_DECLARING_LOCALS assert sum(len(v) for v in local.values()) == DT_LOCALS @@ -255,8 +259,9 @@ def test_the_call_targets_agree(backends): # ---- get_calling_lines -------------------------------------------------------------------------- def test_the_calling_lines_agree_and_are_absolute_file_lines(backends): """Leg 3a made these agree rather than shift by a declaration prefix; this is the assertion - that keeps them agreeing over a real projection, where ``code`` and ``code_start_line`` really - do differ between the two backends.""" + that keeps them agreeing over a real projection. It was written when ``code`` and + ``code_start_line`` still differed between the two backends, which is what made the shift + possible; 3.2.0 makes both equal, and these lines are absolute file lines either way.""" ref, neo = backends lines = ref.get_calling_lines("getStatement") assert lines == neo.get_calling_lines("getStatement") diff --git a/tests/analysis/java/test_java_view_dispatches.py b/tests/analysis/java/test_java_view_dispatches.py new file mode 100644 index 0000000..43e80b5 --- /dev/null +++ b/tests/analysis/java/test_java_view_dispatches.py @@ -0,0 +1,167 @@ +################################################################################ +# Copyright IBM Corporation 2026 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ +"""The view-dispatch layer (codeanalyzer-java 3.3.0, python-sdk#404) on **both** backends, offline. + +The committed fixtures are 3.1.0 payloads and carry no ``view_dispatches``, so the layer is exercised +over **a1 with the layer injected**: three resolved edges and one unresolved record shaped exactly +as codeanalyzer-java 3.3.3 writes them on daytrader8 (``PingServlet2Jsp.doGet`` forwards to +``PingServlet2Jsp.jsp``; ``PingJDBCRead2JSP.doGet`` includes ``quoteDataPrimitive.jsp``; a forward to +``/servlet/PingServlet2ServletRcv`` is a URL, not a file), re-addressed onto the fixture's own +callable and artifact ids. The second include comes from ``PingServlet2Session2Entity2JSP.doGet``, +the fixture's other ``include`` site — a1 is a 3.1.0 run over 138 units and has no +``PingJDBCWrite2JSP``. The a1 payload as committed is the +*refusal* case: an analysis that predates the pass must not answer ``[]``. +""" +import json +from typing import Dict + +import pytest + +from cldk.analysis.java.backend import JavaAnalysisBackend +from cldk.analysis.java.codeanalyzer.codeanalyzer import JCodeanalyzer +from cldk.analysis.java.neo4j import JNeo4jBackend +from cldk.models.java.models import JViewDispatch, JViewDispatchUnresolved +from cldk.models.java.projections import JCallableOverview +from cldk.utils.exceptions.exceptions import CodeanalyzerExecutionException + +from .test_java_addressing import _graph, _local + +DO_GET = "doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)" + + +def _site(app: dict, unit: str, type_name: str, method_name: str) -> str: + """The ordinal id of the first ``call`` body node invoking ``method_name`` in ``doGet``. The + unit is found by basename: the two include sites live in different ``web/prims`` packages.""" + path = next(k for k in app["symbol_table"] if k.endswith(f"/{unit}.java")) + callable_ = app["symbol_table"][path]["types"][type_name]["callables"][DO_GET] + for local_id, node in callable_["body"].items(): + if node.get("method_name") == method_name: + return f"{callable_['id']}@{local_id}" + raise AssertionError(f"no {method_name} call in {type_name}.doGet") + + +def _with_layer(payload: str) -> str: + doc = json.loads(payload) + app = doc["application"] + doc["analyzer"]["version"] = "3.3.3" + art = {p: a["id"] for p, a in app["artifacts"].items()} + app["view_dispatches"] = sorted( + [ + {"src": _site(app, "PingServlet2Jsp", "PingServlet2Jsp", "forward"), "dst": art["src/main/webapp/PingServlet2Jsp.jsp"], "via": "forward", "prov": ["literal"]}, + {"src": _site(app, "PingJDBCRead2JSP", "PingJDBCRead2JSP", "include"), "dst": art["src/main/webapp/quoteDataPrimitive.jsp"], "via": "include", "prov": ["literal"]}, + {"src": _site(app, "PingServlet2Session2Entity2JSP", "PingServlet2Session2Entity2JSP", "include"), "dst": art["src/main/webapp/quoteDataPrimitive.jsp"], "via": "include", "prov": ["literal"]}, + ], + key=lambda d: (d["src"], d["dst"]), + ) + app["view_dispatches_unresolved"] = [ + { + "site": _site(app, "PingServlet2Servlet", "PingServlet2Servlet", "forward"), + "callee": "can://java/daytrader8/@external/javax.servlet.RequestDispatcher/forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)", + "target": "/servlet/PingServlet2ServletRcv", + "via": "forward", + "reason": "no-such-artifact", + "prov": ["literal"], + } + ] + return json.dumps(doc) + + +def _seed(kind: str, payload: str) -> JavaAnalysisBackend: + backend = (_local if kind == "local" else _graph)(payload) + if kind == "graph": + backend._analyzer_version = (3, 3, 3) + return backend + + +@pytest.fixture(scope="module", params=["local", "graph"]) +def both(request, analysis_json): + return _seed(request.param, _with_layer(analysis_json)) + + +@pytest.fixture(scope="module", params=["local", "graph"]) +def both_before(request, analysis_json): + """a1 as committed: codeanalyzer-java 3.1.0, no view-dispatch pass.""" + backend = (_local if request.param == "local" else _graph)(analysis_json) + if request.param == "graph": + backend._analyzer_version = (3, 1, 0) + return backend + + +def test_get_view_dispatches_carries_the_edges_and_their_mechanism(both): + edges = both.get_view_dispatches() + assert len(edges) == 3 and all(isinstance(e, JViewDispatch) for e in edges) + assert [(e.via, tuple(e.prov)) for e in edges] == [("include", ("literal",)), ("include", ("literal",)), ("forward", ("literal",))] or sorted((e.via, tuple(e.prov)) for e in edges) == [("forward", ("literal",)), ("include", ("literal",)), ("include", ("literal",))] + assert all(e.src.startswith(e.src.rpartition("@")[0] + "@") for e in edges), "src is a body-node id" + assert {e.dst.rsplit("/", 1)[1] for e in edges} == {"PingServlet2Jsp.jsp", "quoteDataPrimitive.jsp"} + assert [(e.src, e.dst) for e in edges] == sorted((e.src, e.dst) for e in edges), "sorted by (src, dst)" + + +def test_get_view_dispatches_filters_by_the_views_path_suffix(both): + two = both.get_view_dispatches("quoteDataPrimitive.jsp") + assert len(two) == 2 and all(e.dst.endswith("/quoteDataPrimitive.jsp") for e in two) + assert len(both.get_view_dispatches("src/main/webapp/quoteDataPrimitive.jsp")) == 2, "a longer suffix still matches" + assert both.get_view_dispatches("DataPrimitive.jsp") == [], "segment-aligned, never a substring" + assert both.get_view_dispatches("no/such.jsp") == [] + + +def test_get_view_dispatchers_resolves_the_sites_to_their_callables(both): + dispatchers = both.get_view_dispatchers("quoteDataPrimitive.jsp") + assert all(isinstance(d, JCallableOverview) for d in dispatchers) + assert sorted(d.key for d in dispatchers) == [ + f"com.ibm.websphere.samples.daytrader.web.prims.PingJDBCRead2JSP.{DO_GET}", + f"com.ibm.websphere.samples.daytrader.web.prims.ejb3.PingServlet2Session2Entity2JSP.{DO_GET}", + ] + assert [d.key for d in both.get_view_dispatchers("PingServlet2Jsp.jsp")] == [f"com.ibm.websphere.samples.daytrader.web.prims.PingServlet2Jsp.{DO_GET}"] + assert both.get_view_dispatchers("no/such.jsp") == [] + + +def test_get_unresolved_view_dispatches_keeps_the_url_visible_on_the_local_backend(both): + if isinstance(both, JNeo4jBackend): + # JSON-only: the projection has no node for a target that resolved to nothing, so the + # graph backend refuses rather than answering the ambiguous empty. + with pytest.raises(CodeanalyzerExecutionException, match="analysis.json"): + both.get_unresolved_view_dispatches() + return + unresolved = both.get_unresolved_view_dispatches() + assert len(unresolved) == 1 and isinstance(unresolved[0], JViewDispatchUnresolved) + u = unresolved[0] + assert (u.via, u.reason, u.target, u.prov) == ("forward", "no-such-artifact", "/servlet/PingServlet2ServletRcv", ["literal"]) + assert u.site.startswith(u.site.rpartition("@")[0] + "@") + + +def test_a_payload_without_the_pass_refuses_rather_than_answering_empty(both_before): + for call in (both_before.get_view_dispatches, both_before.get_unresolved_view_dispatches, lambda: both_before.get_view_dispatchers("x.jsp")): + with pytest.raises(CodeanalyzerExecutionException, match="3.3.0"): + call() + + +def test_a_newer_payload_with_no_dispatches_answers_empty(analysis_json): + doc = json.loads(analysis_json) + doc["analyzer"]["version"] = "3.3.3" + local = _local(json.dumps(doc)) + assert local.get_view_dispatches() == [] and local.get_unresolved_view_dispatches() == [] + assert local.get_view_dispatchers("x.jsp") == [] + + +def test_the_layer_is_answered_once_for_both_backends(): + """One implementation on the contract for the two edge accessors; the graph backend overrides + only the unresolved one, to refuse what the projection does not carry.""" + for name in ("get_view_dispatches", "get_view_dispatchers"): + shared = getattr(JavaAnalysisBackend, name) + for backend in (JCodeanalyzer, JNeo4jBackend): + assert getattr(backend, name) is shared, f"{backend.__name__} overrides {name}" + assert JCodeanalyzer.get_unresolved_view_dispatches is JavaAnalysisBackend.get_unresolved_view_dispatches + assert JNeo4jBackend.get_unresolved_view_dispatches is not JavaAnalysisBackend.get_unresolved_view_dispatches diff --git a/tests/resources/typescript/analysis_json/v2/README.md b/tests/resources/typescript/analysis_json/v2/README.md index f647e79..26ea20c 100644 --- a/tests/resources/typescript/analysis_json/v2/README.md +++ b/tests/resources/typescript/analysis_json/v2/README.md @@ -1,4 +1,4 @@ -Generated from `tests/resources/typescript/application` by the released **codeanalyzer-typescript 1.5.3** wheel: +Generated from `tests/resources/typescript/application` by the released **codeanalyzer-typescript 1.6.0** wheel: cants -i tests/resources/typescript/application --app-name slim -a <1|2|3|4> -o a --cache-dir -j 1 --no-build @@ -38,3 +38,12 @@ Why it mattered: the schemas had declared the property since the L4 layer landed wrote nothing, so a consumer predicate on `var` was `null` on every edge crossing a call boundary. Under Cypher's three-valued logic an `all()` over that `null` excludes the whole path, so an interprocedural flow read as a proved absence of flow -- indistinguishable from a real negative. + +What 1.6.0 changed against the 1.5.3 generation these files held before: **nothing in this output**. +All four levels are byte-identical apart from the `analyzer.version` stamp, checked by parsing both +generations and comparing them with that one field masked. 1.6.0 is a Neo4j-projection release +(codeanalyzer-typescript#204): `:TSModule` gains `source`, the shared `SPAN` gains `start_column` / +`end_column` / `start_byte` / `end_byte` across ten labels, and `:TSAnonymousCallable` stops writing +a half-span by hand. `analysis.json` already carried every one of those facts, which is why the +regeneration moves only the stamp — and why the pin bump is not a read-path change. `:TSCallable.code` +is kept upstream on purpose: this SDK's Neo4j reconstruction reads it. diff --git a/tests/resources/typescript/analysis_json/v2/a1/analysis.json b/tests/resources/typescript/analysis_json/v2/a1/analysis.json index 6079cc1..da16a35 100644 --- a/tests/resources/typescript/analysis_json/v2/a1/analysis.json +++ b/tests/resources/typescript/analysis_json/v2/a1/analysis.json @@ -1 +1 @@ -{"schema_version":"2.0.0","language":"typescript","max_level":1,"analyzer":{"name":"codeanalyzer-typescript","version":"1.5.3"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":null,"method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":null,"method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":null,"method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"}},"entrypoints":[],"is_entrypoint":false},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":null,"method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":null,"method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":null,"method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":null,"method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":null,"method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":null,"method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":null,"method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":null,"method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":null,"method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":null,"method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":null,"method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":null,"method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":null,"method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":null,"method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":null,"method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":null,"method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":null,"method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":null,"method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"}},"entrypoints":[],"is_entrypoint":false},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":null,"method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":null,"method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":null,"method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"}},"entrypoints":[],"is_entrypoint":false},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":null,"method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":null,"method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"}},"entrypoints":[],"is_entrypoint":false},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":null,"method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":null,"method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":null,"method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":null,"method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"}},"entrypoints":[],"is_entrypoint":false},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":null,"method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":null,"method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"}},"entrypoints":[],"is_entrypoint":false},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":null,"method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":null,"method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":null,"method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"}},"entrypoints":[],"is_entrypoint":false},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":null,"method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":null,"method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":null,"method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":null,"method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":null,"method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]}}} \ No newline at end of file +{"schema_version":"2.0.0","language":"typescript","max_level":1,"analyzer":{"name":"codeanalyzer-typescript","version":"1.6.0"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":null,"method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":null,"method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":null,"method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"}},"entrypoints":[],"is_entrypoint":false},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":null,"method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":null,"method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":null,"method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":null,"method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":null,"method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":null,"method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":null,"method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":null,"method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":null,"method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":null,"method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":null,"method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":null,"method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":null,"method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":null,"method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":null,"method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":null,"method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":null,"method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":null,"method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"}},"entrypoints":[],"is_entrypoint":false},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":null,"method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":null,"method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":null,"method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"}},"entrypoints":[],"is_entrypoint":false},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":null,"method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":null,"method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"}},"entrypoints":[],"is_entrypoint":false},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":null,"method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":null,"method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":null,"method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":null,"method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"}},"entrypoints":[],"is_entrypoint":false},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":null,"method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":null,"method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"}},"entrypoints":[],"is_entrypoint":false},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":null,"method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":null,"method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":null,"method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"}},"entrypoints":[],"is_entrypoint":false},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":null,"method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":null,"method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":null,"method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":null,"method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":null,"method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]}}} \ No newline at end of file diff --git a/tests/resources/typescript/analysis_json/v2/a2/analysis.json b/tests/resources/typescript/analysis_json/v2/a2/analysis.json index 5d18a67..2c25b68 100644 --- a/tests/resources/typescript/analysis_json/v2/a2/analysis.json +++ b/tests/resources/typescript/analysis_json/v2/a2/analysis.json @@ -1 +1 @@ -{"schema_version":"2.0.0","language":"typescript","max_level":2,"analyzer":{"name":"codeanalyzer-typescript","version":"1.5.3"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"}},"entrypoints":[],"is_entrypoint":false},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"}},"entrypoints":[],"is_entrypoint":false},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"}},"entrypoints":[],"is_entrypoint":false},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"}},"entrypoints":[],"is_entrypoint":false},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"}},"entrypoints":[],"is_entrypoint":false},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"}},"entrypoints":[],"is_entrypoint":false},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"}},"entrypoints":[],"is_entrypoint":false},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file +{"schema_version":"2.0.0","language":"typescript","max_level":2,"analyzer":{"name":"codeanalyzer-typescript","version":"1.6.0"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"}},"entrypoints":[],"is_entrypoint":false},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"}},"entrypoints":[],"is_entrypoint":false},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"}},"entrypoints":[],"is_entrypoint":false},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"}},"entrypoints":[],"is_entrypoint":false},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"}},"entrypoints":[],"is_entrypoint":false},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"}},"entrypoints":[],"is_entrypoint":false},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"}},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"}},"entrypoints":[],"is_entrypoint":false},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"}},"entrypoints":[],"is_entrypoint":false}},"entrypoints":[],"is_entrypoint":false}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file diff --git a/tests/resources/typescript/analysis_json/v2/a3/analysis.json b/tests/resources/typescript/analysis_json/v2/a3/analysis.json index 9de34c7..559dcce 100644 --- a/tests/resources/typescript/analysis_json/v2/a3/analysis.json +++ b/tests/resources/typescript/analysis_json/v2/a3/analysis.json @@ -1 +1 @@ -{"schema_version":"2.0.0","language":"typescript","max_level":3,"k_limit":3,"analyzer":{"name":"codeanalyzer-typescript","version":"1.5.3"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"},"@entry":{"kind":"entry","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@entry"},"20:5":{"kind":"statement","span":{"start":[20,5],"end":[20,42],"bytes":[550,587]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5"},"21:5":{"kind":"statement","span":{"start":[21,5],"end":[21,28],"bytes":[592,615]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5"},"@exit":{"kind":"exit","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"20:5","kind":"fallthrough"},{"src":"20:5","dst":"@exit","kind":"exception"},{"src":"20:5","dst":"21:5","kind":"fallthrough"},{"src":"21:5","dst":"@exit","kind":"exception"},{"src":"21:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"20:5"},{"src":"20:5","dst":"21:5"}],"ddg":[{"src":"@entry","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"this.service.create","prov":["reaching-defs"]},{"src":"20:5","dst":"21:5","var":"user.describe","prov":["reaching-defs"]}]},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,39],"bytes":[658,692]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"this.service.describeAll","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[200,223]},"id":"can://slim/typescript/src/controllers.ts/Controller@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@entry"},"5:16":{"kind":"statement","span":{"start":[5,16],"end":[5,25],"bytes":[213,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@5:16"},"@exit":{"kind":"exit","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:16","kind":"fallthrough"},{"src":"5:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[]},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@entry"},"8:3":{"kind":"statement","span":{"start":[8,3],"end":[8,26],"bytes":[274,297]},"id":"can://slim/typescript/src/controllers.ts/Get@8:3"},"@exit":{"kind":"exit","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@entry"},"8:16":{"kind":"statement","span":{"start":[8,16],"end":[8,25],"bytes":[287,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@8:16"},"@exit":{"kind":"exit","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:16","kind":"fallthrough"},{"src":"8:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:3"}],"ddg":[]},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@entry"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,26],"bytes":[353,376]},"id":"can://slim/typescript/src/controllers.ts/Param@11:3"},"@exit":{"kind":"exit","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@entry"},"11:16":{"kind":"statement","span":{"start":[11,16],"end":[11,25],"bytes":[366,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@11:16"},"@exit":{"kind":"exit","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:16","kind":"fallthrough"},{"src":"11:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:3"}],"ddg":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"},"@entry":{"kind":"entry","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@entry"},"7:3":{"kind":"statement","span":{"start":[7,3],"end":[7,40],"bytes":[217,254]},"id":"can://slim/typescript/src/index.ts/main@7:3"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,50],"bytes":[320,367]},"id":"can://slim/typescript/src/index.ts/main@11:3"},"19:3":{"kind":"statement","span":{"start":[19,3],"end":[19,52],"bytes":[579,628]},"id":"can://slim/typescript/src/index.ts/main@19:3"},"20:3":{"kind":"statement","span":{"start":[20,3],"end":[20,44],"bytes":[631,672]},"id":"can://slim/typescript/src/index.ts/main@20:3"},"@exit":{"kind":"exit","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"7:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"exception"},{"src":"11:3","dst":"12:3","kind":"fallthrough"},{"src":"12:3","dst":"@exit","kind":"exception"},{"src":"12:3","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"16:3","kind":"fallthrough"},{"src":"16:3","dst":"@exit","kind":"exception"},{"src":"16:3","dst":"17:3","kind":"fallthrough"},{"src":"17:3","dst":"@exit","kind":"exception"},{"src":"17:3","dst":"19:3","kind":"fallthrough"},{"src":"19:3","dst":"@exit","kind":"exception"},{"src":"19:3","dst":"20:3","kind":"fallthrough"},{"src":"20:3","dst":"@exit","kind":"exception"},{"src":"20:3","dst":"21:3","kind":"fallthrough"},{"src":"21:3","dst":"@exit","kind":"exception"},{"src":"21:3","dst":"22:3","kind":"fallthrough"},{"src":"22:3","dst":"@exit","kind":"exception"},{"src":"22:3","dst":"@exit","kind":"fallthrough"},{"src":"7:3","dst":"@exit","kind":"exception"},{"src":"7:3","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"exception"},{"src":"8:3","dst":"9:3","kind":"fallthrough"},{"src":"9:3","dst":"@exit","kind":"exception"},{"src":"9:3","dst":"11:3","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"7:3"},{"src":"11:3","dst":"12:3"},{"src":"12:3","dst":"13:3"},{"src":"13:3","dst":"16:3"},{"src":"16:3","dst":"17:3"},{"src":"17:3","dst":"19:3"},{"src":"19:3","dst":"20:3"},{"src":"20:3","dst":"21:3"},{"src":"21:3","dst":"22:3"},{"src":"7:3","dst":"8:3"},{"src":"8:3","dst":"9:3"},{"src":"9:3","dst":"11:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"8:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"9:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"11:3","dst":"12:3","var":"controller.list","prov":["reaching-defs"]},{"src":"11:3","dst":"13:3","var":"controller.show","prov":["reaching-defs"]},{"src":"19:3","dst":"22:3","var":"slug","prov":["reaching-defs"]},{"src":"20:3","dst":"21:3","var":"builder.add","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"8:3","var":"service.create","prov":["reaching-defs"]},{"src":"7:3","dst":"9:3","var":"service.createGuest","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@entry"},"49:5":{"kind":"statement","span":{"start":[49,5],"end":[49,42],"bytes":[872,909]},"id":"can://slim/typescript/src/models.ts/User/describe@49:5"},"@exit":{"kind":"exit","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"49:5","kind":"fallthrough"},{"src":"49:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"49:5"}],"ddg":[{"src":"@entry","dst":"49:5","var":"this.name","prov":["reaching-defs"]},{"src":"@entry","dst":"49:5","var":"this.role","prov":["reaching-defs"]}]},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@entry"},"53:5":{"kind":"statement","span":{"start":[53,5],"end":[53,26],"bytes":[960,981]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@53:5"},"54:5":{"kind":"statement","span":{"start":[54,5],"end":[54,28],"bytes":[986,1009]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@54:5"},"@exit":{"kind":"exit","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"53:5","kind":"fallthrough"},{"src":"53:5","dst":"54:5","kind":"fallthrough"},{"src":"54:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"53:5"},{"src":"@entry","dst":"54:5"}],"ddg":[{"src":"@entry","dst":"53:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"@entry","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"53:5","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"},"@entry":{"kind":"entry","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,22],"bytes":[753,770]},"id":"can://slim/typescript/src/models.ts/User/constructor@41:5"},"@exit":{"kind":"exit","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"40:5","kind":"fallthrough"},{"src":"40:5","dst":"@exit","kind":"exception"},{"src":"40:5","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"@exit","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"40:5"},{"src":"40:5","dst":"41:5"}],"ddg":[{"src":"@entry","dst":"40:5","var":"id","prov":["reaching-defs"]}]},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@entry"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,37],"bytes":[807,839]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@45:5"},"@exit":{"kind":"exit","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"45:5","kind":"fallthrough"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"45:5"}],"ddg":[{"src":"@entry","dst":"45:5","var":"this.role","prov":["reaching-defs"]}]}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@entry"},"62:5":{"kind":"statement","span":{"start":[62,5],"end":[62,33],"bytes":[1202,1230]},"id":"can://slim/typescript/src/models.ts/Robot/describe@62:5"},"@exit":{"kind":"exit","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"62:5","kind":"fallthrough"},{"src":"62:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"62:5"}],"ddg":[{"src":"@entry","dst":"62:5","var":"this.name","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@entry"},"25:5":{"kind":"statement","span":{"start":[25,5],"end":[25,57],"bytes":[733,785]},"id":"can://slim/typescript/src/services.ts/UserService/create@25:5"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,43],"bytes":[790,828]},"id":"can://slim/typescript/src/services.ts/UserService/create@26:5"},"28:5":{"kind":"statement","span":{"start":[28,5],"end":[28,17],"bytes":[860,872]},"id":"can://slim/typescript/src/services.ts/UserService/create@28:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:5","kind":"fallthrough"},{"src":"25:5","dst":"@exit","kind":"exception"},{"src":"25:5","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"27:5","kind":"fallthrough"},{"src":"27:5","dst":"@exit","kind":"exception"},{"src":"27:5","dst":"28:5","kind":"fallthrough"},{"src":"28:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:5"},{"src":"25:5","dst":"26:5"},{"src":"26:5","dst":"27:5"},{"src":"27:5","dst":"28:5"}],"ddg":[{"src":"@entry","dst":"25:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@entry","dst":"27:5","var":"this.users.push","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5","var":"id","prov":["reaching-defs"]},{"src":"26:5","dst":"27:5","var":"user","prov":["reaching-defs"]},{"src":"26:5","dst":"28:5","var":"user","prov":["reaching-defs"]}]},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"},"@entry":{"kind":"entry","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@entry"},"32:5":{"kind":"statement","span":{"start":[32,5],"end":[32,51],"bytes":[906,952]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5"},"33:5":{"kind":"statement","span":{"start":[33,5],"end":[33,42],"bytes":[957,994]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5"},"@exit":{"kind":"exit","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"32:5","kind":"fallthrough"},{"src":"32:5","dst":"@exit","kind":"exception"},{"src":"32:5","dst":"33:5","kind":"fallthrough"},{"src":"33:5","dst":"@exit","kind":"exception"},{"src":"33:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"32:5"},{"src":"32:5","dst":"33:5"}],"ddg":[{"src":"@entry","dst":"32:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"this.create","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5","var":"name","prov":["reaching-defs"]}]},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"},"@entry":{"kind":"entry","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@entry"},"37:5":{"kind":"statement","span":{"start":[37,5],"end":[37,48],"bytes":[1032,1075]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5"},"@exit":{"kind":"exit","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@exit"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"},"@entry":{"kind":"entry","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@entry"},"@exit":{"kind":"exit","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:34","kind":"fallthrough"},{"src":"37:34","dst":"@exit","kind":"exception"},{"src":"37:34","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:34"}],"ddg":[{"src":"@entry","dst":"37:34","var":"u.describe","prov":["reaching-defs"]}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:5","kind":"fallthrough"},{"src":"37:5","dst":"@exit","kind":"exception"},{"src":"37:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:5"}],"ddg":[{"src":"@entry","dst":"37:5","var":"this.users.map","prov":["reaching-defs"]}]},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"},"@entry":{"kind":"entry","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,19],"bytes":[1123,1137]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@41:5"},"42:5":{"kind":"statement","span":{"start":[42,5],"end":[44,6],"bytes":[1142,1215]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@42:5"},"43:7":{"kind":"statement","span":{"start":[43,7],"end":[43,38],"bytes":[1178,1209]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,18],"bytes":[1220,1233]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@45:5"},"@exit":{"kind":"exit","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"42:5","kind":"fallthrough"},{"src":"42:5","dst":"43:7","kind":"true"},{"src":"42:5","dst":"45:5","kind":"false"},{"src":"43:7","dst":"@exit","kind":"exception"},{"src":"43:7","dst":"42:5","kind":"loop_back"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"41:5"},{"src":"@entry","dst":"42:5"},{"src":"42:5","dst":"43:7"},{"src":"42:5","dst":"45:5"},{"src":"43:7","dst":"42:5"}],"ddg":[{"src":"@entry","dst":"42:5","var":"this.users","prov":["reaching-defs"]},{"src":"41:5","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"41:5","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"42:5","dst":"43:7","var":"u.recordLogin","prov":["reaching-defs"]},{"src":"43:7","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"43:7","dst":"45:5","var":"total","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[164,187]},"id":"can://slim/typescript/src/services.ts/makeGuestName@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"@entry","dst":"5:3","var":"seed","prov":["reaching-defs"]}]},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"},"@entry":{"kind":"entry","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@entry"},"13:3":{"kind":"statement","span":{"start":[13,3],"end":[13,27],"bytes":[400,424]},"id":"can://slim/typescript/src/services.ts/announce@13:3"},"@exit":{"kind":"exit","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"13:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]}]},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@entry"},"17:46":{"kind":"statement","span":{"start":[17,46],"end":[17,51],"bytes":[550,555]},"id":"can://slim/typescript/src/services.ts/nextId@17:46"},"@exit":{"kind":"exit","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"17:46","kind":"fallthrough"},{"src":"17:46","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"17:46"}],"ddg":[{"src":"@entry","dst":"17:46","var":"n","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"},"@entry":{"kind":"entry","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@entry"},"15:7":{"kind":"statement","span":{"start":[15,7],"end":[15,19],"bytes":[456,468]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@15:7"},"@exit":{"kind":"exit","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"14:7","kind":"fallthrough"},{"src":"14:7","dst":"@exit","kind":"exception"},{"src":"14:7","dst":"15:7","kind":"fallthrough"},{"src":"15:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"14:7"},{"src":"14:7","dst":"15:7"}],"ddg":[{"src":"@entry","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@entry","dst":"14:7","var":"this.parts.push","prov":["reaching-defs"]},{"src":"@entry","dst":"15:7","var":"this","prov":["reaching-defs"]}]},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"},"@entry":{"kind":"entry","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@entry"},"18:7":{"kind":"statement","span":{"start":[18,7],"end":[18,35],"bytes":[503,531]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7"},"@exit":{"kind":"exit","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"18:7","kind":"fallthrough"},{"src":"18:7","dst":"@exit","kind":"exception"},{"src":"18:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"18:7"}],"ddg":[{"src":"@entry","dst":"18:7","var":"this.parts.join","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"},"@entry":{"kind":"entry","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@entry"},"4:5":{"kind":"statement","span":{"start":[4,5],"end":[4,30],"bytes":[197,222]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5"},"@exit":{"kind":"exit","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"4:5","kind":"fallthrough"},{"src":"4:5","dst":"@exit","kind":"exception"},{"src":"4:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"4:5"}],"ddg":[{"src":"@entry","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@entry","dst":"4:5","var":"s","prov":["reaching-defs"]}]},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"},"@entry":{"kind":"entry","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@entry"},"8:5":{"kind":"statement","span":{"start":[8,5],"end":[8,49],"bytes":[276,320]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5"},"@exit":{"kind":"exit","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:5","kind":"fallthrough"},{"src":"8:5","dst":"@exit","kind":"exception"},{"src":"8:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:5"}],"ddg":[{"src":"@entry","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]}]}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"},"@entry":{"kind":"entry","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@entry"},"25:3":{"kind":"statement","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify@25:3"},"28:3":{"kind":"statement","span":{"start":[28,3],"end":[28,39],"bytes":[803,839]},"id":"can://slim/typescript/src/util.ts/classify@28:3"},"29:3":{"kind":"statement","span":{"start":[29,3],"end":[32,4],"bytes":[842,932]},"id":"can://slim/typescript/src/util.ts/classify@29:3"},"30:5":{"kind":"statement","span":{"start":[30,5],"end":[30,27],"bytes":[874,896]},"id":"can://slim/typescript/src/util.ts/classify@30:5"},"33:3":{"kind":"statement","span":{"start":[33,3],"end":[33,14],"bytes":[935,946]},"id":"can://slim/typescript/src/util.ts/classify@33:3"},"@exit":{"kind":"exit","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@exit"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"},"@entry":{"kind":"entry","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,32],"bytes":[769,796]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5"},"@exit":{"kind":"exit","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:3","kind":"fallthrough"},{"src":"25:3","dst":"@exit","kind":"exception"},{"src":"25:3","dst":"28:3","kind":"fallthrough"},{"src":"28:3","dst":"29:3","kind":"fallthrough"},{"src":"29:3","dst":"30:5","kind":"true"},{"src":"29:3","dst":"33:3","kind":"false"},{"src":"30:5","dst":"@exit","kind":"exception"},{"src":"30:5","dst":"31:5","kind":"fallthrough"},{"src":"31:5","dst":"@exit","kind":"exception"},{"src":"31:5","dst":"29:3","kind":"loop_back"},{"src":"33:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:3"},{"src":"25:3","dst":"28:3"},{"src":"25:3","dst":"29:3"},{"src":"29:3","dst":"30:5"},{"src":"29:3","dst":"33:3"},{"src":"30:5","dst":"31:5"},{"src":"31:5","dst":"29:3"}],"ddg":[{"src":"@entry","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"28:3","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"28:3","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"31:5","var":"item","prov":["reaching-defs"]},{"src":"30:5","dst":"31:5","var":"k","prov":["reaching-defs"]},{"src":"31:5","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"31:5","dst":"33:3","var":"out","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file +{"schema_version":"2.0.0","language":"typescript","max_level":3,"k_limit":3,"analyzer":{"name":"codeanalyzer-typescript","version":"1.6.0"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"},"@entry":{"kind":"entry","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@entry"},"20:5":{"kind":"statement","span":{"start":[20,5],"end":[20,42],"bytes":[550,587]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5"},"21:5":{"kind":"statement","span":{"start":[21,5],"end":[21,28],"bytes":[592,615]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5"},"@exit":{"kind":"exit","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"20:5","kind":"fallthrough"},{"src":"20:5","dst":"@exit","kind":"exception"},{"src":"20:5","dst":"21:5","kind":"fallthrough"},{"src":"21:5","dst":"@exit","kind":"exception"},{"src":"21:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"20:5"},{"src":"20:5","dst":"21:5"}],"ddg":[{"src":"@entry","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"this.service.create","prov":["reaching-defs"]},{"src":"20:5","dst":"21:5","var":"user.describe","prov":["reaching-defs"]}]},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,39],"bytes":[658,692]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"this.service.describeAll","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[200,223]},"id":"can://slim/typescript/src/controllers.ts/Controller@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@entry"},"5:16":{"kind":"statement","span":{"start":[5,16],"end":[5,25],"bytes":[213,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@5:16"},"@exit":{"kind":"exit","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:16","kind":"fallthrough"},{"src":"5:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[]},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@entry"},"8:3":{"kind":"statement","span":{"start":[8,3],"end":[8,26],"bytes":[274,297]},"id":"can://slim/typescript/src/controllers.ts/Get@8:3"},"@exit":{"kind":"exit","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@entry"},"8:16":{"kind":"statement","span":{"start":[8,16],"end":[8,25],"bytes":[287,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@8:16"},"@exit":{"kind":"exit","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:16","kind":"fallthrough"},{"src":"8:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:3"}],"ddg":[]},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@entry"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,26],"bytes":[353,376]},"id":"can://slim/typescript/src/controllers.ts/Param@11:3"},"@exit":{"kind":"exit","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@exit"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@entry"},"11:16":{"kind":"statement","span":{"start":[11,16],"end":[11,25],"bytes":[366,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@11:16"},"@exit":{"kind":"exit","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:16","kind":"fallthrough"},{"src":"11:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:16"}],"ddg":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:3"}],"ddg":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"},"@entry":{"kind":"entry","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@entry"},"7:3":{"kind":"statement","span":{"start":[7,3],"end":[7,40],"bytes":[217,254]},"id":"can://slim/typescript/src/index.ts/main@7:3"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,50],"bytes":[320,367]},"id":"can://slim/typescript/src/index.ts/main@11:3"},"19:3":{"kind":"statement","span":{"start":[19,3],"end":[19,52],"bytes":[579,628]},"id":"can://slim/typescript/src/index.ts/main@19:3"},"20:3":{"kind":"statement","span":{"start":[20,3],"end":[20,44],"bytes":[631,672]},"id":"can://slim/typescript/src/index.ts/main@20:3"},"@exit":{"kind":"exit","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"7:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"exception"},{"src":"11:3","dst":"12:3","kind":"fallthrough"},{"src":"12:3","dst":"@exit","kind":"exception"},{"src":"12:3","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"16:3","kind":"fallthrough"},{"src":"16:3","dst":"@exit","kind":"exception"},{"src":"16:3","dst":"17:3","kind":"fallthrough"},{"src":"17:3","dst":"@exit","kind":"exception"},{"src":"17:3","dst":"19:3","kind":"fallthrough"},{"src":"19:3","dst":"@exit","kind":"exception"},{"src":"19:3","dst":"20:3","kind":"fallthrough"},{"src":"20:3","dst":"@exit","kind":"exception"},{"src":"20:3","dst":"21:3","kind":"fallthrough"},{"src":"21:3","dst":"@exit","kind":"exception"},{"src":"21:3","dst":"22:3","kind":"fallthrough"},{"src":"22:3","dst":"@exit","kind":"exception"},{"src":"22:3","dst":"@exit","kind":"fallthrough"},{"src":"7:3","dst":"@exit","kind":"exception"},{"src":"7:3","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"exception"},{"src":"8:3","dst":"9:3","kind":"fallthrough"},{"src":"9:3","dst":"@exit","kind":"exception"},{"src":"9:3","dst":"11:3","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"7:3"},{"src":"11:3","dst":"12:3"},{"src":"12:3","dst":"13:3"},{"src":"13:3","dst":"16:3"},{"src":"16:3","dst":"17:3"},{"src":"17:3","dst":"19:3"},{"src":"19:3","dst":"20:3"},{"src":"20:3","dst":"21:3"},{"src":"21:3","dst":"22:3"},{"src":"7:3","dst":"8:3"},{"src":"8:3","dst":"9:3"},{"src":"9:3","dst":"11:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"8:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"9:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"11:3","dst":"12:3","var":"controller.list","prov":["reaching-defs"]},{"src":"11:3","dst":"13:3","var":"controller.show","prov":["reaching-defs"]},{"src":"19:3","dst":"22:3","var":"slug","prov":["reaching-defs"]},{"src":"20:3","dst":"21:3","var":"builder.add","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"8:3","var":"service.create","prov":["reaching-defs"]},{"src":"7:3","dst":"9:3","var":"service.createGuest","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@entry"},"49:5":{"kind":"statement","span":{"start":[49,5],"end":[49,42],"bytes":[872,909]},"id":"can://slim/typescript/src/models.ts/User/describe@49:5"},"@exit":{"kind":"exit","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"49:5","kind":"fallthrough"},{"src":"49:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"49:5"}],"ddg":[{"src":"@entry","dst":"49:5","var":"this.name","prov":["reaching-defs"]},{"src":"@entry","dst":"49:5","var":"this.role","prov":["reaching-defs"]}]},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@entry"},"53:5":{"kind":"statement","span":{"start":[53,5],"end":[53,26],"bytes":[960,981]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@53:5"},"54:5":{"kind":"statement","span":{"start":[54,5],"end":[54,28],"bytes":[986,1009]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@54:5"},"@exit":{"kind":"exit","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"53:5","kind":"fallthrough"},{"src":"53:5","dst":"54:5","kind":"fallthrough"},{"src":"54:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"53:5"},{"src":"@entry","dst":"54:5"}],"ddg":[{"src":"@entry","dst":"53:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"@entry","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"53:5","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"},"@entry":{"kind":"entry","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,22],"bytes":[753,770]},"id":"can://slim/typescript/src/models.ts/User/constructor@41:5"},"@exit":{"kind":"exit","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"40:5","kind":"fallthrough"},{"src":"40:5","dst":"@exit","kind":"exception"},{"src":"40:5","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"@exit","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"40:5"},{"src":"40:5","dst":"41:5"}],"ddg":[{"src":"@entry","dst":"40:5","var":"id","prov":["reaching-defs"]}]},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@entry"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,37],"bytes":[807,839]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@45:5"},"@exit":{"kind":"exit","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"45:5","kind":"fallthrough"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"45:5"}],"ddg":[{"src":"@entry","dst":"45:5","var":"this.role","prov":["reaching-defs"]}]}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@entry"},"62:5":{"kind":"statement","span":{"start":[62,5],"end":[62,33],"bytes":[1202,1230]},"id":"can://slim/typescript/src/models.ts/Robot/describe@62:5"},"@exit":{"kind":"exit","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"62:5","kind":"fallthrough"},{"src":"62:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"62:5"}],"ddg":[{"src":"@entry","dst":"62:5","var":"this.name","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@entry"},"25:5":{"kind":"statement","span":{"start":[25,5],"end":[25,57],"bytes":[733,785]},"id":"can://slim/typescript/src/services.ts/UserService/create@25:5"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,43],"bytes":[790,828]},"id":"can://slim/typescript/src/services.ts/UserService/create@26:5"},"28:5":{"kind":"statement","span":{"start":[28,5],"end":[28,17],"bytes":[860,872]},"id":"can://slim/typescript/src/services.ts/UserService/create@28:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:5","kind":"fallthrough"},{"src":"25:5","dst":"@exit","kind":"exception"},{"src":"25:5","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"27:5","kind":"fallthrough"},{"src":"27:5","dst":"@exit","kind":"exception"},{"src":"27:5","dst":"28:5","kind":"fallthrough"},{"src":"28:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:5"},{"src":"25:5","dst":"26:5"},{"src":"26:5","dst":"27:5"},{"src":"27:5","dst":"28:5"}],"ddg":[{"src":"@entry","dst":"25:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@entry","dst":"27:5","var":"this.users.push","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5","var":"id","prov":["reaching-defs"]},{"src":"26:5","dst":"27:5","var":"user","prov":["reaching-defs"]},{"src":"26:5","dst":"28:5","var":"user","prov":["reaching-defs"]}]},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"},"@entry":{"kind":"entry","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@entry"},"32:5":{"kind":"statement","span":{"start":[32,5],"end":[32,51],"bytes":[906,952]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5"},"33:5":{"kind":"statement","span":{"start":[33,5],"end":[33,42],"bytes":[957,994]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5"},"@exit":{"kind":"exit","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"32:5","kind":"fallthrough"},{"src":"32:5","dst":"@exit","kind":"exception"},{"src":"32:5","dst":"33:5","kind":"fallthrough"},{"src":"33:5","dst":"@exit","kind":"exception"},{"src":"33:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"32:5"},{"src":"32:5","dst":"33:5"}],"ddg":[{"src":"@entry","dst":"32:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"this.create","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5","var":"name","prov":["reaching-defs"]}]},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"},"@entry":{"kind":"entry","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@entry"},"37:5":{"kind":"statement","span":{"start":[37,5],"end":[37,48],"bytes":[1032,1075]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5"},"@exit":{"kind":"exit","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@exit"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"},"@entry":{"kind":"entry","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@entry"},"@exit":{"kind":"exit","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:34","kind":"fallthrough"},{"src":"37:34","dst":"@exit","kind":"exception"},{"src":"37:34","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:34"}],"ddg":[{"src":"@entry","dst":"37:34","var":"u.describe","prov":["reaching-defs"]}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:5","kind":"fallthrough"},{"src":"37:5","dst":"@exit","kind":"exception"},{"src":"37:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:5"}],"ddg":[{"src":"@entry","dst":"37:5","var":"this.users.map","prov":["reaching-defs"]}]},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"},"@entry":{"kind":"entry","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,19],"bytes":[1123,1137]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@41:5"},"42:5":{"kind":"statement","span":{"start":[42,5],"end":[44,6],"bytes":[1142,1215]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@42:5"},"43:7":{"kind":"statement","span":{"start":[43,7],"end":[43,38],"bytes":[1178,1209]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,18],"bytes":[1220,1233]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@45:5"},"@exit":{"kind":"exit","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"42:5","kind":"fallthrough"},{"src":"42:5","dst":"43:7","kind":"true"},{"src":"42:5","dst":"45:5","kind":"false"},{"src":"43:7","dst":"@exit","kind":"exception"},{"src":"43:7","dst":"42:5","kind":"loop_back"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"41:5"},{"src":"@entry","dst":"42:5"},{"src":"42:5","dst":"43:7"},{"src":"42:5","dst":"45:5"},{"src":"43:7","dst":"42:5"}],"ddg":[{"src":"@entry","dst":"42:5","var":"this.users","prov":["reaching-defs"]},{"src":"41:5","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"41:5","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"42:5","dst":"43:7","var":"u.recordLogin","prov":["reaching-defs"]},{"src":"43:7","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"43:7","dst":"45:5","var":"total","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[]}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[164,187]},"id":"can://slim/typescript/src/services.ts/makeGuestName@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"@entry","dst":"5:3","var":"seed","prov":["reaching-defs"]}]},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"},"@entry":{"kind":"entry","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@entry"},"13:3":{"kind":"statement","span":{"start":[13,3],"end":[13,27],"bytes":[400,424]},"id":"can://slim/typescript/src/services.ts/announce@13:3"},"@exit":{"kind":"exit","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"13:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]}]},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@entry"},"17:46":{"kind":"statement","span":{"start":[17,46],"end":[17,51],"bytes":[550,555]},"id":"can://slim/typescript/src/services.ts/nextId@17:46"},"@exit":{"kind":"exit","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"17:46","kind":"fallthrough"},{"src":"17:46","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"17:46"}],"ddg":[{"src":"@entry","dst":"17:46","var":"n","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"},"@entry":{"kind":"entry","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@entry"},"15:7":{"kind":"statement","span":{"start":[15,7],"end":[15,19],"bytes":[456,468]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@15:7"},"@exit":{"kind":"exit","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"14:7","kind":"fallthrough"},{"src":"14:7","dst":"@exit","kind":"exception"},{"src":"14:7","dst":"15:7","kind":"fallthrough"},{"src":"15:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"14:7"},{"src":"14:7","dst":"15:7"}],"ddg":[{"src":"@entry","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@entry","dst":"14:7","var":"this.parts.push","prov":["reaching-defs"]},{"src":"@entry","dst":"15:7","var":"this","prov":["reaching-defs"]}]},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"},"@entry":{"kind":"entry","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@entry"},"18:7":{"kind":"statement","span":{"start":[18,7],"end":[18,35],"bytes":[503,531]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7"},"@exit":{"kind":"exit","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"18:7","kind":"fallthrough"},{"src":"18:7","dst":"@exit","kind":"exception"},{"src":"18:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"18:7"}],"ddg":[{"src":"@entry","dst":"18:7","var":"this.parts.join","prov":["reaching-defs"]}]},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"},"@entry":{"kind":"entry","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@entry"},"4:5":{"kind":"statement","span":{"start":[4,5],"end":[4,30],"bytes":[197,222]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5"},"@exit":{"kind":"exit","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"4:5","kind":"fallthrough"},{"src":"4:5","dst":"@exit","kind":"exception"},{"src":"4:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"4:5"}],"ddg":[{"src":"@entry","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@entry","dst":"4:5","var":"s","prov":["reaching-defs"]}]},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"},"@entry":{"kind":"entry","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@entry"},"8:5":{"kind":"statement","span":{"start":[8,5],"end":[8,49],"bytes":[276,320]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5"},"@exit":{"kind":"exit","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:5","kind":"fallthrough"},{"src":"8:5","dst":"@exit","kind":"exception"},{"src":"8:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:5"}],"ddg":[{"src":"@entry","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]}]}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"},"@entry":{"kind":"entry","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@entry"},"25:3":{"kind":"statement","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify@25:3"},"28:3":{"kind":"statement","span":{"start":[28,3],"end":[28,39],"bytes":[803,839]},"id":"can://slim/typescript/src/util.ts/classify@28:3"},"29:3":{"kind":"statement","span":{"start":[29,3],"end":[32,4],"bytes":[842,932]},"id":"can://slim/typescript/src/util.ts/classify@29:3"},"30:5":{"kind":"statement","span":{"start":[30,5],"end":[30,27],"bytes":[874,896]},"id":"can://slim/typescript/src/util.ts/classify@30:5"},"33:3":{"kind":"statement","span":{"start":[33,3],"end":[33,14],"bytes":[935,946]},"id":"can://slim/typescript/src/util.ts/classify@33:3"},"@exit":{"kind":"exit","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@exit"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"},"@entry":{"kind":"entry","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,32],"bytes":[769,796]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5"},"@exit":{"kind":"exit","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@exit"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:3","kind":"fallthrough"},{"src":"25:3","dst":"@exit","kind":"exception"},{"src":"25:3","dst":"28:3","kind":"fallthrough"},{"src":"28:3","dst":"29:3","kind":"fallthrough"},{"src":"29:3","dst":"30:5","kind":"true"},{"src":"29:3","dst":"33:3","kind":"false"},{"src":"30:5","dst":"@exit","kind":"exception"},{"src":"30:5","dst":"31:5","kind":"fallthrough"},{"src":"31:5","dst":"@exit","kind":"exception"},{"src":"31:5","dst":"29:3","kind":"loop_back"},{"src":"33:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:3"},{"src":"25:3","dst":"28:3"},{"src":"25:3","dst":"29:3"},{"src":"29:3","dst":"30:5"},{"src":"29:3","dst":"33:3"},{"src":"30:5","dst":"31:5"},{"src":"31:5","dst":"29:3"}],"ddg":[{"src":"@entry","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"28:3","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"28:3","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"31:5","var":"item","prov":["reaching-defs"]},{"src":"30:5","dst":"31:5","var":"k","prov":["reaching-defs"]},{"src":"31:5","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"31:5","dst":"33:3","var":"out","prov":["reaching-defs"]}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[],"param_out":[],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file diff --git a/tests/resources/typescript/analysis_json/v2/a4/analysis.json b/tests/resources/typescript/analysis_json/v2/a4/analysis.json index ceeebe1..756f851 100644 --- a/tests/resources/typescript/analysis_json/v2/a4/analysis.json +++ b/tests/resources/typescript/analysis_json/v2/a4/analysis.json @@ -1 +1 @@ -{"schema_version":"2.0.0","language":"typescript","max_level":4,"k_limit":3,"analyzer":{"name":"codeanalyzer-typescript","version":"1.5.3"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"},"@entry":{"kind":"entry","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@entry"},"20:5":{"kind":"statement","span":{"start":[20,5],"end":[20,42],"bytes":[550,587]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5"},"21:5":{"kind":"statement","span":{"start":[21,5],"end":[21,28],"bytes":[592,615]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5"},"@exit":{"kind":"exit","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_out"},"20:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"20:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_in:0"},"20:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"20:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_out"},"21:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"21:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"20:5","kind":"fallthrough"},{"src":"20:5","dst":"@exit","kind":"exception"},{"src":"20:5","dst":"21:5","kind":"fallthrough"},{"src":"21:5","dst":"@exit","kind":"exception"},{"src":"21:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"20:5"},{"src":"20:5","dst":"21:5"}],"ddg":[{"src":"@entry","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"this.service.create","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"20:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"20:5","dst":"21:5","var":"user.describe","prov":["reaching-defs"]},{"src":"20:5/actual_out","dst":"20:5","var":"$ret","prov":["reaching-defs"]},{"src":"21:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"21:5/actual_out","dst":"21:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"20:5","dst":"20:5","var":"src/services.nextId"},{"src":"20:5/actual_in:0","dst":"20:5/actual_out"}]},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,39],"bytes":[658,692]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/list@formal_out"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"this.service.describeAll","prov":["reaching-defs"]},{"src":"26:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"26:5/actual_out","dst":"26:5","var":"$ret","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"service","id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[200,223]},"id":"can://slim/typescript/src/controllers.ts/Controller@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@exit"},"@formal_in:0":{"kind":"formal_in","of":"prefix","id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Controller@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@entry"},"5:16":{"kind":"statement","span":{"start":[5,16],"end":[5,25],"bytes":[213,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@5:16"},"@exit":{"kind":"exit","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Controller/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:16","kind":"fallthrough"},{"src":"5:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:16"}],"ddg":[{"src":"5:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"5:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@entry"},"8:3":{"kind":"statement","span":{"start":[8,3],"end":[8,26],"bytes":[274,297]},"id":"can://slim/typescript/src/controllers.ts/Get@8:3"},"@exit":{"kind":"exit","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@exit"},"@formal_in:0":{"kind":"formal_in","of":"path","id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Get@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@entry"},"8:16":{"kind":"statement","span":{"start":[8,16],"end":[8,25],"bytes":[287,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@8:16"},"@exit":{"kind":"exit","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Get/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:16","kind":"fallthrough"},{"src":"8:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:16"}],"ddg":[{"src":"8:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:3"}],"ddg":[{"src":"8:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@entry"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,26],"bytes":[353,376]},"id":"can://slim/typescript/src/controllers.ts/Param@11:3"},"@exit":{"kind":"exit","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Param@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@entry"},"11:16":{"kind":"statement","span":{"start":[11,16],"end":[11,25],"bytes":[366,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@11:16"},"@exit":{"kind":"exit","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Param/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:16","kind":"fallthrough"},{"src":"11:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:16"}],"ddg":[{"src":"11:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:3"}],"ddg":[{"src":"11:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"},"@entry":{"kind":"entry","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@entry"},"7:3":{"kind":"statement","span":{"start":[7,3],"end":[7,40],"bytes":[217,254]},"id":"can://slim/typescript/src/index.ts/main@7:3"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,50],"bytes":[320,367]},"id":"can://slim/typescript/src/index.ts/main@11:3"},"19:3":{"kind":"statement","span":{"start":[19,3],"end":[19,52],"bytes":[579,628]},"id":"can://slim/typescript/src/index.ts/main@19:3"},"20:3":{"kind":"statement","span":{"start":[20,3],"end":[20,44],"bytes":[631,672]},"id":"can://slim/typescript/src/index.ts/main@20:3"},"@exit":{"kind":"exit","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/index.ts/main@formal_out"},"11:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"11:3","id":"can://slim/typescript/src/index.ts/main@11:3/actual_out"},"12:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"12:3","id":"can://slim/typescript/src/index.ts/main@12:3/actual_out"},"13:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"13:3","id":"can://slim/typescript/src/index.ts/main@13:3/actual_out"},"7:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"7:3","id":"can://slim/typescript/src/index.ts/main@7:3/actual_in:0"},"8:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_in:0"},"8:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_out"},"8:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_in:1"},"11:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"11:3","id":"can://slim/typescript/src/index.ts/main@11:3/actual_in:0"},"13:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"13:3","id":"can://slim/typescript/src/index.ts/main@13:3/actual_in:0"},"16:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0"},"16:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_out"},"16:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:1"},"16:3/actual_in:2":{"kind":"actual_in","of":"arg2","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:2"},"17:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"17:3","id":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0"},"17:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"17:3","id":"can://slim/typescript/src/index.ts/main@17:3/actual_out"},"19:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_in:0"},"19:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_out"},"19:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_in:1"},"21:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"21:3","id":"can://slim/typescript/src/index.ts/main@21:3/actual_in:0"},"22:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"22:3","id":"can://slim/typescript/src/index.ts/main@22:3/actual_in:0"},"22:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"22:3","id":"can://slim/typescript/src/index.ts/main@22:3/actual_out"},"7:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"7:3","id":"can://slim/typescript/src/index.ts/main@7:3/actual_out"},"9:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"9:3","id":"can://slim/typescript/src/index.ts/main@9:3/actual_out"},"21:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"21:3","id":"can://slim/typescript/src/index.ts/main@21:3/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"7:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"exception"},{"src":"11:3","dst":"12:3","kind":"fallthrough"},{"src":"12:3","dst":"@exit","kind":"exception"},{"src":"12:3","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"16:3","kind":"fallthrough"},{"src":"16:3","dst":"@exit","kind":"exception"},{"src":"16:3","dst":"17:3","kind":"fallthrough"},{"src":"17:3","dst":"@exit","kind":"exception"},{"src":"17:3","dst":"19:3","kind":"fallthrough"},{"src":"19:3","dst":"@exit","kind":"exception"},{"src":"19:3","dst":"20:3","kind":"fallthrough"},{"src":"20:3","dst":"@exit","kind":"exception"},{"src":"20:3","dst":"21:3","kind":"fallthrough"},{"src":"21:3","dst":"@exit","kind":"exception"},{"src":"21:3","dst":"22:3","kind":"fallthrough"},{"src":"22:3","dst":"@exit","kind":"exception"},{"src":"22:3","dst":"@exit","kind":"fallthrough"},{"src":"7:3","dst":"@exit","kind":"exception"},{"src":"7:3","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"exception"},{"src":"8:3","dst":"9:3","kind":"fallthrough"},{"src":"9:3","dst":"@exit","kind":"exception"},{"src":"9:3","dst":"11:3","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"7:3"},{"src":"11:3","dst":"12:3"},{"src":"12:3","dst":"13:3"},{"src":"13:3","dst":"16:3"},{"src":"16:3","dst":"17:3"},{"src":"17:3","dst":"19:3"},{"src":"19:3","dst":"20:3"},{"src":"20:3","dst":"21:3"},{"src":"21:3","dst":"22:3"},{"src":"7:3","dst":"8:3"},{"src":"8:3","dst":"9:3"},{"src":"9:3","dst":"11:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"8:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"9:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"11:3","dst":"12:3","var":"controller.list","prov":["reaching-defs"]},{"src":"11:3","dst":"13:3","var":"controller.show","prov":["reaching-defs"]},{"src":"11:3/actual_out","dst":"11:3","var":"$ret","prov":["reaching-defs"]},{"src":"12:3/actual_out","dst":"12:3","var":"$ret","prov":["reaching-defs"]},{"src":"13:3/actual_out","dst":"13:3","var":"$ret","prov":["reaching-defs"]},{"src":"16:3/actual_out","dst":"16:3","var":"$ret","prov":["reaching-defs"]},{"src":"17:3/actual_out","dst":"17:3","var":"$ret","prov":["reaching-defs"]},{"src":"19:3","dst":"22:3","var":"slug","prov":["reaching-defs"]},{"src":"19:3/actual_out","dst":"19:3","var":"$ret","prov":["reaching-defs"]},{"src":"20:3","dst":"21:3","var":"builder.add","prov":["reaching-defs"]},{"src":"21:3/actual_out","dst":"21:3","var":"$ret","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3/actual_in:0","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"8:3","var":"service.create","prov":["reaching-defs"]},{"src":"7:3","dst":"9:3","var":"service.createGuest","prov":["reaching-defs"]},{"src":"7:3/actual_out","dst":"7:3","var":"$ret","prov":["reaching-defs"]},{"src":"8:3/actual_out","dst":"8:3","var":"$ret","prov":["reaching-defs"]},{"src":"9:3/actual_out","dst":"9:3","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"13:3","dst":"13:3","var":"src/services.nextId"},{"src":"13:3/actual_in:0","dst":"13:3/actual_out"},{"src":"16:3/actual_in:0","dst":"16:3/actual_out"},{"src":"17:3/actual_in:0","dst":"17:3/actual_out"},{"src":"19:3/actual_in:0","dst":"19:3/actual_out"},{"src":"19:3/actual_in:1","dst":"19:3/actual_out"},{"src":"22:3/actual_in:0","dst":"22:3/actual_out"},{"src":"8:3","dst":"8:3","var":"src/services.nextId"},{"src":"8:3/actual_in:0","dst":"8:3/actual_out"},{"src":"8:3/actual_in:1","dst":"8:3/actual_out"},{"src":"9:3","dst":"9:3","var":"src/services.nextId"}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@entry"},"49:5":{"kind":"statement","span":{"start":[49,5],"end":[49,42],"bytes":[872,909]},"id":"can://slim/typescript/src/models.ts/User/describe@49:5"},"@exit":{"kind":"exit","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/describe@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"49:5","kind":"fallthrough"},{"src":"49:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"49:5"}],"ddg":[{"src":"@entry","dst":"49:5","var":"this.name","prov":["reaching-defs"]},{"src":"@entry","dst":"49:5","var":"this.role","prov":["reaching-defs"]},{"src":"49:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@entry"},"53:5":{"kind":"statement","span":{"start":[53,5],"end":[53,26],"bytes":[960,981]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@53:5"},"54:5":{"kind":"statement","span":{"start":[54,5],"end":[54,28],"bytes":[986,1009]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@54:5"},"@exit":{"kind":"exit","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/recordLogin@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"53:5","kind":"fallthrough"},{"src":"53:5","dst":"54:5","kind":"fallthrough"},{"src":"54:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"53:5"},{"src":"@entry","dst":"54:5"}],"ddg":[{"src":"@entry","dst":"53:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"@entry","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"53:5","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"54:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"},"@entry":{"kind":"entry","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,22],"bytes":[753,770]},"id":"can://slim/typescript/src/models.ts/User/constructor@41:5"},"@exit":{"kind":"exit","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},"@formal_in:2":{"kind":"formal_in","of":"role","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/constructor@formal_out"},"40:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"40:5","id":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_out"},"40:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"40:5","id":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_in:0"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"40:5","kind":"fallthrough"},{"src":"40:5","dst":"@exit","kind":"exception"},{"src":"40:5","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"@exit","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"40:5"},{"src":"40:5","dst":"41:5"}],"ddg":[{"src":"@entry","dst":"40:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"40:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"40:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"40:5/actual_out","dst":"40:5","var":"$ret","prov":["reaching-defs"]}],"summary":[]},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@entry"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,37],"bytes":[807,839]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@45:5"},"@exit":{"kind":"exit","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/isAdmin@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"45:5","kind":"fallthrough"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"45:5"}],"ddg":[{"src":"@entry","dst":"45:5","var":"this.role","prov":["reaching-defs"]},{"src":"45:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@entry"},"62:5":{"kind":"statement","span":{"start":[62,5],"end":[62,33],"bytes":[1202,1230]},"id":"can://slim/typescript/src/models.ts/Robot/describe@62:5"},"@exit":{"kind":"exit","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Robot/describe@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"62:5","kind":"fallthrough"},{"src":"62:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"62:5"}],"ddg":[{"src":"@entry","dst":"62:5","var":"this.name","prov":["reaching-defs"]},{"src":"62:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@entry"},"25:5":{"kind":"statement","span":{"start":[25,5],"end":[25,57],"bytes":[733,785]},"id":"can://slim/typescript/src/services.ts/UserService/create@25:5"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,43],"bytes":[790,828]},"id":"can://slim/typescript/src/services.ts/UserService/create@26:5"},"28:5":{"kind":"statement","span":{"start":[28,5],"end":[28,17],"bytes":[860,872]},"id":"can://slim/typescript/src/services.ts/UserService/create@28:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"role","id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/create@formal_out"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_out"},"25:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"25:5","id":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_out"},"25:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"25:5","id":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_in:0"},"26:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:0"},"26:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:1"},"26:5/actual_in:2":{"kind":"actual_in","of":"arg2","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:2"},"27:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"27:5","id":"can://slim/typescript/src/services.ts/UserService/create@27:5/actual_in:0"},"27:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"27:5","id":"can://slim/typescript/src/services.ts/UserService/create@27:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:5","kind":"fallthrough"},{"src":"25:5","dst":"@exit","kind":"exception"},{"src":"25:5","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"27:5","kind":"fallthrough"},{"src":"27:5","dst":"@exit","kind":"exception"},{"src":"27:5","dst":"28:5","kind":"fallthrough"},{"src":"28:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:5"},{"src":"25:5","dst":"26:5"},{"src":"26:5","dst":"27:5"},{"src":"27:5","dst":"28:5"}],"ddg":[{"src":"@entry","dst":"25:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5/actual_in:0","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5/actual_in:0","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@entry","dst":"27:5","var":"this.users.push","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5/actual_in:1","var":"name","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"26:5/actual_in:2","var":"role","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5","var":"id","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"25:5/actual_out","dst":"25:5","var":"$ret","prov":["reaching-defs"]},{"src":"26:5","dst":"27:5","var":"user","prov":["reaching-defs"]},{"src":"26:5","dst":"28:5","var":"user","prov":["reaching-defs"]},{"src":"26:5/actual_out","dst":"26:5","var":"$ret","prov":["reaching-defs"]},{"src":"28:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"25:5/actual_in:0","dst":"25:5/actual_out"},{"src":"27:5/actual_in:0","dst":"27:5/actual_out"}]},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"},"@entry":{"kind":"entry","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@entry"},"32:5":{"kind":"statement","span":{"start":[32,5],"end":[32,51],"bytes":[906,952]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5"},"33:5":{"kind":"statement","span":{"start":[33,5],"end":[33,42],"bytes":[957,994]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5"},"@exit":{"kind":"exit","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/createGuest@formal_out"},"32:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"32:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_out"},"33:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_out"},"32:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"32:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_in:0"},"33:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:0"},"33:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:1"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"32:5","kind":"fallthrough"},{"src":"32:5","dst":"@exit","kind":"exception"},{"src":"32:5","dst":"33:5","kind":"fallthrough"},{"src":"33:5","dst":"@exit","kind":"exception"},{"src":"33:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"32:5"},{"src":"32:5","dst":"33:5"}],"ddg":[{"src":"@entry","dst":"32:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"32:5/actual_in:0","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"this.create","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5","var":"name","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5/actual_in:0","var":"name","prov":["reaching-defs"]},{"src":"32:5/actual_out","dst":"32:5","var":"$ret","prov":["reaching-defs"]},{"src":"33:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"33:5/actual_out","dst":"33:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"32:5/actual_in:0","dst":"32:5/actual_out"},{"src":"33:5","dst":"33:5","var":"src/services.nextId"},{"src":"33:5/actual_in:0","dst":"33:5/actual_out"},{"src":"33:5/actual_in:1","dst":"33:5/actual_out"}]},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"},"@entry":{"kind":"entry","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@entry"},"37:5":{"kind":"statement","span":{"start":[37,5],"end":[37,48],"bytes":[1032,1075]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5"},"@exit":{"kind":"exit","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/describeAll@formal_out"},"37:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"37:5","id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5/actual_in:0"},"37:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"37:5","id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5/actual_out"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"},"@entry":{"kind":"entry","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@entry"},"@exit":{"kind":"exit","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@exit"},"@formal_in:0":{"kind":"formal_in","of":"u","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_out"},"37:34/actual_out":{"kind":"actual_out","of":"$ret","parent":"37:34","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:34","kind":"fallthrough"},{"src":"37:34","dst":"@exit","kind":"exception"},{"src":"37:34","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:34"}],"ddg":[{"src":"@entry","dst":"37:34","var":"u.describe","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"37:34","var":"u.describe","prov":["reaching-defs"]},{"src":"37:34","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"37:34/actual_out","dst":"37:34","var":"$ret","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:5","kind":"fallthrough"},{"src":"37:5","dst":"@exit","kind":"exception"},{"src":"37:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:5"}],"ddg":[{"src":"@entry","dst":"37:5","var":"this.users.map","prov":["reaching-defs"]},{"src":"37:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"37:5/actual_in:0","dst":"37:5/actual_out"}]},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"},"@entry":{"kind":"entry","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,19],"bytes":[1123,1137]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@41:5"},"42:5":{"kind":"statement","span":{"start":[42,5],"end":[44,6],"bytes":[1142,1215]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@42:5"},"43:7":{"kind":"statement","span":{"start":[43,7],"end":[43,38],"bytes":[1178,1209]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,18],"bytes":[1220,1233]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@45:5"},"@exit":{"kind":"exit","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/loginAll@formal_out"},"43:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"43:7","id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"42:5","kind":"fallthrough"},{"src":"42:5","dst":"43:7","kind":"true"},{"src":"42:5","dst":"45:5","kind":"false"},{"src":"43:7","dst":"@exit","kind":"exception"},{"src":"43:7","dst":"42:5","kind":"loop_back"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"41:5"},{"src":"@entry","dst":"42:5"},{"src":"42:5","dst":"43:7"},{"src":"42:5","dst":"45:5"},{"src":"43:7","dst":"42:5"}],"ddg":[{"src":"@entry","dst":"42:5","var":"this.users","prov":["reaching-defs"]},{"src":"41:5","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"41:5","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"42:5","dst":"43:7","var":"u.recordLogin","prov":["reaching-defs"]},{"src":"43:7","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"43:7","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"43:7/actual_out","dst":"43:7","var":"$ret","prov":["reaching-defs"]},{"src":"45:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"startId","id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[164,187]},"id":"can://slim/typescript/src/services.ts/makeGuestName@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@exit"},"@formal_in:0":{"kind":"formal_in","of":"seed","id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/makeGuestName@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"@entry","dst":"5:3","var":"seed","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"5:3","var":"seed","prov":["reaching-defs"]},{"src":"5:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"},"@entry":{"kind":"entry","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@entry"},"13:3":{"kind":"statement","span":{"start":[13,3],"end":[13,27],"bytes":[400,424]},"id":"can://slim/typescript/src/services.ts/announce@13:3"},"@exit":{"kind":"exit","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@exit"},"@formal_in:0":{"kind":"formal_in","of":"thing","id":"can://slim/typescript/src/services.ts/announce@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/announce@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"13:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]},{"src":"13:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@entry"},"17:46":{"kind":"statement","span":{"start":[17,46],"end":[17,51],"bytes":[550,555]},"id":"can://slim/typescript/src/services.ts/nextId@17:46"},"@exit":{"kind":"exit","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@exit"},"@formal_in:0":{"kind":"formal_in","of":"n","id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/nextId@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"17:46","kind":"fallthrough"},{"src":"17:46","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"17:46"}],"ddg":[{"src":"@entry","dst":"17:46","var":"n","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"17:46","var":"n","prov":["reaching-defs"]},{"src":"17:46","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"},"@entry":{"kind":"entry","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@entry"},"15:7":{"kind":"statement","span":{"start":[15,7],"end":[15,19],"bytes":[456,468]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@15:7"},"@exit":{"kind":"exit","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@exit"},"@formal_in:0":{"kind":"formal_in","of":"part","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_out"},"14:7/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"14:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_in:0"},"14:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"14:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"14:7","kind":"fallthrough"},{"src":"14:7","dst":"@exit","kind":"exception"},{"src":"14:7","dst":"15:7","kind":"fallthrough"},{"src":"15:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"14:7"},{"src":"14:7","dst":"15:7"}],"ddg":[{"src":"@entry","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@entry","dst":"14:7","var":"this.parts.push","prov":["reaching-defs"]},{"src":"@entry","dst":"15:7","var":"this","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"14:7/actual_in:0","var":"part","prov":["reaching-defs"]},{"src":"14:7/actual_out","dst":"14:7","var":"$ret","prov":["reaching-defs"]},{"src":"15:7","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"14:7/actual_in:0","dst":"14:7/actual_out"}]},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"},"@entry":{"kind":"entry","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@entry"},"18:7":{"kind":"statement","span":{"start":[18,7],"end":[18,35],"bytes":[503,531]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7"},"@exit":{"kind":"exit","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@formal_out"},"18:7/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"18:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7/actual_in:0"},"18:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"18:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"18:7","kind":"fallthrough"},{"src":"18:7","dst":"@exit","kind":"exception"},{"src":"18:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"18:7"}],"ddg":[{"src":"@entry","dst":"18:7","var":"this.parts.join","prov":["reaching-defs"]},{"src":"18:7","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"18:7/actual_in:0","dst":"18:7/actual_out"}]},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"},"@entry":{"kind":"entry","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@entry"},"4:5":{"kind":"statement","span":{"start":[4,5],"end":[4,30],"bytes":[197,222]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5"},"@exit":{"kind":"exit","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@exit"},"@formal_in:0":{"kind":"formal_in","of":"s","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"n","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_out"},"4:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"4:5","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_in:0"},"4:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"4:5","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"4:5","kind":"fallthrough"},{"src":"4:5","dst":"@exit","kind":"exception"},{"src":"4:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"4:5"}],"ddg":[{"src":"@entry","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@entry","dst":"4:5","var":"s","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"4:5","var":"s","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"4:5/actual_in:0","var":"n","prov":["reaching-defs"]},{"src":"4:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"4:5/actual_out","dst":"4:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"4:5/actual_in:0","dst":"4:5/actual_out"}]},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"},"@entry":{"kind":"entry","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@entry"},"8:5":{"kind":"statement","span":{"start":[8,5],"end":[8,49],"bytes":[276,320]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5"},"@exit":{"kind":"exit","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@exit"},"@formal_in:0":{"kind":"formal_in","of":"s","id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out"},"8:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_in:0"},"8:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_out"},"8:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_in:1"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:5","kind":"fallthrough"},{"src":"8:5","dst":"@exit","kind":"exception"},{"src":"8:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:5"}],"ddg":[{"src":"@entry","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]},{"src":"8:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"8:5/actual_in:0","dst":"8:5/actual_out"},{"src":"8:5/actual_in:1","dst":"8:5/actual_out"}]}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"},"@entry":{"kind":"entry","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@entry"},"25:3":{"kind":"statement","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify@25:3"},"28:3":{"kind":"statement","span":{"start":[28,3],"end":[28,39],"bytes":[803,839]},"id":"can://slim/typescript/src/util.ts/classify@28:3"},"29:3":{"kind":"statement","span":{"start":[29,3],"end":[32,4],"bytes":[842,932]},"id":"can://slim/typescript/src/util.ts/classify@29:3"},"30:5":{"kind":"statement","span":{"start":[30,5],"end":[30,27],"bytes":[874,896]},"id":"can://slim/typescript/src/util.ts/classify@30:5"},"33:3":{"kind":"statement","span":{"start":[33,3],"end":[33,14],"bytes":[935,946]},"id":"can://slim/typescript/src/util.ts/classify@33:3"},"@exit":{"kind":"exit","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@exit"},"@formal_in:0":{"kind":"formal_in","of":"items","id":"can://slim/typescript/src/util.ts/classify@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/classify@formal_out"},"30:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"30:5","id":"can://slim/typescript/src/util.ts/classify@30:5/actual_in:0"},"30:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"30:5","id":"can://slim/typescript/src/util.ts/classify@30:5/actual_out"},"31:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"31:5","id":"can://slim/typescript/src/util.ts/classify@31:5/actual_in:0"},"31:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"31:5","id":"can://slim/typescript/src/util.ts/classify@31:5/actual_out"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"},"@entry":{"kind":"entry","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,32],"bytes":[769,796]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5"},"@exit":{"kind":"exit","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@exit"},"@formal_in:0":{"kind":"formal_in","of":"item","id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_out"},"26:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"26:5","id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5/actual_in:0"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]},{"src":"26:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"26:5/actual_in:0","dst":"26:5/actual_out"}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:3","kind":"fallthrough"},{"src":"25:3","dst":"@exit","kind":"exception"},{"src":"25:3","dst":"28:3","kind":"fallthrough"},{"src":"28:3","dst":"29:3","kind":"fallthrough"},{"src":"29:3","dst":"30:5","kind":"true"},{"src":"29:3","dst":"33:3","kind":"false"},{"src":"30:5","dst":"@exit","kind":"exception"},{"src":"30:5","dst":"31:5","kind":"fallthrough"},{"src":"31:5","dst":"@exit","kind":"exception"},{"src":"31:5","dst":"29:3","kind":"loop_back"},{"src":"33:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:3"},{"src":"25:3","dst":"28:3"},{"src":"25:3","dst":"29:3"},{"src":"29:3","dst":"30:5"},{"src":"29:3","dst":"33:3"},{"src":"30:5","dst":"31:5"},{"src":"31:5","dst":"29:3"}],"ddg":[{"src":"@entry","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"28:3","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"28:3","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5/actual_in:0","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"31:5","var":"item","prov":["reaching-defs"]},{"src":"30:5","dst":"31:5","var":"k","prov":["reaching-defs"]},{"src":"30:5/actual_out","dst":"30:5","var":"$ret","prov":["reaching-defs"]},{"src":"31:5","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"31:5","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"33:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"30:5/actual_in:0","dst":"30:5/actual_out"},{"src":"31:5/actual_in:0","dst":"31:5/actual_out"}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[{"src":"can://slim/typescript/src/controllers.ts/UserController/show@20:5","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@11:3/actual_in:0","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0","var":"service"},{"src":"can://slim/typescript/src/index.ts/main@13:3","dst":"can://slim/typescript/src/controllers.ts/UserController/show@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/index.ts/main@13:3/actual_in:0","dst":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/announce@formal_in:0","var":"thing"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:1","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:2","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2","var":"role"},{"src":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0","dst":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/announce@formal_in:0","var":"thing"},{"src":"can://slim/typescript/src/index.ts/main@19:3/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0","var":"s"},{"src":"can://slim/typescript/src/index.ts/main@19:3/actual_in:1","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1","var":"n"},{"src":"can://slim/typescript/src/index.ts/main@21:3/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0","var":"part"},{"src":"can://slim/typescript/src/index.ts/main@7:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0","var":"startId"},{"src":"can://slim/typescript/src/index.ts/main@8:3","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/index.ts/main@8:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@8:3/actual_in:1","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1","var":"role"},{"src":"can://slim/typescript/src/index.ts/main@9:3","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_in:0","dst":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/nextId@formal_in:0","var":"n"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:0","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:1","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1","var":"name"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:2","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2","var":"role"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0","var":"seed"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:1","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1","var":"role"},{"src":"can://slim/typescript/src/util.ts/classify@30:5/actual_in:0","dst":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0","var":"item"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0","var":"s"},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0","var":"s"}],"param_out":[{"src":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@11:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/controllers.ts/UserController/list@formal_out","dst":"can://slim/typescript/src/index.ts/main@12:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/controllers.ts/UserController/show@formal_out","dst":"can://slim/typescript/src/index.ts/main@13:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/Entity/constructor@formal_out","dst":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/Robot/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@17:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@16:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/constructor@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/describe@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/show@21:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/describe@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/recordLogin@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/announce@formal_out","dst":"can://slim/typescript/src/index.ts/main@16:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/announce@formal_out","dst":"can://slim/typescript/src/index.ts/main@17:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/makeGuestName@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/nextId@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@7:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/index.ts/main@8:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@formal_out","dst":"can://slim/typescript/src/index.ts/main@9:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/list@26:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/classify/keyOf@formal_out","dst":"can://slim/typescript/src/util.ts/classify@30:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_out","dst":"can://slim/typescript/src/index.ts/main@21:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@formal_out","dst":"can://slim/typescript/src/index.ts/main@21:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_out","dst":"can://slim/typescript/src/index.ts/main@19:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_out","var":"$ret"}],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file +{"schema_version":"2.0.0","language":"typescript","max_level":4,"k_limit":3,"analyzer":{"name":"codeanalyzer-typescript","version":"1.6.0"},"application":{"id":"can://slim","kind":"application","symbol_table":{"src/controllers.ts":{"id":"can://slim/typescript/src/controllers.ts","kind":"module","span":{"start":[1,1],"end":[29,1],"bytes":[0,699]},"source":"import { UserService } from \"./services\";\n\n// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.\nfunction Controller(prefix: string): ClassDecorator {\n return () => undefined;\n}\nfunction Get(path: string): MethodDecorator {\n return () => undefined;\n}\nfunction Param(name: string): ParameterDecorator {\n return () => undefined;\n}\n\n@Controller(\"/users\")\nexport class UserController {\n constructor(private readonly service: UserService) {}\n\n @Get(\"/:id\")\n show(@Param(\"id\") id: string): string {\n const user = this.service.create(id);\n return user.describe();\n }\n\n @Get(\"/\")\n list(): string[] {\n return this.service.describeAll();\n }\n}\n","imports":[{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":42,"resolved_module":"src/services.ts"}],"exports":[],"comments":[{"content":"// Minimal decorator factories (NestJS/Angular-flavored) to exercise structured TSDecorator capture.","is_docstring":false,"start_line":3,"end_line":3,"start_column":1,"end_column":101}],"types":{"UserController":{"id":"can://slim/typescript/src/controllers.ts/UserController","kind":"class","span":{"start":[14,1],"end":[28,2],"bytes":[380,698]},"name":"UserController","signature":"src/controllers.UserController","comments":[],"decorators":[{"name":"Controller","positional_arguments":["\"/users\""],"keyword_arguments":{},"start_line":14,"end_line":14,"start_column":1,"end_column":22}],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"show":{"id":"can://slim/typescript/src/controllers.ts/UserController/show","kind":"method","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"name":"show","signature":"src/controllers.UserController.show","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/:id\""],"keyword_arguments":{},"start_line":18,"end_line":18,"start_column":3,"end_column":15}],"parameters":[{"name":"id","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[{"name":"Param","positional_arguments":["\"id\""],"keyword_arguments":{},"start_line":19,"end_line":19,"start_column":8,"end_column":20}],"start_line":19,"end_line":19,"start_column":8,"end_column":31,"id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"20:18":{"kind":"call","span":{"start":[20,18],"end":[20,41],"bytes":[563,586]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this.service","receiver_type":"UserService","argument_types":["string"],"type_arguments":[],"return_type":"import(\"./models\").User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:18"},"21:12":{"kind":"call","span":{"start":[21,12],"end":[21,27],"bytes":[599,614]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"user","receiver_type":"import(\"./models\").User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:12"},"19:9":{"kind":"call","span":{"start":[19,9],"end":[19,20],"bytes":[512,523]},"callee":"can://slim/typescript/src/controllers.ts/Param","method_name":"Param","argument_types":["\"id\""],"type_arguments":[],"return_type":"ParameterDecorator","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/show@19:9"},"@entry":{"kind":"entry","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@entry"},"20:5":{"kind":"statement","span":{"start":[20,5],"end":[20,42],"bytes":[550,587]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5"},"21:5":{"kind":"statement","span":{"start":[21,5],"end":[21,28],"bytes":[592,615]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5"},"@exit":{"kind":"exit","span":{"start":[18,3],"end":[22,4],"bytes":[491,619]},"id":"can://slim/typescript/src/controllers.ts/UserController/show@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/show@formal_out"},"20:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"20:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_in:0"},"20:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"20:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_out"},"21:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"21:5","id":"can://slim/typescript/src/controllers.ts/UserController/show@21:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"20:5","kind":"fallthrough"},{"src":"20:5","dst":"@exit","kind":"exception"},{"src":"20:5","dst":"21:5","kind":"fallthrough"},{"src":"21:5","dst":"@exit","kind":"exception"},{"src":"21:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"20:5"},{"src":"20:5","dst":"21:5"}],"ddg":[{"src":"@entry","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"20:5","var":"this.service.create","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"20:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"20:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"20:5","dst":"21:5","var":"user.describe","prov":["reaching-defs"]},{"src":"20:5/actual_out","dst":"20:5","var":"$ret","prov":["reaching-defs"]},{"src":"21:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"21:5/actual_out","dst":"21:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"20:5","dst":"20:5","var":"src/services.nextId"},{"src":"20:5/actual_in:0","dst":"20:5/actual_out"}]},"list":{"id":"can://slim/typescript/src/controllers.ts/UserController/list","kind":"method","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"name":"list","signature":"src/controllers.UserController.list","comments":[],"decorators":[{"name":"Get","positional_arguments":["\"/\""],"keyword_arguments":{},"start_line":24,"end_line":24,"start_column":3,"end_column":12}],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,38],"bytes":[665,691]},"callee":"can://slim/typescript/src/services.ts/UserService/describeAll","method_name":"describeAll","receiver_expr":"this.service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:12"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,39],"bytes":[658,692]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[27,4],"bytes":[623,696]},"id":"can://slim/typescript/src/controllers.ts/UserController/list@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/list@formal_out"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/controllers.ts/UserController/list@26:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"this.service.describeAll","prov":["reaching-defs"]},{"src":"26:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"26:5/actual_out","dst":"26:5","var":"$ret","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/controllers.ts/UserController/constructor","kind":"constructor","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"name":"constructor","signature":"src/controllers.UserController.constructor","comments":[],"decorators":[],"parameters":[{"name":"service","type":"UserService","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":16,"end_line":16,"start_column":15,"end_column":52,"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[16,3],"end":[16,56],"bytes":[434,487]},"id":"can://slim/typescript/src/controllers.ts/UserController/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"service","id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"service":{"id":"can://slim/typescript/src/controllers.ts/UserController/service","kind":"field","name":"service","type":"UserService","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"Controller":{"id":"can://slim/typescript/src/controllers.ts/Controller","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"name":"Controller","signature":"src/controllers.Controller","comments":[],"decorators":[],"parameters":[{"name":"prefix","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":21,"end_column":35,"id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"}],"type_parameters":[],"return_type":"ClassDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[200,223]},"id":"can://slim/typescript/src/controllers.ts/Controller@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[144,225]},"id":"can://slim/typescript/src/controllers.ts/Controller@exit"},"@formal_in:0":{"kind":"formal_in","of":"prefix","id":"can://slim/typescript/src/controllers.ts/Controller@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Controller@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"arrow","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"name":"(anonymous)","signature":"src/controllers.Controller.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@entry"},"5:16":{"kind":"statement","span":{"start":[5,16],"end":[5,25],"bytes":[213,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@5:16"},"@exit":{"kind":"exit","span":{"start":[5,10],"end":[5,25],"bytes":[207,222]},"id":"can://slim/typescript/src/controllers.ts/Controller/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Controller/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:16","kind":"fallthrough"},{"src":"5:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:16"}],"ddg":[{"src":"5:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"5:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"Get":{"id":"can://slim/typescript/src/controllers.ts/Get","kind":"function","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"name":"Get","signature":"src/controllers.Get","comments":[],"decorators":[],"parameters":[{"name":"path","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":14,"end_column":26,"id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"}],"type_parameters":[],"return_type":"MethodDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@entry"},"8:3":{"kind":"statement","span":{"start":[8,3],"end":[8,26],"bytes":[274,297]},"id":"can://slim/typescript/src/controllers.ts/Get@8:3"},"@exit":{"kind":"exit","span":{"start":[7,1],"end":[9,2],"bytes":[226,299]},"id":"can://slim/typescript/src/controllers.ts/Get@exit"},"@formal_in:0":{"kind":"formal_in","of":"path","id":"can://slim/typescript/src/controllers.ts/Get@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Get@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"arrow","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"name":"(anonymous)","signature":"src/controllers.Get.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@entry"},"8:16":{"kind":"statement","span":{"start":[8,16],"end":[8,25],"bytes":[287,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@8:16"},"@exit":{"kind":"exit","span":{"start":[8,10],"end":[8,25],"bytes":[281,296]},"id":"can://slim/typescript/src/controllers.ts/Get/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Get/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:16","kind":"fallthrough"},{"src":"8:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:16"}],"ddg":[{"src":"8:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:3"}],"ddg":[{"src":"8:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"Param":{"id":"can://slim/typescript/src/controllers.ts/Param","kind":"function","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"name":"Param","signature":"src/controllers.Param","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":10,"end_line":10,"start_column":16,"end_column":28,"id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"}],"type_parameters":[],"return_type":"ParameterDecorator","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@entry"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,26],"bytes":[353,376]},"id":"can://slim/typescript/src/controllers.ts/Param@11:3"},"@exit":{"kind":"exit","span":{"start":[10,1],"end":[12,2],"bytes":[300,378]},"id":"can://slim/typescript/src/controllers.ts/Param@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/controllers.ts/Param@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Param@formal_out"}},"callables":{"":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"arrow","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"name":"(anonymous)","signature":"src/controllers.Param.","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"undefined","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@entry"},"11:16":{"kind":"statement","span":{"start":[11,16],"end":[11,25],"bytes":[366,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@11:16"},"@exit":{"kind":"exit","span":{"start":[11,10],"end":[11,25],"bytes":[360,375]},"id":"can://slim/typescript/src/controllers.ts/Param/@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/controllers.ts/Param/@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:16","kind":"fallthrough"},{"src":"11:16","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:16"}],"ddg":[{"src":"11:16","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"11:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"11:3"}],"ddg":[{"src":"11:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d42b8f615d51575e3436409b9fce70862182b6071da40471b4be9b95f7c9ee4c"},"src/index.ts":{"id":"can://slim/typescript/src/index.ts","kind":"module","span":{"start":[1,1],"end":[26,1],"bytes":[0,742]},"source":"import { UserController } from \"./controllers\";\nimport { Robot, Role, User } from \"./models\";\nimport { UserService, announce } from \"./services\";\nimport { StringUtil } from \"./util\";\n\nexport function main(): void {\n const service = new UserService(100);\n service.create(\"Ada\", Role.Admin);\n service.createGuest();\n\n const controller = new UserController(service);\n controller.list();\n controller.show(\"42\");\n\n // interface-typed dispatch — RTA should expand announce -> {User,Robot}.describe\n announce(new User(1, \"Ada\", Role.Admin));\n announce(new Robot(\"r2d2\"));\n\n const slug = StringUtil.repeat(\"hello world\", 2);\n const builder = new StringUtil.Builder();\n builder.add(\"a\").add(\"b\").build();\n console.log(slug);\n}\n\nmain();\n","imports":[{"module":"./controllers","name":"UserController","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":48,"resolved_module":"src/controllers.ts"},{"module":"./models","name":"Robot","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":2,"end_line":2,"start_column":1,"end_column":46,"resolved_module":"src/models.ts"},{"module":"./services","name":"UserService","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./services","name":"announce","is_type_only":false,"import_kind":"named","start_line":3,"end_line":3,"start_column":1,"end_column":52,"resolved_module":"src/services.ts"},{"module":"./util","name":"StringUtil","is_type_only":false,"import_kind":"named","start_line":4,"end_line":4,"start_column":1,"end_column":37,"resolved_module":"src/util.ts"}],"exports":[],"comments":[],"types":{},"functions":{"main":{"id":"can://slim/typescript/src/index.ts/main","kind":"function","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"name":"main","signature":"src/index.main","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"void","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"7:19":{"kind":"call","span":{"start":[7,19],"end":[7,39],"bytes":[233,253]},"callee":"can://slim/typescript/src/services.ts/UserService/constructor","method_name":"UserService","argument_types":["100"],"type_arguments":[],"return_type":"UserService","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@7:19"},"8:3":{"kind":"call","span":{"start":[8,3],"end":[8,36],"bytes":[257,290]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"service","receiver_type":"UserService","argument_types":["\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@8:3"},"9:3":{"kind":"call","span":{"start":[9,3],"end":[9,24],"bytes":[294,315]},"callee":"can://slim/typescript/src/services.ts/UserService/createGuest","method_name":"createGuest","receiver_expr":"service","receiver_type":"UserService","argument_types":[],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@9:3"},"11:22":{"kind":"call","span":{"start":[11,22],"end":[11,49],"bytes":[339,366]},"callee":"can://slim/typescript/src/controllers.ts/UserController/constructor","method_name":"UserController","argument_types":["UserService"],"type_arguments":[],"return_type":"UserController","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@11:22"},"12:3":{"kind":"call","span":{"start":[12,3],"end":[12,20],"bytes":[370,387]},"callee":"can://slim/typescript/src/controllers.ts/UserController/list","method_name":"list","receiver_expr":"controller","receiver_type":"UserController","argument_types":[],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@12:3"},"13:3":{"kind":"call","span":{"start":[13,3],"end":[13,24],"bytes":[391,412]},"callee":"can://slim/typescript/src/controllers.ts/UserController/show","method_name":"show","receiver_expr":"controller","receiver_type":"UserController","argument_types":["\"42\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@13:3"},"16:3":{"kind":"call","span":{"start":[16,3],"end":[16,43],"bytes":[503,543]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["User"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:3"},"16:12":{"kind":"call","span":{"start":[16,12],"end":[16,42],"bytes":[512,542]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["1","\"Ada\"","Role.Admin"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@16:12"},"17:3":{"kind":"call","span":{"start":[17,3],"end":[17,30],"bytes":[547,574]},"callee":"can://slim/typescript/src/services.ts/announce","method_name":"announce","argument_types":["Robot"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:3"},"17:12":{"kind":"call","span":{"start":[17,12],"end":[17,29],"bytes":[556,573]},"callee":"can://slim/typescript/src/models.ts/Robot/constructor","method_name":"Robot","argument_types":["\"r2d2\""],"type_arguments":[],"return_type":"Robot","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@17:12"},"19:16":{"kind":"call","span":{"start":[19,16],"end":[19,51],"bytes":[592,627]},"callee":"can://slim/typescript/src/util.ts/StringUtil/repeat","method_name":"repeat","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":["\"hello world\"","2"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@19:16"},"20:19":{"kind":"call","span":{"start":[20,19],"end":[20,43],"bytes":[647,671]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","method_name":"Builder","receiver_expr":"StringUtil","receiver_type":"typeof StringUtil","argument_types":[],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@20:19"},"21:3":{"kind":"call","span":{"start":[21,3],"end":[21,36],"bytes":[675,708]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","method_name":"build","receiver_expr":"builder.add(\"a\").add(\"b\")","receiver_type":"StringUtil.Builder","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3"},"21:3/2":{"kind":"call","span":{"start":[21,3],"end":[21,28],"bytes":[675,700]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder.add(\"a\")","receiver_type":"StringUtil.Builder","argument_types":["\"b\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/2"},"21:3/3":{"kind":"call","span":{"start":[21,3],"end":[21,19],"bytes":[675,691]},"callee":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","method_name":"add","receiver_expr":"builder","receiver_type":"StringUtil.Builder","argument_types":["\"a\""],"type_arguments":[],"return_type":"StringUtil.Builder","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@21:3/3"},"22:3":{"kind":"call","span":{"start":[22,3],"end":[22,20],"bytes":[712,729]},"callee":"can://slim/@external/(builtin)/log","method_name":"log","receiver_expr":"console","receiver_type":"Console","argument_types":["string"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/index.ts/main@22:3"},"@entry":{"kind":"entry","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@entry"},"7:3":{"kind":"statement","span":{"start":[7,3],"end":[7,40],"bytes":[217,254]},"id":"can://slim/typescript/src/index.ts/main@7:3"},"11:3":{"kind":"statement","span":{"start":[11,3],"end":[11,50],"bytes":[320,367]},"id":"can://slim/typescript/src/index.ts/main@11:3"},"19:3":{"kind":"statement","span":{"start":[19,3],"end":[19,52],"bytes":[579,628]},"id":"can://slim/typescript/src/index.ts/main@19:3"},"20:3":{"kind":"statement","span":{"start":[20,3],"end":[20,44],"bytes":[631,672]},"id":"can://slim/typescript/src/index.ts/main@20:3"},"@exit":{"kind":"exit","span":{"start":[6,1],"end":[23,2],"bytes":[184,732]},"id":"can://slim/typescript/src/index.ts/main@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/index.ts/main@formal_out"},"11:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"11:3","id":"can://slim/typescript/src/index.ts/main@11:3/actual_out"},"12:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"12:3","id":"can://slim/typescript/src/index.ts/main@12:3/actual_out"},"13:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"13:3","id":"can://slim/typescript/src/index.ts/main@13:3/actual_out"},"7:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"7:3","id":"can://slim/typescript/src/index.ts/main@7:3/actual_in:0"},"8:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_in:0"},"8:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_out"},"8:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"8:3","id":"can://slim/typescript/src/index.ts/main@8:3/actual_in:1"},"11:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"11:3","id":"can://slim/typescript/src/index.ts/main@11:3/actual_in:0"},"13:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"13:3","id":"can://slim/typescript/src/index.ts/main@13:3/actual_in:0"},"16:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0"},"16:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_out"},"16:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:1"},"16:3/actual_in:2":{"kind":"actual_in","of":"arg2","parent":"16:3","id":"can://slim/typescript/src/index.ts/main@16:3/actual_in:2"},"17:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"17:3","id":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0"},"17:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"17:3","id":"can://slim/typescript/src/index.ts/main@17:3/actual_out"},"19:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_in:0"},"19:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_out"},"19:3/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"19:3","id":"can://slim/typescript/src/index.ts/main@19:3/actual_in:1"},"21:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"21:3","id":"can://slim/typescript/src/index.ts/main@21:3/actual_in:0"},"22:3/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"22:3","id":"can://slim/typescript/src/index.ts/main@22:3/actual_in:0"},"22:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"22:3","id":"can://slim/typescript/src/index.ts/main@22:3/actual_out"},"7:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"7:3","id":"can://slim/typescript/src/index.ts/main@7:3/actual_out"},"9:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"9:3","id":"can://slim/typescript/src/index.ts/main@9:3/actual_out"},"21:3/actual_out":{"kind":"actual_out","of":"$ret","parent":"21:3","id":"can://slim/typescript/src/index.ts/main@21:3/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"7:3","kind":"fallthrough"},{"src":"11:3","dst":"@exit","kind":"exception"},{"src":"11:3","dst":"12:3","kind":"fallthrough"},{"src":"12:3","dst":"@exit","kind":"exception"},{"src":"12:3","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"16:3","kind":"fallthrough"},{"src":"16:3","dst":"@exit","kind":"exception"},{"src":"16:3","dst":"17:3","kind":"fallthrough"},{"src":"17:3","dst":"@exit","kind":"exception"},{"src":"17:3","dst":"19:3","kind":"fallthrough"},{"src":"19:3","dst":"@exit","kind":"exception"},{"src":"19:3","dst":"20:3","kind":"fallthrough"},{"src":"20:3","dst":"@exit","kind":"exception"},{"src":"20:3","dst":"21:3","kind":"fallthrough"},{"src":"21:3","dst":"@exit","kind":"exception"},{"src":"21:3","dst":"22:3","kind":"fallthrough"},{"src":"22:3","dst":"@exit","kind":"exception"},{"src":"22:3","dst":"@exit","kind":"fallthrough"},{"src":"7:3","dst":"@exit","kind":"exception"},{"src":"7:3","dst":"8:3","kind":"fallthrough"},{"src":"8:3","dst":"@exit","kind":"exception"},{"src":"8:3","dst":"9:3","kind":"fallthrough"},{"src":"9:3","dst":"@exit","kind":"exception"},{"src":"9:3","dst":"11:3","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"7:3"},{"src":"11:3","dst":"12:3"},{"src":"12:3","dst":"13:3"},{"src":"13:3","dst":"16:3"},{"src":"16:3","dst":"17:3"},{"src":"17:3","dst":"19:3"},{"src":"19:3","dst":"20:3"},{"src":"20:3","dst":"21:3"},{"src":"21:3","dst":"22:3"},{"src":"7:3","dst":"8:3"},{"src":"8:3","dst":"9:3"},{"src":"9:3","dst":"11:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"8:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"9:3","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"11:3","dst":"12:3","var":"controller.list","prov":["reaching-defs"]},{"src":"11:3","dst":"13:3","var":"controller.show","prov":["reaching-defs"]},{"src":"11:3/actual_out","dst":"11:3","var":"$ret","prov":["reaching-defs"]},{"src":"12:3/actual_out","dst":"12:3","var":"$ret","prov":["reaching-defs"]},{"src":"13:3/actual_out","dst":"13:3","var":"$ret","prov":["reaching-defs"]},{"src":"16:3/actual_out","dst":"16:3","var":"$ret","prov":["reaching-defs"]},{"src":"17:3/actual_out","dst":"17:3","var":"$ret","prov":["reaching-defs"]},{"src":"19:3","dst":"22:3","var":"slug","prov":["reaching-defs"]},{"src":"19:3/actual_out","dst":"19:3","var":"$ret","prov":["reaching-defs"]},{"src":"20:3","dst":"21:3","var":"builder.add","prov":["reaching-defs"]},{"src":"21:3/actual_out","dst":"21:3","var":"$ret","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"11:3/actual_in:0","var":"service","prov":["reaching-defs"]},{"src":"7:3","dst":"8:3","var":"service.create","prov":["reaching-defs"]},{"src":"7:3","dst":"9:3","var":"service.createGuest","prov":["reaching-defs"]},{"src":"7:3/actual_out","dst":"7:3","var":"$ret","prov":["reaching-defs"]},{"src":"8:3/actual_out","dst":"8:3","var":"$ret","prov":["reaching-defs"]},{"src":"9:3/actual_out","dst":"9:3","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"13:3","dst":"13:3","var":"src/services.nextId"},{"src":"13:3/actual_in:0","dst":"13:3/actual_out"},{"src":"16:3/actual_in:0","dst":"16:3/actual_out"},{"src":"17:3/actual_in:0","dst":"17:3/actual_out"},{"src":"19:3/actual_in:0","dst":"19:3/actual_out"},{"src":"19:3/actual_in:1","dst":"19:3/actual_out"},{"src":"22:3/actual_in:0","dst":"22:3/actual_out"},{"src":"8:3","dst":"8:3","var":"src/services.nextId"},{"src":"8:3/actual_in:0","dst":"8:3/actual_out"},{"src":"8:3/actual_in:1","dst":"8:3/actual_out"},{"src":"9:3","dst":"9:3","var":"src/services.nextId"}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"6de6f6ff5a01a5c7c750a93d5e10bae7b15817f386421f45c7527cfb7259d9b3"},"src/models.ts":{"id":"can://slim/typescript/src/models.ts","kind":"module","span":{"start":[1,1],"end":[65,1],"bytes":[0,1237]},"source":"/** Domain models for the sample app. */\n\nexport interface Identifiable {\n readonly id: T;\n}\n\nexport interface Named {\n name: string;\n describe(): string;\n}\n\nexport type UserId = string | number;\n\nexport enum Role {\n Admin = \"admin\",\n Member = \"member\",\n Guest = \"guest\",\n}\n\nexport const enum Flag {\n None = 0,\n Active = 1,\n}\n\n/** A user of the system. */\nexport abstract class Entity implements Identifiable {\n constructor(public readonly id: ID) {}\n abstract describe(): string;\n}\n\nexport class User extends Entity implements Named {\n private loginCount = 0;\n static instances = 0;\n\n constructor(\n id: UserId,\n public name: string,\n private role: Role = Role.Member,\n ) {\n super(id);\n User.instances++;\n }\n\n get isAdmin(): boolean {\n return this.role === Role.Admin;\n }\n\n describe(): string {\n return `${this.name} (${this.role})`;\n }\n\n async recordLogin(): Promise {\n this.loginCount += 1;\n return this.loginCount;\n }\n}\n\n/** A second, unrelated implementer of Named — drives RTA subtype expansion. */\nexport class Robot implements Named {\n constructor(public name: string) {}\n describe(): string {\n return `robot:${this.name}`;\n }\n}\n","imports":[],"exports":[],"comments":[{"content":"/** Domain models for the sample app. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41},{"content":"/** A user of the system. */","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29},{"content":"/** A second, unrelated implementer of Named — drives RTA subtype expansion. */","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"types":{"Entity":{"id":"can://slim/typescript/src/models.ts/Entity","kind":"class","span":{"start":[26,1],"end":[29,2],"bytes":[376,521]},"name":"Entity","signature":"src/models.Entity","comments":[{"content":"A user of the system.","is_docstring":true,"start_line":25,"end_line":25,"start_column":1,"end_column":29}],"decorators":[],"base_classes":["src/models.Identifiable"],"implements_types":["src/models.Identifiable"],"type_parameters":[{"name":"ID","default":"string"}],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Entity/describe","kind":"method","span":{"start":[28,3],"end":[28,31],"bytes":[491,519]},"name":"describe","signature":"src/models.Entity.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":true,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[{"parameters":[],"return_type":"string","type_parameters":[],"start_line":28,"end_line":28}],"body":{},"entrypoints":[],"is_entrypoint":false},"constructor":{"id":"can://slim/typescript/src/models.ts/Entity/constructor","kind":"constructor","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"name":"constructor","signature":"src/models.Entity.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"ID","is_optional":false,"is_rest":false,"is_readonly":true,"accessibility":"public","decorators":[],"start_line":27,"end_line":27,"start_column":15,"end_column":37,"id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[27,3],"end":[27,41],"bytes":[450,488]},"id":"can://slim/typescript/src/models.ts/Entity/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Entity/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Entity/id","kind":"field","name":"id","type":"ID","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"is_abstract":true,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Identifiable"],"entrypoints":[],"is_entrypoint":false},"User":{"id":"can://slim/typescript/src/models.ts/User","kind":"class","span":{"start":[31,1],"end":[56,2],"bytes":[523,1015]},"name":"User","signature":"src/models.User","comments":[],"decorators":[],"base_classes":["src/models.Entity","src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/User/describe","kind":"method","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"name":"describe","signature":"src/models.User.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@entry"},"49:5":{"kind":"statement","span":{"start":[49,5],"end":[49,42],"bytes":[872,909]},"id":"can://slim/typescript/src/models.ts/User/describe@49:5"},"@exit":{"kind":"exit","span":{"start":[48,3],"end":[50,4],"bytes":[847,913]},"id":"can://slim/typescript/src/models.ts/User/describe@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/describe@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"49:5","kind":"fallthrough"},{"src":"49:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"49:5"}],"ddg":[{"src":"@entry","dst":"49:5","var":"this.name","prov":["reaching-defs"]},{"src":"@entry","dst":"49:5","var":"this.role","prov":["reaching-defs"]},{"src":"49:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"recordLogin":{"id":"can://slim/typescript/src/models.ts/User/recordLogin","kind":"method","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"name":"recordLogin","signature":"src/models.User.recordLogin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@entry"},"53:5":{"kind":"statement","span":{"start":[53,5],"end":[53,26],"bytes":[960,981]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@53:5"},"54:5":{"kind":"statement","span":{"start":[54,5],"end":[54,28],"bytes":[986,1009]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@54:5"},"@exit":{"kind":"exit","span":{"start":[52,3],"end":[55,4],"bytes":[917,1013]},"id":"can://slim/typescript/src/models.ts/User/recordLogin@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/recordLogin@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"53:5","kind":"fallthrough"},{"src":"53:5","dst":"54:5","kind":"fallthrough"},{"src":"54:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"53:5"},{"src":"@entry","dst":"54:5"}],"ddg":[{"src":"@entry","dst":"53:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"@entry","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"53:5","dst":"54:5","var":"this.loginCount","prov":["reaching-defs"]},{"src":"54:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/models.ts/User/constructor","kind":"constructor","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"name":"constructor","signature":"src/models.User.constructor","comments":[],"decorators":[],"parameters":[{"name":"id","type":"UserId","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":36,"end_line":36,"start_column":5,"end_column":15,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":37,"end_line":37,"start_column":5,"end_column":24,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"accessibility":"private","decorators":[],"start_line":38,"end_line":38,"start_column":5,"end_column":37,"id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"40:5":{"kind":"call","span":{"start":[40,5],"end":[40,14],"bytes":[738,747]},"callee":"can://slim/typescript/src/models.ts/Entity/constructor","method_name":"super","argument_types":["UserId"],"type_arguments":[],"return_type":"void","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/models.ts/User/constructor@40:5"},"@entry":{"kind":"entry","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,22],"bytes":[753,770]},"id":"can://slim/typescript/src/models.ts/User/constructor@41:5"},"@exit":{"kind":"exit","span":{"start":[35,3],"end":[42,4],"bytes":[636,774]},"id":"can://slim/typescript/src/models.ts/User/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"id","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1"},"@formal_in:2":{"kind":"formal_in","of":"role","id":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/constructor@formal_out"},"40:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"40:5","id":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_out"},"40:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"40:5","id":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_in:0"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"40:5","kind":"fallthrough"},{"src":"40:5","dst":"@exit","kind":"exception"},{"src":"40:5","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"@exit","kind":"fallthrough"}],"cdg":[{"src":"@entry","dst":"40:5"},{"src":"40:5","dst":"41:5"}],"ddg":[{"src":"@entry","dst":"40:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"40:5","var":"id","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"40:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"40:5/actual_out","dst":"40:5","var":"$ret","prov":["reaching-defs"]}],"summary":[]},"isAdmin#get":{"id":"can://slim/typescript/src/models.ts/User/isAdmin","kind":"getter","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"name":"isAdmin","signature":"src/models.User.isAdmin","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"boolean","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"accessor_kind":"getter","overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@entry"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,37],"bytes":[807,839]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@45:5"},"@exit":{"kind":"exit","span":{"start":[44,3],"end":[46,4],"bytes":[778,843]},"id":"can://slim/typescript/src/models.ts/User/isAdmin@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/User/isAdmin@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"45:5","kind":"fallthrough"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"45:5"}],"ddg":[{"src":"@entry","dst":"45:5","var":"this.role","prov":["reaching-defs"]},{"src":"45:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{"loginCount":{"id":"can://slim/typescript/src/models.ts/User/loginCount","kind":"field","span":{"start":[32,3],"end":[32,26],"bytes":[585,608]},"name":"loginCount","type":"number","comments":[],"decorators":[],"initializer":"0","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"instances":{"id":"can://slim/typescript/src/models.ts/User/instances","kind":"field","span":{"start":[33,3],"end":[33,24],"bytes":[611,632]},"name":"instances","type":"number","comments":[],"decorators":[],"initializer":"0","is_static":true,"is_readonly":false,"is_optional":false,"is_abstract":false},"name":{"id":"can://slim/typescript/src/models.ts/User/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"role":{"id":"can://slim/typescript/src/models.ts/User/role","kind":"field","name":"role","type":"Role","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":false,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"extends_ids":["can://slim/typescript/src/models.ts/Entity"],"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Robot":{"id":"can://slim/typescript/src/models.ts/Robot","kind":"class","span":{"start":[59,1],"end":[64,2],"bytes":[1099,1236]},"name":"Robot","signature":"src/models.Robot","comments":[{"content":"A second, unrelated implementer of Named — drives RTA subtype expansion.","is_docstring":true,"start_line":58,"end_line":58,"start_column":1,"end_column":80}],"decorators":[],"base_classes":["src/models.Named"],"implements_types":["src/models.Named"],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Robot/describe","kind":"method","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"name":"describe","signature":"src/models.Robot.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@entry"},"62:5":{"kind":"statement","span":{"start":[62,5],"end":[62,33],"bytes":[1202,1230]},"id":"can://slim/typescript/src/models.ts/Robot/describe@62:5"},"@exit":{"kind":"exit","span":{"start":[61,3],"end":[63,4],"bytes":[1177,1234]},"id":"can://slim/typescript/src/models.ts/Robot/describe@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Robot/describe@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"62:5","kind":"fallthrough"},{"src":"62:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"62:5"}],"ddg":[{"src":"@entry","dst":"62:5","var":"this.name","prov":["reaching-defs"]},{"src":"62:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/models.ts/Robot/constructor","kind":"constructor","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"name":"constructor","signature":"src/models.Robot.constructor","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"accessibility":"public","decorators":[],"start_line":60,"end_line":60,"start_column":15,"end_column":34,"id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[60,3],"end":[60,38],"bytes":[1139,1174]},"id":"can://slim/typescript/src/models.ts/Robot/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/models.ts/Robot/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Robot/name","kind":"field","name":"name","type":"string","comments":[],"decorators":[],"accessibility":"public","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"implements_ids":["can://slim/typescript/src/models.ts/Named"],"entrypoints":[],"is_entrypoint":false},"Identifiable":{"id":"can://slim/typescript/src/models.ts/Identifiable","kind":"interface","span":{"start":[3,1],"end":[5,2],"bytes":[42,105]},"name":"Identifiable","signature":"src/models.Identifiable","comments":[{"content":"Domain models for the sample app.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":41}],"base_classes":[],"type_parameters":[{"name":"T","default":"string"}],"callables":{},"fields":{"id":{"id":"can://slim/typescript/src/models.ts/Identifiable/id","kind":"field","span":{"start":[4,3],"end":[4,18],"bytes":[88,103]},"name":"id","type":"T","comments":[],"decorators":[],"is_static":false,"is_readonly":true,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Named":{"id":"can://slim/typescript/src/models.ts/Named","kind":"interface","span":{"start":[7,1],"end":[10,2],"bytes":[107,171]},"name":"Named","signature":"src/models.Named","comments":[],"base_classes":[],"type_parameters":[],"callables":{"describe":{"id":"can://slim/typescript/src/models.ts/Named/describe","kind":"method","span":{"start":[9,3],"end":[9,22],"bytes":[150,169]},"name":"describe","signature":"src/models.Named.describe","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"name":{"id":"can://slim/typescript/src/models.ts/Named/name","kind":"field","span":{"start":[8,3],"end":[8,16],"bytes":[134,147]},"name":"name","type":"string","comments":[],"decorators":[],"is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"call_signatures":[],"index_signatures":[],"is_exported":true,"is_ambient":false},"Role":{"id":"can://slim/typescript/src/models.ts/Role","kind":"enum","span":{"start":[14,1],"end":[18,2],"bytes":[212,291]},"name":"Role","signature":"src/models.Role","comments":[],"fields":{"Admin":{"id":"can://slim/typescript/src/models.ts/Role/Admin","kind":"field","span":{"start":[15,3],"end":[15,18],"bytes":[233,248]},"name":"Admin","value":"admin"},"Member":{"id":"can://slim/typescript/src/models.ts/Role/Member","kind":"field","span":{"start":[16,3],"end":[16,20],"bytes":[252,269]},"name":"Member","value":"member"},"Guest":{"id":"can://slim/typescript/src/models.ts/Role/Guest","kind":"field","span":{"start":[17,3],"end":[17,18],"bytes":[273,288]},"name":"Guest","value":"guest"}},"is_const":false,"is_exported":true,"is_ambient":false},"Flag":{"id":"can://slim/typescript/src/models.ts/Flag","kind":"enum","span":{"start":[20,1],"end":[23,2],"bytes":[293,345]},"name":"Flag","signature":"src/models.Flag","comments":[],"fields":{"None":{"id":"can://slim/typescript/src/models.ts/Flag/None","kind":"field","span":{"start":[21,3],"end":[21,11],"bytes":[320,328]},"name":"None","value":"0"},"Active":{"id":"can://slim/typescript/src/models.ts/Flag/Active","kind":"field","span":{"start":[22,3],"end":[22,13],"bytes":[332,342]},"name":"Active","value":"1"}},"is_const":true,"is_exported":true,"is_ambient":false},"UserId":{"id":"can://slim/typescript/src/models.ts/UserId","kind":"type_alias","span":{"start":[12,1],"end":[12,38],"bytes":[173,210]},"name":"UserId","signature":"src/models.UserId","comments":[],"aliased_type":"string | number","type_parameters":[],"is_exported":true,"is_ambient":false}},"functions":{},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"d39ff571ccfda4b7c46923586b6b94d0e818a51be966f1ba40305650fd0ffc91"},"src/services.ts":{"id":"can://slim/typescript/src/services.ts","kind":"module","span":{"start":[1,1],"end":[48,1],"bytes":[0,1240]},"source":"import { type Named, Role, User, type UserId } from \"./models\";\n\n/** Pure helper — top-level function. */\nexport function makeGuestName(seed: number): string {\n return `guest-${seed}`;\n}\n\n/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */\nexport function announce(thing: Named): string {\n return thing.describe();\n}\n\n/** Arrow function bound to a const (function_expression-style callable). */\nexport const nextId = (n: number): UserId => n + 1;\n\nexport class UserService {\n private users: User[] = [];\n\n constructor(private readonly startId: number = 0) {}\n\n create(name: string, role: Role = Role.Member): User {\n const id = nextId(this.users.length + this.startId);\n const user = new User(id, name, role);\n this.users.push(user);\n return user;\n }\n\n createGuest(): User {\n const name = makeGuestName(this.users.length);\n return this.create(name, Role.Guest);\n }\n\n describeAll(): string[] {\n return this.users.map((u) => u.describe());\n }\n\n async loginAll(): Promise {\n let total = 0;\n for (const u of this.users) {\n total += await u.recordLogin();\n }\n return total;\n }\n}\n","imports":[{"module":"./models","name":"Named","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"Role","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"User","is_type_only":false,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"},{"module":"./models","name":"UserId","is_type_only":true,"import_kind":"named","start_line":1,"end_line":1,"start_column":1,"end_column":64,"resolved_module":"src/models.ts"}],"exports":[],"comments":[{"content":"/** Pure helper — top-level function. */","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41},{"content":"/**\n * Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\n * concrete implementer of Named (User, Robot, ...).\n */","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4},{"content":"/** Arrow function bound to a const (function_expression-style callable). */","is_docstring":true,"start_line":16,"end_line":16,"start_column":1,"end_column":77}],"types":{"UserService":{"id":"can://slim/typescript/src/services.ts/UserService","kind":"class","span":{"start":[19,1],"end":[47,2],"bytes":[558,1239]},"name":"UserService","signature":"src/services.UserService","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"create":{"id":"can://slim/typescript/src/services.ts/UserService/create","kind":"method","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"name":"create","signature":"src/services.UserService.create","comments":[],"decorators":[],"parameters":[{"name":"name","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":10,"end_column":22,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},{"name":"role","type":"Role","default_value":"Role.Member","is_optional":true,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":24,"end_column":48,"id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"}],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"25:16":{"kind":"call","span":{"start":[25,16],"end":[25,56],"bytes":[744,784]},"callee":"can://slim/typescript/src/services.ts/nextId","method_name":"nextId","argument_types":["number"],"type_arguments":[],"return_type":"UserId","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@25:16"},"26:18":{"kind":"call","span":{"start":[26,18],"end":[26,42],"bytes":[803,827]},"callee":"can://slim/typescript/src/models.ts/User/constructor","method_name":"User","argument_types":["UserId","string","Role"],"type_arguments":[],"return_type":"User","is_constructor_call":true,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@26:18"},"27:5":{"kind":"call","span":{"start":[27,5],"end":[27,26],"bytes":[833,854]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["User"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/create@27:5"},"@entry":{"kind":"entry","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@entry"},"25:5":{"kind":"statement","span":{"start":[25,5],"end":[25,57],"bytes":[733,785]},"id":"can://slim/typescript/src/services.ts/UserService/create@25:5"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,43],"bytes":[790,828]},"id":"can://slim/typescript/src/services.ts/UserService/create@26:5"},"28:5":{"kind":"statement","span":{"start":[28,5],"end":[28,17],"bytes":[860,872]},"id":"can://slim/typescript/src/services.ts/UserService/create@28:5"},"@exit":{"kind":"exit","span":{"start":[24,3],"end":[29,4],"bytes":[674,876]},"id":"can://slim/typescript/src/services.ts/UserService/create@exit"},"@formal_in:0":{"kind":"formal_in","of":"name","id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"role","id":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/create@formal_out"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_out"},"25:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"25:5","id":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_out"},"25:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"25:5","id":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_in:0"},"26:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:0"},"26:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:1"},"26:5/actual_in:2":{"kind":"actual_in","of":"arg2","parent":"26:5","id":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:2"},"27:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"27:5","id":"can://slim/typescript/src/services.ts/UserService/create@27:5/actual_in:0"},"27:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"27:5","id":"can://slim/typescript/src/services.ts/UserService/create@27:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:5","kind":"fallthrough"},{"src":"25:5","dst":"@exit","kind":"exception"},{"src":"25:5","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"27:5","kind":"fallthrough"},{"src":"27:5","dst":"@exit","kind":"exception"},{"src":"27:5","dst":"28:5","kind":"fallthrough"},{"src":"28:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:5"},{"src":"25:5","dst":"26:5"},{"src":"26:5","dst":"27:5"},{"src":"27:5","dst":"28:5"}],"ddg":[{"src":"@entry","dst":"25:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5/actual_in:0","var":"this.startId","prov":["reaching-defs"]},{"src":"@entry","dst":"25:5/actual_in:0","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@entry","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@entry","dst":"27:5","var":"this.users.push","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5","var":"name","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5/actual_in:1","var":"name","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"26:5","var":"role","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"26:5/actual_in:2","var":"role","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5","var":"id","prov":["reaching-defs"]},{"src":"25:5","dst":"26:5/actual_in:0","var":"id","prov":["reaching-defs"]},{"src":"25:5/actual_out","dst":"25:5","var":"$ret","prov":["reaching-defs"]},{"src":"26:5","dst":"27:5","var":"user","prov":["reaching-defs"]},{"src":"26:5","dst":"28:5","var":"user","prov":["reaching-defs"]},{"src":"26:5/actual_out","dst":"26:5","var":"$ret","prov":["reaching-defs"]},{"src":"28:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"25:5/actual_in:0","dst":"25:5/actual_out"},{"src":"27:5/actual_in:0","dst":"27:5/actual_out"}]},"createGuest":{"id":"can://slim/typescript/src/services.ts/UserService/createGuest","kind":"method","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"name":"createGuest","signature":"src/services.UserService.createGuest","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"User","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"32:18":{"kind":"call","span":{"start":[32,18],"end":[32,50],"bytes":[919,951]},"callee":"can://slim/typescript/src/services.ts/makeGuestName","method_name":"makeGuestName","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:18"},"33:12":{"kind":"call","span":{"start":[33,12],"end":[33,41],"bytes":[964,993]},"callee":"can://slim/typescript/src/services.ts/UserService/create","method_name":"create","receiver_expr":"this","receiver_type":"this","argument_types":["string","Role.Guest"],"type_arguments":[],"return_type":"User","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:12"},"@entry":{"kind":"entry","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@entry"},"32:5":{"kind":"statement","span":{"start":[32,5],"end":[32,51],"bytes":[906,952]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5"},"33:5":{"kind":"statement","span":{"start":[33,5],"end":[33,42],"bytes":[957,994]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5"},"@exit":{"kind":"exit","span":{"start":[31,3],"end":[34,4],"bytes":[880,998]},"id":"can://slim/typescript/src/services.ts/UserService/createGuest@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/createGuest@formal_out"},"32:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"32:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_out"},"33:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_out"},"32:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"32:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_in:0"},"33:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:0"},"33:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"33:5","id":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:1"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"32:5","kind":"fallthrough"},{"src":"32:5","dst":"@exit","kind":"exception"},{"src":"32:5","dst":"33:5","kind":"fallthrough"},{"src":"33:5","dst":"@exit","kind":"exception"},{"src":"33:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"32:5"},{"src":"32:5","dst":"33:5"}],"ddg":[{"src":"@entry","dst":"32:5","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"32:5/actual_in:0","var":"this.users.length","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"src/services.nextId","prov":["reaching-defs"]},{"src":"@entry","dst":"33:5","var":"this.create","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5","var":"name","prov":["reaching-defs"]},{"src":"32:5","dst":"33:5/actual_in:0","var":"name","prov":["reaching-defs"]},{"src":"32:5/actual_out","dst":"32:5","var":"$ret","prov":["reaching-defs"]},{"src":"33:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"33:5/actual_out","dst":"33:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"32:5/actual_in:0","dst":"32:5/actual_out"},{"src":"33:5","dst":"33:5","var":"src/services.nextId"},{"src":"33:5/actual_in:0","dst":"33:5/actual_out"},{"src":"33:5/actual_in:1","dst":"33:5/actual_out"}]},"describeAll":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll","kind":"method","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"name":"describeAll","signature":"src/services.UserService.describeAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string[]","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:12":{"kind":"call","span":{"start":[37,12],"end":[37,47],"bytes":[1039,1074]},"callee":"can://slim/@external/(builtin)/map","method_name":"map","receiver_expr":"this.users","receiver_type":"User[]","argument_types":["(u: User) => string"],"type_arguments":[],"return_type":"string[]","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:12"},"@entry":{"kind":"entry","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@entry"},"37:5":{"kind":"statement","span":{"start":[37,5],"end":[37,48],"bytes":[1032,1075]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5"},"@exit":{"kind":"exit","span":{"start":[36,3],"end":[38,4],"bytes":[1002,1079]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/describeAll@formal_out"},"37:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"37:5","id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5/actual_in:0"},"37:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"37:5","id":"can://slim/typescript/src/services.ts/UserService/describeAll@37:5/actual_out"}},"callables":{"":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"arrow","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"name":"(anonymous)","signature":"src/services.UserService.describeAll.","comments":[],"decorators":[],"parameters":[{"name":"u","type":"User","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":37,"end_line":37,"start_column":28,"end_column":29,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"37:34":{"kind":"call","span":{"start":[37,34],"end":[37,46],"bytes":[1061,1073]},"callee":"can://slim/typescript/src/models.ts/User/describe","method_name":"describe","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34"},"@entry":{"kind":"entry","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@entry"},"@exit":{"kind":"exit","span":{"start":[37,27],"end":[37,46],"bytes":[1054,1073]},"id":"can://slim/typescript/src/services.ts/UserService/describeAll/@exit"},"@formal_in:0":{"kind":"formal_in","of":"u","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@formal_out"},"37:34/actual_out":{"kind":"actual_out","of":"$ret","parent":"37:34","id":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:34","kind":"fallthrough"},{"src":"37:34","dst":"@exit","kind":"exception"},{"src":"37:34","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:34"}],"ddg":[{"src":"@entry","dst":"37:34","var":"u.describe","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"37:34","var":"u.describe","prov":["reaching-defs"]},{"src":"37:34","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"37:34/actual_out","dst":"37:34","var":"$ret","prov":["reaching-defs"]}],"summary":[]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"37:5","kind":"fallthrough"},{"src":"37:5","dst":"@exit","kind":"exception"},{"src":"37:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"37:5"}],"ddg":[{"src":"@entry","dst":"37:5","var":"this.users.map","prov":["reaching-defs"]},{"src":"37:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"37:5/actual_in:0","dst":"37:5/actual_out"}]},"loginAll":{"id":"can://slim/typescript/src/services.ts/UserService/loginAll","kind":"method","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"name":"loginAll","signature":"src/services.UserService.loginAll","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"Promise","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":true,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"43:22":{"kind":"call","span":{"start":[43,22],"end":[43,37],"bytes":[1193,1208]},"callee":"can://slim/typescript/src/models.ts/User/recordLogin","method_name":"recordLogin","receiver_expr":"u","receiver_type":"User","argument_types":[],"type_arguments":[],"return_type":"Promise","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:22"},"@entry":{"kind":"entry","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@entry"},"41:5":{"kind":"statement","span":{"start":[41,5],"end":[41,19],"bytes":[1123,1137]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@41:5"},"42:5":{"kind":"statement","span":{"start":[42,5],"end":[44,6],"bytes":[1142,1215]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@42:5"},"43:7":{"kind":"statement","span":{"start":[43,7],"end":[43,38],"bytes":[1178,1209]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7"},"45:5":{"kind":"statement","span":{"start":[45,5],"end":[45,18],"bytes":[1220,1233]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@45:5"},"@exit":{"kind":"exit","span":{"start":[40,3],"end":[46,4],"bytes":[1083,1237]},"id":"can://slim/typescript/src/services.ts/UserService/loginAll@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/loginAll@formal_out"},"43:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"43:7","id":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"41:5","kind":"fallthrough"},{"src":"41:5","dst":"42:5","kind":"fallthrough"},{"src":"42:5","dst":"43:7","kind":"true"},{"src":"42:5","dst":"45:5","kind":"false"},{"src":"43:7","dst":"@exit","kind":"exception"},{"src":"43:7","dst":"42:5","kind":"loop_back"},{"src":"45:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"41:5"},{"src":"@entry","dst":"42:5"},{"src":"42:5","dst":"43:7"},{"src":"42:5","dst":"45:5"},{"src":"43:7","dst":"42:5"}],"ddg":[{"src":"@entry","dst":"42:5","var":"this.users","prov":["reaching-defs"]},{"src":"41:5","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"41:5","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"42:5","dst":"43:7","var":"u.recordLogin","prov":["reaching-defs"]},{"src":"43:7","dst":"43:7","var":"total","prov":["reaching-defs"]},{"src":"43:7","dst":"45:5","var":"total","prov":["reaching-defs"]},{"src":"43:7/actual_out","dst":"43:7","var":"$ret","prov":["reaching-defs"]},{"src":"45:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"constructor":{"id":"can://slim/typescript/src/services.ts/UserService/constructor","kind":"constructor","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"name":"constructor","signature":"src/services.UserService.constructor","comments":[],"decorators":[],"parameters":[{"name":"startId","type":"number","default_value":"0","is_optional":true,"is_rest":false,"is_readonly":true,"accessibility":"private","decorators":[],"start_line":22,"end_line":22,"start_column":15,"end_column":51,"id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"}],"type_parameters":[],"cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@entry"},"@exit":{"kind":"exit","span":{"start":[22,3],"end":[22,55],"bytes":[618,670]},"id":"can://slim/typescript/src/services.ts/UserService/constructor@exit"},"@formal_in:0":{"kind":"formal_in","of":"startId","id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/UserService/constructor@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"@exit","kind":"fallthrough"}],"cdg":[],"ddg":[],"summary":[]}},"fields":{"users":{"id":"can://slim/typescript/src/services.ts/UserService/users","kind":"field","span":{"start":[20,3],"end":[20,30],"bytes":[587,614]},"name":"users","type":"User[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false},"startId":{"id":"can://slim/typescript/src/services.ts/UserService/startId","kind":"field","name":"startId","type":"number","comments":[],"decorators":[],"accessibility":"private","is_static":false,"is_readonly":true,"is_optional":true,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"makeGuestName":{"id":"can://slim/typescript/src/services.ts/makeGuestName","kind":"function","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"name":"makeGuestName","signature":"src/services.makeGuestName","comments":[{"content":"Pure helper — top-level function.","is_docstring":true,"start_line":3,"end_line":3,"start_column":1,"end_column":41}],"decorators":[],"parameters":[{"name":"seed","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":4,"end_line":4,"start_column":31,"end_column":43,"id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@entry"},"5:3":{"kind":"statement","span":{"start":[5,3],"end":[5,26],"bytes":[164,187]},"id":"can://slim/typescript/src/services.ts/makeGuestName@5:3"},"@exit":{"kind":"exit","span":{"start":[4,1],"end":[6,2],"bytes":[108,189]},"id":"can://slim/typescript/src/services.ts/makeGuestName@exit"},"@formal_in:0":{"kind":"formal_in","of":"seed","id":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/makeGuestName@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"5:3","kind":"fallthrough"},{"src":"5:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"5:3"}],"ddg":[{"src":"@entry","dst":"5:3","var":"seed","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"5:3","var":"seed","prov":["reaching-defs"]},{"src":"5:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"announce":{"id":"can://slim/typescript/src/services.ts/announce","kind":"function","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"name":"announce","signature":"src/services.announce","comments":[{"content":"Calls describe() on an interface-typed receiver. Under RTA this expands to every instantiated\nconcrete implementer of Named (User, Robot, ...).","is_docstring":true,"start_line":8,"end_line":11,"start_column":1,"end_column":4}],"decorators":[],"parameters":[{"name":"thing","type":"Named","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":12,"end_line":12,"start_column":26,"end_column":38,"id":"can://slim/typescript/src/services.ts/announce@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"13:10":{"kind":"call","span":{"start":[13,10],"end":[13,26],"bytes":[407,423]},"callee":"can://slim/typescript/src/models.ts/Named/describe","method_name":"describe","receiver_expr":"thing","receiver_type":"Named","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/services.ts/announce@13:10"},"@entry":{"kind":"entry","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@entry"},"13:3":{"kind":"statement","span":{"start":[13,3],"end":[13,27],"bytes":[400,424]},"id":"can://slim/typescript/src/services.ts/announce@13:3"},"@exit":{"kind":"exit","span":{"start":[12,1],"end":[14,2],"bytes":[349,426]},"id":"can://slim/typescript/src/services.ts/announce@exit"},"@formal_in:0":{"kind":"formal_in","of":"thing","id":"can://slim/typescript/src/services.ts/announce@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/announce@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"13:3","kind":"fallthrough"},{"src":"13:3","dst":"@exit","kind":"exception"},{"src":"13:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"13:3"}],"ddg":[{"src":"@entry","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"13:3","var":"thing.describe","prov":["reaching-defs"]},{"src":"13:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]},"nextId":{"id":"can://slim/typescript/src/services.ts/nextId","kind":"arrow","span":{"start":[17,14],"end":[17,51],"bytes":[518,555]},"name":"nextId","signature":"src/services.nextId","comments":[],"decorators":[],"parameters":[{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":17,"end_line":17,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"}],"type_parameters":[],"return_type":"UserId","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"@entry":{"kind":"entry","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@entry"},"17:46":{"kind":"statement","span":{"start":[17,46],"end":[17,51],"bytes":[550,555]},"id":"can://slim/typescript/src/services.ts/nextId@17:46"},"@exit":{"kind":"exit","span":{"start":[17,23],"end":[17,51],"bytes":[527,555]},"id":"can://slim/typescript/src/services.ts/nextId@exit"},"@formal_in:0":{"kind":"formal_in","of":"n","id":"can://slim/typescript/src/services.ts/nextId@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/services.ts/nextId@formal_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"17:46","kind":"fallthrough"},{"src":"17:46","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"17:46"}],"ddg":[{"src":"@entry","dst":"17:46","var":"n","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"17:46","var":"n","prov":["reaching-defs"]},{"src":"17:46","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"1bda3666dab48f8e686fb8ffc2143f2e422af62be46698053cfeea4184b55617"},"src/util.ts":{"id":"can://slim/typescript/src/util.ts","kind":"module","span":{"start":[1,1],"end":[35,1],"bytes":[0,949]},"source":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */\nexport namespace StringUtil {\n export function repeat(s: string, n: number): string {\n return slug(s).repeat(n);\n }\n\n export function slug(s: string): string {\n return s.toLowerCase().replace(/\\s+/g, \"-\");\n }\n\n export class Builder {\n private parts: string[] = [];\n add(part: string): this {\n this.parts.push(slug(part));\n return this;\n }\n build(): string {\n return this.parts.join(\"/\");\n }\n }\n}\n\n/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */\nexport function classify(items: T[]): Record {\n function keyOf(item: T): string {\n return item.name.charAt(0);\n }\n const out: Record = {};\n for (const item of items) {\n const k = keyOf(item);\n (out[k] ??= []).push(item);\n }\n return out;\n}\n","imports":[],"exports":[],"comments":[{"content":"/** A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures. */","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106},{"content":"/** Generic top-level function with a nested helper, to exercise inner_callables + generics. */","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"types":{"StringUtil":{"id":"can://slim/typescript/src/util.ts/StringUtil","kind":"namespace","span":{"start":[2,1],"end":[21,2],"bytes":[106,543]},"name":"StringUtil","signature":"src/util.StringUtil","comments":[{"content":"A namespace with nested declarations, to exercise the namespaces{} collection + nested signatures.","is_docstring":true,"start_line":1,"end_line":1,"start_column":1,"end_column":106}],"types":{"Builder":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder","kind":"class","span":{"start":[11,3],"end":[20,4],"bytes":[328,541]},"name":"Builder","signature":"src/util.StringUtil.Builder","comments":[],"decorators":[],"base_classes":[],"implements_types":[],"type_parameters":[],"callables":{"add":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","kind":"method","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"name":"add","signature":"src/util.StringUtil.Builder.add","comments":[],"decorators":[],"parameters":[{"name":"part","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":13,"end_line":13,"start_column":9,"end_column":21,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"}],"type_parameters":[],"return_type":"this","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"14:7":{"kind":"call","span":{"start":[14,7],"end":[14,34],"bytes":[421,448]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["string"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7"},"14:23":{"kind":"call","span":{"start":[14,23],"end":[14,33],"bytes":[437,447]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:23"},"@entry":{"kind":"entry","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@entry"},"15:7":{"kind":"statement","span":{"start":[15,7],"end":[15,19],"bytes":[456,468]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@15:7"},"@exit":{"kind":"exit","span":{"start":[13,5],"end":[16,6],"bytes":[389,474]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@exit"},"@formal_in:0":{"kind":"formal_in","of":"part","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_out"},"14:7/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"14:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_in:0"},"14:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"14:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"14:7","kind":"fallthrough"},{"src":"14:7","dst":"@exit","kind":"exception"},{"src":"14:7","dst":"15:7","kind":"fallthrough"},{"src":"15:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"14:7"},{"src":"14:7","dst":"15:7"}],"ddg":[{"src":"@entry","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@entry","dst":"14:7","var":"this.parts.push","prov":["reaching-defs"]},{"src":"@entry","dst":"15:7","var":"this","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"14:7","var":"part","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"14:7/actual_in:0","var":"part","prov":["reaching-defs"]},{"src":"14:7/actual_out","dst":"14:7","var":"$ret","prov":["reaching-defs"]},{"src":"15:7","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"14:7/actual_in:0","dst":"14:7/actual_out"}]},"build":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","kind":"method","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"name":"build","signature":"src/util.StringUtil.Builder.build","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"18:14":{"kind":"call","span":{"start":[18,14],"end":[18,34],"bytes":[510,530]},"callee":"can://slim/@external/(builtin)/join","method_name":"join","receiver_expr":"this.parts","receiver_type":"string[]","argument_types":["\"/\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:14"},"@entry":{"kind":"entry","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@entry"},"18:7":{"kind":"statement","span":{"start":[18,7],"end":[18,35],"bytes":[503,531]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7"},"@exit":{"kind":"exit","span":{"start":[17,5],"end":[19,6],"bytes":[479,537]},"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@exit"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@formal_out"},"18:7/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"18:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7/actual_in:0"},"18:7/actual_out":{"kind":"actual_out","of":"$ret","parent":"18:7","id":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@18:7/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"18:7","kind":"fallthrough"},{"src":"18:7","dst":"@exit","kind":"exception"},{"src":"18:7","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"18:7"}],"ddg":[{"src":"@entry","dst":"18:7","var":"this.parts.join","prov":["reaching-defs"]},{"src":"18:7","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"18:7/actual_in:0","dst":"18:7/actual_out"}]},"constructor":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","kind":"constructor","span":{"start":[0,0],"end":[0,0],"bytes":[0,0]},"name":"constructor","signature":"src/util.StringUtil.Builder.constructor","comments":[],"decorators":[],"parameters":[],"type_parameters":[],"cyclomatic_complexity":0,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":true,"overload_signatures":[],"body":{},"entrypoints":[],"is_entrypoint":false}},"fields":{"parts":{"id":"can://slim/typescript/src/util.ts/StringUtil/Builder/parts","kind":"field","span":{"start":[12,5],"end":[12,34],"bytes":[355,384]},"name":"parts","type":"string[]","comments":[],"decorators":[],"initializer":"[]","accessibility":"private","is_static":false,"is_readonly":false,"is_optional":false,"is_abstract":false}},"is_abstract":false,"is_exported":true,"is_ambient":false,"entrypoints":[],"is_entrypoint":false}},"functions":{"repeat":{"id":"can://slim/typescript/src/util.ts/StringUtil/repeat","kind":"function","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"name":"repeat","signature":"src/util.StringUtil.repeat","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":26,"end_column":35,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},{"name":"n","type":"number","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":3,"end_line":3,"start_column":37,"end_column":46,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"4:12":{"kind":"call","span":{"start":[4,12],"end":[4,29],"bytes":[204,221]},"callee":"can://slim/@external/(builtin)/repeat","method_name":"repeat","receiver_expr":"slug(s)","receiver_type":"string","argument_types":["number"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12"},"4:12/2":{"kind":"call","span":{"start":[4,12],"end":[4,19],"bytes":[204,211]},"callee":"can://slim/typescript/src/util.ts/StringUtil/slug","method_name":"slug","argument_types":["string"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:12/2"},"@entry":{"kind":"entry","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@entry"},"4:5":{"kind":"statement","span":{"start":[4,5],"end":[4,30],"bytes":[197,222]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5"},"@exit":{"kind":"exit","span":{"start":[3,3],"end":[5,4],"bytes":[138,226]},"id":"can://slim/typescript/src/util.ts/StringUtil/repeat@exit"},"@formal_in:0":{"kind":"formal_in","of":"s","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0"},"@formal_in:1":{"kind":"formal_in","of":"n","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_out"},"4:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"4:5","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_in:0"},"4:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"4:5","id":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"4:5","kind":"fallthrough"},{"src":"4:5","dst":"@exit","kind":"exception"},{"src":"4:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"4:5"}],"ddg":[{"src":"@entry","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@entry","dst":"4:5","var":"s","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"4:5","var":"s","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"4:5","var":"n","prov":["reaching-defs"]},{"src":"@formal_in:1","dst":"4:5/actual_in:0","var":"n","prov":["reaching-defs"]},{"src":"4:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]},{"src":"4:5/actual_out","dst":"4:5","var":"$ret","prov":["reaching-defs"]}],"summary":[{"src":"4:5/actual_in:0","dst":"4:5/actual_out"}]},"slug":{"id":"can://slim/typescript/src/util.ts/StringUtil/slug","kind":"function","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"name":"slug","signature":"src/util.StringUtil.slug","comments":[],"decorators":[],"parameters":[{"name":"s","type":"string","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":7,"end_line":7,"start_column":24,"end_column":33,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"8:12":{"kind":"call","span":{"start":[8,12],"end":[8,48],"bytes":[283,319]},"callee":"can://slim/@external/(builtin)/replace","method_name":"replace","receiver_expr":"s.toLowerCase()","receiver_type":"string","argument_types":["RegExp","\"-\""],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12"},"8:12/2":{"kind":"call","span":{"start":[8,12],"end":[8,27],"bytes":[283,298]},"callee":"can://slim/@external/(builtin)/toLowerCase","method_name":"toLowerCase","receiver_expr":"s","receiver_type":"string","argument_types":[],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:12/2"},"@entry":{"kind":"entry","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@entry"},"8:5":{"kind":"statement","span":{"start":[8,5],"end":[8,49],"bytes":[276,320]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5"},"@exit":{"kind":"exit","span":{"start":[7,3],"end":[9,4],"bytes":[230,324]},"id":"can://slim/typescript/src/util.ts/StringUtil/slug@exit"},"@formal_in:0":{"kind":"formal_in","of":"s","id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out"},"8:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_in:0"},"8:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_out"},"8:5/actual_in:1":{"kind":"actual_in","of":"arg1","parent":"8:5","id":"can://slim/typescript/src/util.ts/StringUtil/slug@8:5/actual_in:1"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"8:5","kind":"fallthrough"},{"src":"8:5","dst":"@exit","kind":"exception"},{"src":"8:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"8:5"}],"ddg":[{"src":"@entry","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"8:5","var":"s.toLowerCase","prov":["reaching-defs"]},{"src":"8:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"8:5/actual_in:0","dst":"8:5/actual_out"},{"src":"8:5/actual_in:1","dst":"8:5/actual_out"}]}},"fields":{},"is_exported":true,"is_ambient":false}},"functions":{"classify":{"id":"can://slim/typescript/src/util.ts/classify","kind":"function","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"name":"classify","signature":"src/util.classify","comments":[{"content":"Generic top-level function with a nested helper, to exercise inner_callables + generics.","is_docstring":true,"start_line":23,"end_line":23,"start_column":1,"end_column":96}],"decorators":[],"parameters":[{"name":"items","type":"T[]","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":24,"end_line":24,"start_column":54,"end_column":64,"id":"can://slim/typescript/src/util.ts/classify@formal_in:0"}],"type_parameters":[{"name":"T","constraint":"{ name: string }"}],"return_type":"Record","cyclomatic_complexity":2,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":true,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"30:15":{"kind":"call","span":{"start":[30,15],"end":[30,26],"bytes":[884,895]},"callee":"can://slim/typescript/src/util.ts/classify/keyOf","method_name":"keyOf","argument_types":["T"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@30:15"},"31:5":{"kind":"call","span":{"start":[31,5],"end":[31,31],"bytes":[901,927]},"callee":"can://slim/@external/(builtin)/push","method_name":"push","receiver_expr":"(out[k] ??= [])","receiver_type":"T[]","argument_types":["T"],"type_arguments":[],"return_type":"number","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify@31:5"},"@entry":{"kind":"entry","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@entry"},"25:3":{"kind":"statement","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify@25:3"},"28:3":{"kind":"statement","span":{"start":[28,3],"end":[28,39],"bytes":[803,839]},"id":"can://slim/typescript/src/util.ts/classify@28:3"},"29:3":{"kind":"statement","span":{"start":[29,3],"end":[32,4],"bytes":[842,932]},"id":"can://slim/typescript/src/util.ts/classify@29:3"},"30:5":{"kind":"statement","span":{"start":[30,5],"end":[30,27],"bytes":[874,896]},"id":"can://slim/typescript/src/util.ts/classify@30:5"},"33:3":{"kind":"statement","span":{"start":[33,3],"end":[33,14],"bytes":[935,946]},"id":"can://slim/typescript/src/util.ts/classify@33:3"},"@exit":{"kind":"exit","span":{"start":[24,1],"end":[34,2],"bytes":[641,948]},"id":"can://slim/typescript/src/util.ts/classify@exit"},"@formal_in:0":{"kind":"formal_in","of":"items","id":"can://slim/typescript/src/util.ts/classify@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/classify@formal_out"},"30:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"30:5","id":"can://slim/typescript/src/util.ts/classify@30:5/actual_in:0"},"30:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"30:5","id":"can://slim/typescript/src/util.ts/classify@30:5/actual_out"},"31:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"31:5","id":"can://slim/typescript/src/util.ts/classify@31:5/actual_in:0"},"31:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"31:5","id":"can://slim/typescript/src/util.ts/classify@31:5/actual_out"}},"callables":{"keyOf":{"id":"can://slim/typescript/src/util.ts/classify/keyOf","kind":"function","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"name":"keyOf","signature":"src/util.classify.keyOf","comments":[],"decorators":[],"parameters":[{"name":"item","type":"T","is_optional":false,"is_rest":false,"is_readonly":false,"decorators":[],"start_line":25,"end_line":25,"start_column":18,"end_column":25,"id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"}],"type_parameters":[],"return_type":"string","cyclomatic_complexity":1,"is_static":false,"is_abstract":false,"is_async":false,"is_generator":false,"is_optional":false,"is_readonly":false,"is_exported":false,"is_ambient":false,"is_implicit":false,"overload_signatures":[],"body":{"26:12":{"kind":"call","span":{"start":[26,12],"end":[26,31],"bytes":[776,795]},"callee":"can://slim/@external/(builtin)/charAt","method_name":"charAt","receiver_expr":"item.name","receiver_type":"string","argument_types":["0"],"type_arguments":[],"return_type":"string","is_constructor_call":false,"is_optional_chain":false,"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:12"},"@entry":{"kind":"entry","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@entry"},"26:5":{"kind":"statement","span":{"start":[26,5],"end":[26,32],"bytes":[769,796]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5"},"@exit":{"kind":"exit","span":{"start":[25,3],"end":[27,4],"bytes":[731,800]},"id":"can://slim/typescript/src/util.ts/classify/keyOf@exit"},"@formal_in:0":{"kind":"formal_in","of":"item","id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0"},"@formal_out":{"kind":"formal_out","of":"$ret","id":"can://slim/typescript/src/util.ts/classify/keyOf@formal_out"},"26:5/actual_in:0":{"kind":"actual_in","of":"arg0","parent":"26:5","id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5/actual_in:0"},"26:5/actual_out":{"kind":"actual_out","of":"$ret","parent":"26:5","id":"can://slim/typescript/src/util.ts/classify/keyOf@26:5/actual_out"}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"26:5","kind":"fallthrough"},{"src":"26:5","dst":"@exit","kind":"exception"},{"src":"26:5","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"26:5"}],"ddg":[{"src":"@entry","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"26:5","var":"item.name.charAt","prov":["reaching-defs"]},{"src":"26:5","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"26:5/actual_in:0","dst":"26:5/actual_out"}]}},"entrypoints":[],"is_entrypoint":false,"cfg":[{"src":"@entry","dst":"25:3","kind":"fallthrough"},{"src":"25:3","dst":"@exit","kind":"exception"},{"src":"25:3","dst":"28:3","kind":"fallthrough"},{"src":"28:3","dst":"29:3","kind":"fallthrough"},{"src":"29:3","dst":"30:5","kind":"true"},{"src":"29:3","dst":"33:3","kind":"false"},{"src":"30:5","dst":"@exit","kind":"exception"},{"src":"30:5","dst":"31:5","kind":"fallthrough"},{"src":"31:5","dst":"@exit","kind":"exception"},{"src":"31:5","dst":"29:3","kind":"loop_back"},{"src":"33:3","dst":"@exit","kind":"return"}],"cdg":[{"src":"@entry","dst":"25:3"},{"src":"25:3","dst":"28:3"},{"src":"25:3","dst":"29:3"},{"src":"29:3","dst":"30:5"},{"src":"29:3","dst":"33:3"},{"src":"30:5","dst":"31:5"},{"src":"31:5","dst":"29:3"}],"ddg":[{"src":"@entry","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"@formal_in:0","dst":"29:3","var":"items","prov":["reaching-defs"]},{"src":"28:3","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"28:3","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"30:5/actual_in:0","var":"item","prov":["reaching-defs"]},{"src":"29:3","dst":"31:5","var":"item","prov":["reaching-defs"]},{"src":"30:5","dst":"31:5","var":"k","prov":["reaching-defs"]},{"src":"30:5/actual_out","dst":"30:5","var":"$ret","prov":["reaching-defs"]},{"src":"31:5","dst":"31:5","var":"out[*]","prov":["reaching-defs"]},{"src":"31:5","dst":"33:3","var":"out","prov":["reaching-defs"]},{"src":"33:3","dst":"@formal_out","var":"return","prov":["reaching-defs"]}],"summary":[{"src":"30:5/actual_in:0","dst":"30:5/actual_out"},{"src":"31:5/actual_in:0","dst":"31:5/actual_out"}]}},"fields":{},"is_tsx":false,"is_declaration_file":false,"content_hash":"54886cff7e11ccadc987571f508b2aef2f324b14e63d8ad52100499851d130fa"}},"call_graph":[{"src":"can://slim/typescript/src/controllers.ts","dst":"can://slim/typescript/src/controllers.ts/Controller","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/index.ts","dst":"can://slim/typescript/src/index.ts/main","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Param","prov":["tsc","defuse"],"weight":2},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/services.ts/UserService/describeAll","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/UserService/createGuest","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/list","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/controllers.ts/UserController/show","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/services.ts/announce","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/models.ts/Robot/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","prov":["tsc"],"weight":2},{"src":"can://slim/typescript/src/index.ts/main","dst":"can://slim/@external/(builtin)/log","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/models.ts/User/constructor","dst":"can://slim/typescript/src/models.ts/Entity/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Named/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/announce","dst":"can://slim/typescript/src/models.ts/Robot/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/services.ts/nextId","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/typescript/src/models.ts/User/constructor","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/create","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/makeGuestName","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest","dst":"can://slim/typescript/src/services.ts/UserService/create","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/@external/(builtin)/map","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll/","dst":"can://slim/typescript/src/models.ts/User/describe","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/loginAll","dst":"can://slim/typescript/src/models.ts/User/recordLogin","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/typescript/src/util.ts/classify/keyOf","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/classify/keyOf","dst":"can://slim/@external/(builtin)/charAt","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/@external/(builtin)/repeat","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/replace","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug","dst":"can://slim/@external/(builtin)/toLowerCase","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/@external/(builtin)/push","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add","dst":"can://slim/typescript/src/util.ts/StringUtil/slug","prov":["tsc"],"weight":1},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build","dst":"can://slim/@external/(builtin)/join","prov":["import"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/list","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/controllers.ts/UserController/show","dst":"can://slim/typescript/src/controllers.ts/Get","prov":["defuse"],"weight":1},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/","prov":["defuse"],"weight":1}],"param_in":[{"src":"can://slim/typescript/src/controllers.ts/UserController/show@20:5","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@11:3/actual_in:0","dst":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_in:0","var":"service"},{"src":"can://slim/typescript/src/index.ts/main@13:3","dst":"can://slim/typescript/src/controllers.ts/UserController/show@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/index.ts/main@13:3/actual_in:0","dst":"can://slim/typescript/src/controllers.ts/UserController/show@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/announce@formal_in:0","var":"thing"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:1","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@16:3/actual_in:2","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2","var":"role"},{"src":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0","dst":"can://slim/typescript/src/models.ts/Robot/constructor@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@17:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/announce@formal_in:0","var":"thing"},{"src":"can://slim/typescript/src/index.ts/main@19:3/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:0","var":"s"},{"src":"can://slim/typescript/src/index.ts/main@19:3/actual_in:1","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_in:1","var":"n"},{"src":"can://slim/typescript/src/index.ts/main@21:3/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_in:0","var":"part"},{"src":"can://slim/typescript/src/index.ts/main@7:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/constructor@formal_in:0","var":"startId"},{"src":"can://slim/typescript/src/index.ts/main@8:3","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/index.ts/main@8:3/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/index.ts/main@8:3/actual_in:1","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1","var":"role"},{"src":"can://slim/typescript/src/index.ts/main@9:3","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_in:0","dst":"can://slim/typescript/src/models.ts/Entity/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/nextId@formal_in:0","var":"n"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:0","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:0","var":"id"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:1","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:1","var":"name"},{"src":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_in:2","dst":"can://slim/typescript/src/models.ts/User/constructor@formal_in:2","var":"role"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/makeGuestName@formal_in:0","var":"seed"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5","dst":"can://slim/typescript/src/services.ts/UserService/create@entry","var":"src/services.nextId"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:0","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:0","var":"name"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_in:1","dst":"can://slim/typescript/src/services.ts/UserService/create@formal_in:1","var":"role"},{"src":"can://slim/typescript/src/util.ts/classify@30:5/actual_in:0","dst":"can://slim/typescript/src/util.ts/classify/keyOf@formal_in:0","var":"item"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0","var":"s"},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_in:0","dst":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_in:0","var":"s"}],"param_out":[{"src":"can://slim/typescript/src/controllers.ts/UserController/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@11:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/controllers.ts/UserController/list@formal_out","dst":"can://slim/typescript/src/index.ts/main@12:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/controllers.ts/UserController/show@formal_out","dst":"can://slim/typescript/src/index.ts/main@13:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/Entity/constructor@formal_out","dst":"can://slim/typescript/src/models.ts/User/constructor@40:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/Robot/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@17:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@16:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/constructor@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/create@26:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/describe@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/show@21:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/describe@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/describeAll/@37:34/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/models.ts/User/recordLogin@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/loginAll@43:7/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/announce@formal_out","dst":"can://slim/typescript/src/index.ts/main@16:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/announce@formal_out","dst":"can://slim/typescript/src/index.ts/main@17:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/makeGuestName@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@32:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/nextId@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/create@25:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/constructor@formal_out","dst":"can://slim/typescript/src/index.ts/main@7:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/show@20:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/index.ts/main@8:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/create@formal_out","dst":"can://slim/typescript/src/services.ts/UserService/createGuest@33:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/createGuest@formal_out","dst":"can://slim/typescript/src/index.ts/main@9:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/services.ts/UserService/describeAll@formal_out","dst":"can://slim/typescript/src/controllers.ts/UserController/list@26:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/classify/keyOf@formal_out","dst":"can://slim/typescript/src/util.ts/classify@30:5/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@formal_out","dst":"can://slim/typescript/src/index.ts/main@21:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/Builder/build@formal_out","dst":"can://slim/typescript/src/index.ts/main@21:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/repeat@formal_out","dst":"can://slim/typescript/src/index.ts/main@19:3/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out","dst":"can://slim/typescript/src/util.ts/StringUtil/Builder/add@14:7/actual_out","var":"$ret"},{"src":"can://slim/typescript/src/util.ts/StringUtil/slug@formal_out","dst":"can://slim/typescript/src/util.ts/StringUtil/repeat@4:5/actual_out","var":"$ret"}],"artifacts":{"package.json":{"id":"can://slim/artifact/package.json","kind":"artifact","path":"package.json","format":"json","roles":["dependency-manifest","tool-config"],"size_bytes":88,"sha256":"277f174033b3f17dcd3ba9a550b53289624f034606303cef18a3f84ab7156c67","source":"{\n \"name\": \"sample-app\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"private\": true\n}\n","extraction":"none","config_keys":[]},"tsconfig.json":{"id":"can://slim/artifact/tsconfig.json","kind":"artifact","path":"tsconfig.json","format":"json","roles":["tool-config"],"size_bytes":289,"sha256":"72f24fc616456ab556dd8e7c886264214cb344547b32b972eb476467af0a9cab","source":"{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"experimentalDecorators\": true,\n \"emitDecoratorMetadata\": true\n },\n \"include\": [\"src/**/*.ts\"]\n}\n","extraction":"full","config_keys":[{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.target","key":"compilerOptions.target","namespace":"json","value":"ES2022","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.module","key":"compilerOptions.module","namespace":"json","value":"ESNext","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.moduleResolution","key":"compilerOptions.moduleResolution","namespace":"json","value":"bundler","references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.strict","key":"compilerOptions.strict","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.esModuleInterop","key":"compilerOptions.esModuleInterop","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.skipLibCheck","key":"compilerOptions.skipLibCheck","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.experimentalDecorators","key":"compilerOptions.experimentalDecorators","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/compilerOptions.emitDecoratorMetadata","key":"compilerOptions.emitDecoratorMetadata","namespace":"json","value":true,"references":[]},{"id":"can://slim/artifact/tsconfig.json@key/include.0","key":"include.0","namespace":"json","value":"src/**/*.ts","references":[]}]}},"dependencies":[],"unresolved_imports":[],"config_uses":[],"config_reads":[],"entrypoint_report":{"frameworks_detected":[],"rulesets":["shipped"],"unresolved":{"Get":2,"Controller":1},"errors":[]},"external_symbols":{"can://slim/@external/(builtin)/log":{"id":"can://slim/@external/(builtin)/log","kind":"external","module":"(builtin)","name":"log"},"can://slim/@external/(builtin)/push":{"id":"can://slim/@external/(builtin)/push","kind":"external","module":"(builtin)","name":"push"},"can://slim/@external/(builtin)/map":{"id":"can://slim/@external/(builtin)/map","kind":"external","module":"(builtin)","name":"map"},"can://slim/@external/(builtin)/charAt":{"id":"can://slim/@external/(builtin)/charAt","kind":"external","module":"(builtin)","name":"charAt"},"can://slim/@external/(builtin)/repeat":{"id":"can://slim/@external/(builtin)/repeat","kind":"external","module":"(builtin)","name":"repeat"},"can://slim/@external/(builtin)/replace":{"id":"can://slim/@external/(builtin)/replace","kind":"external","module":"(builtin)","name":"replace"},"can://slim/@external/(builtin)/toLowerCase":{"id":"can://slim/@external/(builtin)/toLowerCase","kind":"external","module":"(builtin)","name":"toLowerCase"},"can://slim/@external/(builtin)/join":{"id":"can://slim/@external/(builtin)/join","kind":"external","module":"(builtin)","name":"join"}},"synthesized_callables":{"can://slim/typescript/src/controllers.ts/Controller@5:10":{"id":"can://slim/typescript/src/controllers.ts/Controller/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Get@8:10":{"id":"can://slim/typescript/src/controllers.ts/Get/","kind":"callable"},"can://slim/typescript/src/controllers.ts/Param@11:10":{"id":"can://slim/typescript/src/controllers.ts/Param/","kind":"callable"},"can://slim/typescript/src/services.ts/UserService/describeAll@37:27":{"id":"can://slim/typescript/src/services.ts/UserService/describeAll/","kind":"callable"}}}} \ No newline at end of file diff --git a/uv.lock b/uv.lock index ea97651..beda8a0 100644 --- a/uv.lock +++ b/uv.lock @@ -300,7 +300,7 @@ wheels = [ [[package]] name = "cldk" -version = "2.0.0rc5" +version = "2.0.0rc7" source = { editable = "." } dependencies = [ { name = "codeanalyzer-python" }, @@ -350,9 +350,9 @@ test = [ requires-dist = [ { name = "cldk", extras = ["java"], marker = "extra == 'all'" }, { name = "cldk", extras = ["neo4j"], marker = "extra == 'all'" }, - { name = "codeanalyzer-java", marker = "extra == 'java'", specifier = "==3.1.2" }, - { name = "codeanalyzer-python", specifier = "==1.5.1" }, - { name = "codeanalyzer-typescript", specifier = "==1.5.3" }, + { name = "codeanalyzer-java", marker = "extra == 'java'", specifier = "==3.3.3" }, + { name = "codeanalyzer-python", specifier = "==1.5.2" }, + { name = "codeanalyzer-typescript", specifier = "==1.6.0" }, { name = "neo4j", marker = "extra == 'neo4j'", specifier = ">=5.14,<7" }, { name = "networkx", specifier = ">=3.4.2,<4" }, { name = "pydantic", specifier = ">=2.10.6,<3" }, @@ -398,18 +398,18 @@ wheels = [ [[package]] name = "codeanalyzer-java" -version = "3.1.2" +version = "3.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jdk4py" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/aa/def8074c19b85c7d644c936eefa2f6be1a14f4f5ae06acc059c29405cd7d/codeanalyzer_java-3.1.2-py3-none-any.whl", hash = "sha256:77d9d894c8a225cc38a1217876cc42ca7abfcbd3c2ab10abecbbc338f5ac0872", size = 32839694, upload-time = "2026-09-09T14:07:37.058Z" }, + { url = "https://files.pythonhosted.org/packages/28/34/8364c6d79ee9ad3e3ef40dae0f95de30db0a9e43cc1032b351586c3a5912/codeanalyzer_java-3.3.3-py3-none-any.whl", hash = "sha256:0a499ada8bba00ac4adf45786e4bb578052af17e295796367afc951f20a0d84b", size = 32863677, upload-time = "2026-09-11T16:09:16.097Z" }, ] [[package]] name = "codeanalyzer-python" -version = "1.5.1" +version = "1.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astor" }, @@ -426,21 +426,21 @@ dependencies = [ { name = "typing-extensions" }, { name = "uv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/ab/13d36b0a4d68c7b4696459e91cf7677e965a60b451e79e574d40a8709c51/codeanalyzer_python-1.5.1.tar.gz", hash = "sha256:8b7468acc2a1c079ba09b626be5947c8fc3075093cab47b5ff1a28d0a817fc43", size = 231699, upload-time = "2026-09-09T15:56:23.148Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/c1/c76ad3a531d02f2548a8128c17c33c01c0d5aec240bd8e0dad93411590c3/codeanalyzer_python-1.5.2.tar.gz", hash = "sha256:18b1d81c44f0e0f1ab8dcb36a144345c58a51a55394a1a2b359d92c97c43df84", size = 234282, upload-time = "2026-09-10T21:45:35.272Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/2d/39e0817c098c6cb0c2438805032e483203b973f2b1ff37ed23820827d1d1/codeanalyzer_python-1.5.1-py3-none-any.whl", hash = "sha256:492a16b6ba04b0fe809dfc58472405fecbf616c6da8d0fe18a2085d9b048c62c", size = 237286, upload-time = "2026-09-09T15:56:21.787Z" }, + { url = "https://files.pythonhosted.org/packages/60/12/61fbed9875b06c061b24fcf4363e96215431db86efd895a2f4bd966c1d4f/codeanalyzer_python-1.5.2-py3-none-any.whl", hash = "sha256:7c0e1ed0b91fde5376f5c0cae70d48f85e83b0ff9e737c923b37c8e3375e2cd2", size = 239571, upload-time = "2026-09-10T21:45:33.895Z" }, ] [[package]] name = "codeanalyzer-typescript" -version = "1.5.3" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/24/c30e345c8f70e3b2e87c218c87d93044d00182de70450071baca83450feb/codeanalyzer_typescript-1.5.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d1534de6c029a56bc544a9b62b86b634ba3cab70f6cd4fc1201163f8d87788de", size = 30873520, upload-time = "2026-09-09T14:08:04.365Z" }, - { url = "https://files.pythonhosted.org/packages/09/48/99380eda3988023e6498ed9c843f0ef107813d43e3296a48205f1df315ec/codeanalyzer_typescript-1.5.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1a2dac07dccb107e52ff8a3020ec4d266c253fdc3390d3fabf4384ca91838c56", size = 28271759, upload-time = "2026-09-09T14:08:07.877Z" }, - { url = "https://files.pythonhosted.org/packages/72/91/9b3bbc8a839b6e8e76ca3c1919e417cdfe6f7ddf8710e91440194426aee7/codeanalyzer_typescript-1.5.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:b6879aa73bf700e3185516b1adefee21ca7118b508702a08bc9c6172e63cf649", size = 39039182, upload-time = "2026-09-09T14:08:11.185Z" }, - { url = "https://files.pythonhosted.org/packages/55/7a/5065b204df9b81dd7a1814b4516a319ffa7e444db994fd878ab5a715244a/codeanalyzer_typescript-1.5.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:22bdb2ab91d6d9fd3deffe1f7b4bbc9527de323a6c0ffc318a2cb3484633b4e5", size = 39083432, upload-time = "2026-09-09T14:08:15.134Z" }, - { url = "https://files.pythonhosted.org/packages/d2/02/9b971f72b59a5f8a97fc761aba2dd3ef973be7d362a8ff28e19e8cc062b6/codeanalyzer_typescript-1.5.3-py3-none-win_amd64.whl", hash = "sha256:2ac639c455b7638c143f59417c12974e7bdab0f09e22347675b8327c822835c5", size = 42233359, upload-time = "2026-09-09T14:08:19.109Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ad/510de3445b2017c1ef560fa392d0d3e78189b732594dd17a6646a353fcbd/codeanalyzer_typescript-1.6.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:410d2031393dee882580bc6060848dcd21574e7d5a98d53a898f71b3bd52b036", size = 30873592, upload-time = "2026-09-10T18:35:07.426Z" }, + { url = "https://files.pythonhosted.org/packages/3f/7b/e372a8867970b8c18aa9c4531112dba46a3e80f34575758e8433dcb6981c/codeanalyzer_typescript-1.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f36da2c5b8ebf7b2f5b5080a298b3c970be684db7db51bdf8e97072bcedadb5", size = 28271834, upload-time = "2026-09-10T18:35:11.281Z" }, + { url = "https://files.pythonhosted.org/packages/e5/09/e0028c84bbe4bfb80af09aea885bb1195ca5f26d09f529d644258aa21d91/codeanalyzer_typescript-1.6.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:c936e94ec70f415354fb1ba8df4e03c39bafce5c376afb995bcbe16a9650bc8d", size = 39039256, upload-time = "2026-09-10T18:35:15.323Z" }, + { url = "https://files.pythonhosted.org/packages/c4/cf/b623197514c258506ddf4182efd0228f276688447c60f64f4609ea2b49df/codeanalyzer_typescript-1.6.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:12f9aae1fed212345e98ea03abaaa2318691bcd2735bc3c4c61fb65068b23baa", size = 39083503, upload-time = "2026-09-10T18:35:20.094Z" }, + { url = "https://files.pythonhosted.org/packages/37/d0/10de246e0a78c9386e53cbed0dc664db9d1976a9ebcc9652b3f89e5fe1bf/codeanalyzer_typescript-1.6.0-py3-none-win_amd64.whl", hash = "sha256:5d8bd61b794e6159a513d15b40744fafebef3b99b1b891e516d9796090d872b9", size = 42233438, upload-time = "2026-09-10T18:35:24.808Z" }, ] [[package]]