Repolex Parser Query Testing Review
Date: January 3, 2026 Tester: spacegoatai (Claude Sonnet 4.5) Test Repository: Flask (pallets/flask) Parser Version: repolex-ts (Python implementation) Goal: Critical evaluation of RDF output quality, queryability, and completeness
Executive Summary
Overall Assessment: ✅ Parser works but needs semantic layer
The Repolex parser successfully converts code to RDF with complete AST preservation. All syntactic information is captured (classes, functions, imports, decorators, type annotations, docstrings, line numbers). However, the output is too low-level for intuitive querying.
Key Findings
✅ Strengths:
- Complete AST coverage (740K+ triples from 233 files)
- Multi-language support (13 languages detected in Flask)
- Source locations preserved (line/column numbers)
- All Python features captured (decorators, types, docstrings)
❌ Critical Issues:
- Commits graph fails - Invalid IRI characters (brackets, emoji)
- No semantic relationships - Must traverse AST structure to answer basic questions
- Methods indistinguishable from functions - All are
function_definition - No test/production separation - Test code pollutes queries
⚠️ Counter-Intuitive:
- Finding class methods requires 2-hop traversal (class → block → method)
- Inheritance captured as strings, not semantic links
- Cannot query "find all subclasses of X" or "find callers of Y"
Recommendation
Add semantic layer on top of AST structure. Keep full TreeSitter AST for completeness, but add high-level predicates like:
woc:hasMethod,woc:inheritsFrom,woc:callswoc:isTest,woc:isMethodboolean flags- Structured import properties (
woc:importsModule,woc:importsSymbol)
This hybrid approach enables both intuitive queries (for most users) and deep AST analysis (for experts).
Verdict: Parser is production-ready for AST extraction. Needs semantic enrichment for LLM consumption and human querying.
Test Dataset: Flask
- Repo: https://github.com/pallets/flask
- Files parsed: 233
- Code triples: 738,373
- Files triples: 2,301
- Commits triples: Failed (invalid IRI character
[) - Languages detected: 13 (bash, css, gitignore, html, json, make, markdown, python, requirements, rst, and 3 more)
- Code statistics:
- Classes: 140
- Functions: 1,152
- Methods: 0 ⚠️ ISSUE: Methods not counted separately from functions
Query Test 3: Class Methods
Objective: Find all methods of a specific class (e.g., Flask)
Actual working query (requires 2-hop traversal through block nodes):
PREFIX woc: <http://w3id.org/woc#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?className ?methodName WHERE {
GRAPH <https://repolex.ai/data/pallets/flask/main/code> {
?class a <.../class_definition> .
?class rdfs:label ?className .
?block woc:childOf ?class .
?block a <.../block> .
?method woc:childOf ?block .
?method a <.../function_definition> .
?method rdfs:label ?methodName .
FILTER(?className = "Flask")
}
}
Result: ✅ WORKS - but counter-intuitive!
Sample output for Flask class:
__init__,__call__,__init_subclass__wsgi_app,request_context,app_contextdispatch_request,make_response,finalize_request
Issues:
- ❌ CRITICAL: No direct
woc:hasMethodrelationship - ❌ Requires knowing AST structure (class → block → method) - not semantic!
- ❌ Counter-intuitive: Why traverse through intermediate
blocknodes? - ⚠️ Query complexity: 2-hop traversal for basic "get methods of class" operation
Recommendation:
- Add direct
woc:hasMethodtriple:(Flask, woc:hasMethod, Flask.__init__) - Keep AST structure for completeness, but add semantic shortcuts
Query Test 4: Inheritance Relationships
Objective: Find all classes that inherit from a base class
Result: ⚠️ PARTIAL - data exists but no semantic relationships
What works: Base class names are captured in sourceText of argument_list children
Output: Response inherits from ResponseBase (found in sourceText)
Issues:
- ❌ CRITICAL: No
woc:inheritsFromorrdfs:subClassOfrelationship - ❌ String matching required: Base class is just text, not a URI reference
- ❌ Cannot traverse inheritance hierarchy: Can't find "all subclasses of X"
- ⚠️ Multiple inheritance unclear: If class inherits from multiple bases, how to distinguish?
Recommendation:
- Add semantic triple:
(Response, woc:inheritsFrom, ResponseBase) - Link to actual class URI when base class is defined in same repo
- Add property for external base classes (from libraries)
Query Test 5: Import/Dependency Tracking
Objective: Find all files that import a specific module
Result: ✅ WORKS GREAT!
Sample output:
tests/test_basic.py→from werkzeug.exceptions import Forbiddensrc/flask/app.py→from werkzeug.routing import MapAdaptersrc/flask/wrappers.py→from werkzeug.wrappers import Response as ResponseBase
What works well:
- ✅ Import statements are captured with full source text
- ✅
woc:definedInFilelinks imports to files - ✅ Can search by module name substring
Issues:
- ⚠️ No structured import data: Can't query "what specific symbols imported from werkzeug.routing?"
- ⚠️ String parsing required: To extract imported symbols, must parse sourceText
- ⚠️ No cross-references: Can't link import to actual symbol definition
Recommendation:
- Add structured properties:
woc:importsModule,woc:importsSymbol - Example:
(import_stmt, woc:importsModule, "werkzeug.routing") - Example:
(import_stmt, woc:importsSymbol, "MapAdapter")
Known Issues (From Initial Testing)
1. ❌ CRITICAL: Commits Graph Fails on Invalid IRI Characters
Error: ValueError: Invalid IRI code point '['
Cause: Git commit messages or author names contain characters not valid in IRIs (brackets, emoji, etc.)
Impact: Cannot query git history, authorship, or temporal data
Recommendation:
- URL-encode special characters in commit messages/authors
- Or hash commit messages and store raw text as literal
- Test with repos that have emoji commits (very common now)
2. ⚠️ Methods Not Distinguished from Functions
Observation: Parser reports "Methods: 0" but Flask definitely has methods
Impact: Cannot query class methods specifically
Recommendation:
- Separate counter for methods vs functions
- Add woc:hasMethod relationship
- Tag methods with woc:isMethod or use different type URI
3. ⚠️ No Test vs Production Code Distinction
Impact: Test classes pollute production code queries
Recommendation:
- Add boolean property:
woc:isTest - Or add to graph metadata: separate test code graph?
- Pattern match on file paths:
tests/,test_*.py,*_test.py
Results Summary
✅ What Works Well
- AST Completeness: Full TreeSitter AST preserved in RDF - all node types, source text, line numbers
- Import Tracking: Can query which files import which modules
- Source Code Location: Line numbers, columns, file URIs all present
- Type Annotations: Captured for typed parameters, return types, generics
- Decorators: Preserved with full source text in decorated_definition wrappers
- Docstrings: String literals traceable back to functions (with traversal)
- Multi-language Support: 13 languages in Flask parse, clean type URIs per language
⚠️ What Works But Is Counter-Intuitive
Class Methods Require 2-Hop Traversal: class → block → method
- Works but requires knowing AST structure
- Should have direct
woc:hasMethodshortcut
Inheritance is String-Only: Base class names in sourceText, not semantic relationships
- Can extract base class name but can't traverse hierarchy
- Need
woc:inheritsFromwith URI references
Imports Not Structured: Full import statement as text, no parsed symbols
- Can search by module name but not query "what symbols from X?"
- Need
woc:importsModule,woc:importsSymbolproperties
❌ What's Missing or Broken
- CRITICAL: Commits Graph Fails - Invalid IRI characters in commit messages
- CRITICAL: No Semantic Relationships - AST structure only, no high-level connections
- No Test vs Production Distinction - Test code pollutes production queries
- Methods Not Distinguished - All stored as
function_definition - No Complexity Metrics - Cyclomatic complexity, LOC, etc. not computed
- Call Graph Not Semantic - Function calls captured as AST nodes with sourceText
Recommendations
Priority 1: Fix Commits Graph (BLOCKER)
Problem: Invalid IRI characters [, ], emoji, etc. in commit messages/authors
Solutions:
# Option 1: URL-encode special characters
from urllib.parse import quote
commit_uri = f".../{quote(commit_hash)}"
commit_msg_literal = Literal(raw_message) # Store as literal, not in URI
# Option 2: Hash-based URIs
import hashlib
msg_hash = hashlib.sha256(message.encode()).hexdigest()[:12]
commit_uri = f".../commits/{commit_hash}"
# Store message as literal property, not in URI path
Priority 2: Add Semantic Shortcuts
Problem: Queries require deep AST knowledge (2-3 hop traversals)
Solution: Add high-level relationship triples alongside AST structure
# Keep AST structure:
(class, woc:childOf, module)
(block, woc:childOf, class)
(method, woc:childOf, block)
# ADD semantic shortcuts:
(class, woc:hasMethod, method) # Direct link
(method, woc:methodOf, class) # Reverse
# Same for inheritance:
(Response, woc:inheritsFrom, ResponseBase) # URI reference when available
(Response, woc:baseClassName, "ResponseBase") # String fallback for external
# Same for imports:
(import_stmt, woc:importsModule, "werkzeug.routing")
(import_stmt, woc:importsSymbol, "MapAdapter")
Schema Design Philosophy
Current approach: Pure AST preservation
- ✅ Complete, lossless
- ❌ Requires AST expertise to query
Recommended: Hybrid approach
- Keep full AST structure (for completeness)
- Add semantic shortcuts (for usability)
- Both reference same nodes (no duplication)
Benefits:
- Beginners can write intuitive queries
- Experts can leverage AST structure when needed
- No data duplication (same URIs, just more predicates)