The Problem

Developers need a fast, multi‑language way to turn a codebase into a queryable graph of entities and relationships. Without an automated pipeline the process is manual, error‑prone, and does not scale across large or mixed‑language projects.

What This Does

code-to-knowledge-graph is a Kotlin/JVM toolkit that parses source code and emits a rich, queryable knowledge graph. It leverages ANTLR grammars for C#, JavaScript and Kotlin, then merges the parsed ASTs into a unified model that can be persisted in Neo4j or queried via the VS Code Language Server Protocol.

Key components (from the measured structure):

ModuleResponsibilityNotable files
antlrGenerates language parsers (CSharp, JavaScript, Kotlin) from .g4 grammars and provides AST‑walking logic.antlr/src/main/kotlin/AntlrTreeWalker.kt, antlr/src/main/kotlin/GraphAugmenter.kt, antlr/src/main/kotlin/bevel_ast_ql/ArgumentResolver.kt, language‑specific grammars (CSharpLexer.g4, JavaScriptParser.g4, KotlinParser.g4).
providersSupplies file‑system walking, graph‑merging, and MinHash similarity logic.providers/src/main/kotlin/GraphMergingServiceImpl.kt, providers/src/main/kotlin/MinHasher.kt, providers/src/main/kotlin/GitignoreAwareFileWalker.kt.
vscodeVS Code extension entry point that creates a graph from a project path and exposes it through the LSP.vscode/src/main/kotlin/VsCodeParser.kt, vscode/src/main/kotlin/BatchProcessor.kt, vscode/src/main/kotlin/VsCodeGraphUpdater.kt.
srcSmall bootstrap module; contains Factories.kt which creates a VsCodeParser instance.src/main/kotlin/Factories.kt.
regexOptional utility for HTML/JS‑specific tokenisation.regex/src/main/kotlin/AngularHtmlParser.kt.

The entry point is FactoriesKt.createVsCodeParser(projectPath) (src/main/kotlin/Factories.kt). That function instantiates a VsCodeParser, which internally walks the project respecting .gitignore, invokes the appropriate ANTLR language specification (Kotlin/JS/C#) and feeds the resulting ASTs into GraphAugmenter.kt and GraphMergingServiceImpl.kt to build nodes and edges. The final graph can be stored in a Neo4j instance (the repo references Neo4j visualisation assets) or exported for further tooling.

How It Is Wired

  1. Project discoveryGitignoreAwareFileWalker.kt traverses the filesystem, filtering by .gitignore.
  2. Language selectionConverterBasedAntlrLanguageSpecification.kt / QueryBasedAntlrLanguageSpecification.kt decide which ANTLR grammar to use per file extension.
  3. Parsing – ANTLR‑generated lexers/parsers (e.g., CSharpLexer.java, JavaScriptParser.java, KotlinParser.java) produce ASTs.
  4. AST walkingAntlrTreeWalker.kt walks each tree, extracting entities (classes, functions, imports) and relationships (calls, inherits, uses).
  5. Graph augmentationGraphAugmenter.kt merges per‑file graphs, deduplicates nodes, and attaches MinHash signatures for similarity detection (MinHasher.kt).
  6. Persist / exposeGraphMergingServiceImpl.kt writes the graph to Neo4j (or an in‑memory store) and VsCodeParser.kt makes it available via the LSP for VS Code extensions.

Hub / blast‑radius filesAntlrTreeWalker.kt, GraphAugmenter.kt, and Factories.kt are the most central: changes to grammar or traversal logic ripple across all language parsers. The measured “oversized file” findings (e.g., CSharpLexer.java at 1 239 lines) indicate that any modification to the C# parser has a wide impact.

How To Use It

Setup

# Clone the repository (use the exact URL)
git clone https://github.com/moses-y/code-to-knowledge-graph

# Build with Gradle (the project uses the Gradle wrapper)
./gradlew build   # from the repo root

Configuration No external keys or env‑vars are required; the parser respects each language’s .g4 grammar files located under antlr/src/main/antlr/. If you wish to persist the graph in Neo4j, add a Neo4j connection string in providers/src/main/kotlin/GraphMergingServiceImpl.kt (the file currently contains a placeholder; adjust the URI, user, password as needed).

Running it

// From Kotlin or Java
import software.bevel.code_to_knowledge_graph.FactoriesKt

val projectPath = "/path/to/your/codebase"
val parser = FactoriesKt.createVsCodeParser(projectPath)
val graph = parser.parse(listOf(projectPath))

println("Nodes: ${graph.nodes.size}")
println("Connections: ${graph.connections.allConnections.size}")

The same logic can be invoked from the VS Code extension (Bevel: Re-/Analyze Project) or via the Gradle plugin (software.bevel:code-to-knowledge-graph:1.1.3).

Real‑World Use

A security‑audit team wants to surface every external library call across a monorepo of Kotlin, JavaScript and C# services. They run the parser on the repo root:

./gradlew run -PmainClass=software.bevel.code_to_knowledge_graph.FactoriesKt \
  -Pargs="\"src/main/kotlin\""

The resulting graph is loaded into Neo4j (neo4j-admin import‑compatible CSV) and queried:

MATCH (n:Class)-[:CALLS]->(m:Class)
RETURN n.name, count(m) AS callCount
ORDER BY callCount DESC
LIMIT 20

The team then uses the Bevel Neo4j Visualisation repo to explore hot‑spot dependencies and prioritise refactoring.

Code Health & Issues

Measured findings (static analysis, 60 total):

  • High cognitive load – deep nesting (28 occurrences) in InmemantlrErrorListener.java, ParseTree.java, ArgumentResolver.kt – max indentation depth 11; guard‑clause refactor recommended.
  • High duplicated code blocks (515 repeated 6‑line blocks across 41 files) – e.g., ParseTreeProcessorException.java, DefaultListener.java, DefaultTreeListener.java, JsonProcessor.java; extract shared helpers.
  • High oversized files (13 files > 1 200 loc) – CSharpLexer.java, JavaScriptParser.java, KotlinLexer.java; split into smaller modules.
  • High branching density (15 files, 24 branch points over 78 lines) – AntlrTreeWalker.kt, GraphAugmenter.kt, ArgumentResolver.kt; decompose decision logic.
  • Low TODO/FIXME markers (3 files) – AntlrTreeWalker.kt, MacroConverters.kt, NodeConverter.kt.

SDLC observations (from structure):

  • No CI/CD pipeline – .github/ or CI config absent; every change merges without an automated build/test gate.
  • Large binary assets (.gif files 27‑30 MB) stored in the repo; consider Git LFS or moving to object storage.
  • Missing convention files: .editorconfig, .gitattributes, formatter config (e.g., Kotlinfmt).

The Bottom Line

The repository provides a functional, language‑aware parser that turns source code into a queryable graph with modest setup. The codebase is sizable and contains several high‑severity maintainability hot‑spots (deep nesting, duplicated blocks, oversized files) that should be addressed before scaling. It is well‑suited for teams that need custom code‑graph tools and are willing to invest in refactoring and CI infrastructure.