Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion schema.neo4j.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"schema_version": "string",
"language": "string",
"max_level": "integer",
"k_limit": "integer"
"k_limit": "integer",
"analyzer_name": "string",
"analyzer_version": "string"
}
},
{
Expand Down
6 changes: 6 additions & 0 deletions src/build/neo4j/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export function project(app: V2Application, _appName?: string): GraphRows {
language: app.language,
max_level: app.max_level,
k_limit: app.k_limit ?? null,
// Same analyzer{name,version} the JSON envelope carries (emit.ts) — the two co-primary
// projections must never diverge on analyzer identity (issue #43). Namespaced as
// analyzer_name/analyzer_version (not bare name/version) to avoid colliding with the
// app-name param (project()'s _appName) and every other CanNode's bare `name`.
analyzer_name: app.analyzer.name,
analyzer_version: app.analyzer.version,
}));

for (const mod of Object.values(root.symbol_table)) {
Expand Down
8 changes: 7 additions & 1 deletion src/build/neo4j/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ export const NODE_LABELS: NodeLabel[] = [
label: "Application",
mergeLabel: "Application",
key: "id",
properties: { id: "string", schema_version: "string", language: "string", max_level: "integer", k_limit: "integer" },
properties: {
id: "string", schema_version: "string", language: "string", max_level: "integer", k_limit: "integer",
// Analyzer identity — mirrors the JSON envelope's `analyzer{name,version}` (issue #43),
// namespaced (not bare name/version) to avoid colliding with the app-name param / every
// other CanNode's bare `name`.
analyzer_name: "string", analyzer_version: "string",
},
},
{
label: "Module",
Expand Down
14 changes: 14 additions & 0 deletions test/neo4j-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { describe, expect, test } from "bun:test";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import pkg from "../package.json";
import {
MARKER_LABELS,
NODE_LABELS,
Expand Down Expand Up @@ -92,6 +93,19 @@ describe("neo4j schema conformance", () => {
});
});

// ---- :Application analyzer identity (issue #43) ------------------------------------------------
// The JSON envelope advertises `analyzer{name,version}` (#29); the Neo4j :Application node is the
// co-primary projection of the same envelope and must not diverge on analyzer identity.

describe(":Application node carries analyzer identity (issue #43)", () => {
test("version matches package.json (the same source the JSON envelope's analyzer.version uses)", () => {
const appNode = rows.nodes.find((n) => n.labels.includes("Application"));
expect(appNode, "no :Application node projected").toBeDefined();
expect(appNode!.props.analyzer_version).toBe(pkg.version);
expect(appNode!.props.analyzer_name).toBe("codeanalyzer-typescript");
});
});

// ---- Class inheritance: EXTENDS/IMPLEMENTS (issue #33) ------------------------------------------
// dataflow-app's src/hierarchy.ts is a minimal, first-party heritage fixture: `Rectangle implements
// Shape`, `Square extends Rectangle implements Labeled`.
Expand Down