fix/neo4j: lossless field, import & call-graph projection (#156, #157, #158) + relative-path build fix - #159
Merged
Merged
Conversation
, #158) Three bugs in the `--emit neo4j` projection (GraphProjector) that silently dropped IR data the `--emit json` backend preserves: - #156: every :JField shared the id `<fqn>#field#null` because the node was keyed by Field.getName(), which is always null for a field declaration (the IR keys fields by their `variables` list). All fields of a class collapsed to one node under the j_field_id unique constraint. Key the id by the joined variable names, with a positional-index fallback. - #157: single-type imports were stripped to a :JPackage and multiple imports from one package collapsed to a single edge, losing the type name. Link non-wildcard, non-static imports to a :JType (materializing an external ghost when it is not a project type), keep :JPackage for wildcard/static-member imports, and carry the full import `path` on every J_IMPORTS edge. Adds the `path` property to the J_IMPORTS schema and regenerates schema.neo4j.json. - #158: constructor call edges were gated out because the call-graph vertex `signature` rewrites <init>/<clinit> to the simple class name for readability, while the :JCallable node id keeps the raw <init> signature. Key J_CALLS endpoints off `callable_declaration`, which preserves the symbol-table signature verbatim. On daytrader8 this recovers all resolvable constructor edges (J_CALLS 1562 -> 1715; ~97% of call-graph edges with both endpoints present). The remainder are synthetic/implicit callables with no source node (implicit default ctors, access$ accessors, bridge methods, anonymous classes), which are correctly dropped. Adds GraphProjectorCallGraphTest covering constructor resolution, gating of unresolved targets, and the signature fallback.
…ailures Two coupled papercuts in the level-2 build path: - A relative `--input` doubled the project path. The build runs with its working directory set to the project root, but gradleBuild passed the raw (relative) `-p <projectPath>` (maven was already absolutized, gradle was not), so it resolved against the root to `<root>/<root>`, the build failed, and zero application classes loaded. Normalize the path to absolute once at the buildProjectAndStreamClassFiles entry point so every downstream tool is consistent. - A failed build was swallowed: buildProjectAndStreamClassFiles returns an empty list (never null) on failure, but ScopeUtils only guarded `== null`, so analysis proceeded with an empty scope and died later with a cryptic WALA "Could not create entrypoint callsites" error. Guard on emptiness too and report the real cause (build failed / no compiled classes / bad input path).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #156, #157, #158, all in the
--emit neo4jprojection path, plus a coupled build-path papercut found while reproducing #158.#156 — every JField collapses into one node
projectFieldkeyed the node id byField.getName(), which is alwaysnullfor a field declaration (the IR keys fields by theirvariableslist). All fields of a class collapsed to a single<fqn>#field#nullnode under thej_field_idunique constraint. Now keyed by the joined variable names with a positional fallback.#field#null122 → 0; distinct JField ids → 339.#157 — imports lose the type name
Single-type imports were stripped to a
:JPackage, and multiple imports from one package collapsed to one edge. Now non-wildcard, non-static imports link to a:JType(materializing an external ghost when it isn't a project type); wildcard/static-member imports keep:JPackage; and the fullpathrides on everyJ_IMPORTSedge. Addspathto theJ_IMPORTSschema and regeneratesschema.neo4j.json.J_IMPORTS → JType0 → 1470,→ JPackage771 → 9 (just wildcards).#158 — J_CALLS undercount
The call-graph vertex
signaturerewrites constructors from<init>(...)to the simple class name for readability, while the:JCallablenode id keeps the raw<init>(...)signature — so every constructor call edge was gated out. KeyJ_CALLSendpoints offcallable_declaration, which preserves the symbol-table signature verbatim (verified: zero ambiguity conflicts).access$accessors, bridge methods, anonymous classes) — correctly dropped.Relative-path build fix (found while reproducing #158)
--inputdoubled the project path: the build runs with its working dir at the project root, butgradleBuildpassed a relative-p(maven was already absolutized, gradle wasn't), resolving to<root>/<root>→ build fails → 0 application classes. Normalized to absolute once at the build entry point.buildProjectAndStreamClassFilesreturns an empty list (never null) on failure, butScopeUtilsonly guarded== null, so analysis proceeded with an empty scope and died with a cryptic WALA "Could not create entrypoint callsites". Now guards emptiness and reports the real cause.Tests
GraphProjectorCallGraphTest(constructor resolution, gating of unresolved targets, signature fallback).Neo4jSchemaConformanceTestgreen (covers --emit neo4j: all JField nodes share id <fqn>#field#null, collapsing every field of a class into one node #156/--emit neo4j: imports lose the type name (J_IMPORTS only links to JPackage, never JType) #157 + regenerated schema).--analysis-level 2.Neo4jBoltWriterTest,CodeAnalyzerIntegrationTest) not run locally — exercised in CI.