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):
| Module | Responsibility | Notable files |
|---|---|---|
| antlr | Generates 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). |
| providers | Supplies 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. |
| vscode | VS 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. |
| src | Small bootstrap module; contains Factories.kt which creates a VsCodeParser instance. | src/main/kotlin/Factories.kt. |
| regex | Optional 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
- Project discovery –
GitignoreAwareFileWalker.kttraverses the filesystem, filtering by.gitignore. - Language selection –
ConverterBasedAntlrLanguageSpecification.kt/QueryBasedAntlrLanguageSpecification.ktdecide which ANTLR grammar to use per file extension. - Parsing – ANTLR‑generated lexers/parsers (e.g.,
CSharpLexer.java,JavaScriptParser.java,KotlinParser.java) produce ASTs. - AST walking –
AntlrTreeWalker.ktwalks each tree, extracting entities (classes, functions, imports) and relationships (calls, inherits, uses). - Graph augmentation –
GraphAugmenter.ktmerges per‑file graphs, deduplicates nodes, and attaches MinHash signatures for similarity detection (MinHasher.kt). - Persist / expose –
GraphMergingServiceImpl.ktwrites the graph to Neo4j (or an in‑memory store) andVsCodeParser.ktmakes it available via the LSP for VS Code extensions.
Hub / blast‑radius files – AntlrTreeWalker.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 (
.giffiles 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.