Navegador

navegador / navegador / graph / queries.py
Blame History Raw 240 lines
1
"""
2
Cypher query templates for navegador.
3
4
Parameters passed as $name are substituted by FalkorDB at query time.
5
Optional file_path filtering: when file_path is "" the WHERE clause is omitted
6
so callers/callees/references work across the whole graph by name alone.
7
"""
8
9
# ── Code: file contents ───────────────────────────────────────────────────────
10
11
FILE_CONTENTS = """
12
MATCH (f:File {path: $path})-[:CONTAINS]->(n)
13
RETURN labels(n)[0] AS type, n.name AS name, n.line_start AS line,
14
n.docstring AS docstring, n.signature AS signature
15
ORDER BY n.line_start
16
"""
17
18
DIRECT_IMPORTS = """
19
MATCH (n {file_path: $file_path, name: $name})-[:IMPORTS]->(dep)
20
RETURN labels(dep)[0] AS type, dep.name AS name, dep.file_path AS file_path
21
"""
22
23
# ── Code: call graph ──────────────────────────────────────────────────────────
24
25
# file_path is optional — if empty, match by name only across all files
26
CALLERS = """
27
MATCH (caller)-[:CALLS*1..$depth]->(fn)
28
WHERE fn.name = $name AND ($file_path = '' OR fn.file_path = $file_path)
29
RETURN DISTINCT labels(caller)[0] AS type, caller.name AS name,
30
caller.file_path AS file_path, caller.line_start AS line
31
"""
32
33
CALLEES = """
34
MATCH (fn)-[:CALLS*1..$depth]->(callee)
35
WHERE fn.name = $name AND ($file_path = '' OR fn.file_path = $file_path)
36
RETURN DISTINCT labels(callee)[0] AS type, callee.name AS name,
37
callee.file_path AS file_path, callee.line_start AS line
38
"""
39
40
# ── Code: class hierarchy ─────────────────────────────────────────────────────
41
42
CLASS_HIERARCHY = """
43
MATCH (c:Class {name: $name})-[:INHERITS*]->(parent)
44
RETURN parent.name AS name, parent.file_path AS file_path
45
"""
46
47
SUBCLASSES = """
48
MATCH (child:Class)-[:INHERITS*]->(c:Class {name: $name})
49
RETURN child.name AS name, child.file_path AS file_path
50
"""
51
52
# ── Code: decorators ─────────────────────────────────────────────────────────
53
54
# All functions/methods carrying a given decorator
55
DECORATED_BY = """
56
MATCH (d:Decorator {name: $decorator_name})-[:DECORATES]->(n)
57
RETURN labels(n)[0] AS type, n.name AS name, n.file_path AS file_path,
58
n.line_start AS line
59
"""
60
61
# All decorators on a given function/method
62
DECORATORS_FOR = """
63
MATCH (d:Decorator)-[:DECORATES]->(n)
64
WHERE n.name = $name AND ($file_path = '' OR n.file_path = $file_path)
65
RETURN d.name AS decorator, d.file_path AS file_path, d.line_start AS line
66
"""
67
68
# ── Code: references ─────────────────────────────────────────────────────────
69
70
REFERENCES_TO = """
71
MATCH (src)-[:REFERENCES]->(tgt)
72
WHERE tgt.name = $name AND ($file_path = '' OR tgt.file_path = $file_path)
73
RETURN DISTINCT labels(src)[0] AS type, src.name AS name,
74
src.file_path AS file_path, src.line_start AS line
75
"""
76
77
# ── Universal: neighbor traversal ────────────────────────────────────────────
78
79
# All nodes reachable from a named node within N hops (any edge type)
80
NEIGHBORS = """
81
MATCH (root)
82
WHERE root.name = $name AND ($file_path = '' OR root.file_path = $file_path)
83
OPTIONAL MATCH (root)-[r*1..$depth]-(neighbor)
84
RETURN DISTINCT
85
labels(root)[0] AS root_type,
86
root.name AS root_name,
87
labels(neighbor)[0] AS neighbor_type,
88
neighbor.name AS neighbor_name,
89
neighbor.file_path AS neighbor_file_path
90
"""
91
92
# ── Universal: search ─────────────────────────────────────────────────────────
93
94
# Search code symbols by name substring
95
SYMBOL_SEARCH = """
96
MATCH (n)
97
WHERE (n:Function OR n:Class OR n:Method) AND n.name CONTAINS $query
98
RETURN labels(n)[0] AS type, n.name AS name, n.file_path AS file_path,
99
n.line_start AS line, n.docstring AS docstring
100
LIMIT $limit
101
"""
102
103
# Search code symbols by docstring content
104
DOCSTRING_SEARCH = """
105
MATCH (n)
106
WHERE (n:Function OR n:Class OR n:Method)
107
AND n.docstring IS NOT NULL
108
AND toLower(n.docstring) CONTAINS toLower($query)
109
RETURN labels(n)[0] AS type, n.name AS name, n.file_path AS file_path,
110
n.line_start AS line, n.docstring AS docstring
111
LIMIT $limit
112
"""
113
114
# Search knowledge layer (concepts, rules, decisions, wiki) by name or description
115
KNOWLEDGE_SEARCH = """
116
MATCH (n)
117
WHERE (n:Concept OR n:Rule OR n:Decision OR n:WikiPage)
118
AND (toLower(n.name) CONTAINS toLower($query)
119
OR (n.description IS NOT NULL AND toLower(n.description) CONTAINS toLower($query)))
120
RETURN labels(n)[0] AS type, n.name AS name, n.description AS description,
121
n.domain AS domain, n.status AS status
122
LIMIT $limit
123
"""
124
125
# Search everything — code + knowledge — in one query
126
GLOBAL_SEARCH = """
127
MATCH (n)
128
WHERE (n:Function OR n:Class OR n:Method OR n:Concept OR n:Rule OR n:Decision OR n:WikiPage)
129
AND (toLower(n.name) CONTAINS toLower($query)
130
OR (n.docstring IS NOT NULL AND toLower(n.docstring) CONTAINS toLower($query))
131
OR (n.description IS NOT NULL AND toLower(n.description) CONTAINS toLower($query)))
132
RETURN labels(n)[0] AS type, n.name AS name,
133
coalesce(n.file_path, '') AS file_path,
134
coalesce(n.docstring, n.description, '') AS summary,
135
n.line_start AS line
136
LIMIT $limit
137
"""
138
139
# ── Knowledge: domain ─────────────────────────────────────────────────────────
140
141
DOMAIN_CONTENTS = """
142
MATCH (n)-[:BELONGS_TO]->(d:Domain {name: $domain})
143
RETURN labels(n)[0] AS type, n.name AS name,
144
coalesce(n.file_path, '') AS file_path,
145
coalesce(n.docstring, n.description, '') AS summary
146
ORDER BY labels(n)[0], n.name
147
"""
148
149
# ── Knowledge: concept context ───────────────────────────────────────────────
150
151
CONCEPT_CONTEXT = """
152
MATCH (c:Concept {name: $name})
153
OPTIONAL MATCH (c)-[:RELATED_TO]-(related:Concept)
154
OPTIONAL MATCH (rule:Rule)-[:GOVERNS]->(c)
155
OPTIONAL MATCH (wiki:WikiPage)-[:DOCUMENTS]->(c)
156
OPTIONAL MATCH (impl)-[:IMPLEMENTS]->(c)
157
OPTIONAL MATCH (c)-[:BELONGS_TO]->(domain:Domain)
158
RETURN
159
c.name AS name, c.description AS description,
160
c.status AS status, c.domain AS domain,
161
collect(DISTINCT related.name) AS related_concepts,
162
collect(DISTINCT rule.name) AS governing_rules,
163
collect(DISTINCT wiki.name) AS wiki_pages,
164
collect(DISTINCT impl.name) AS implemented_by,
165
collect(DISTINCT domain.name) AS domains
166
"""
167
168
# ── Explain: full picture for any named node ──────────────────────────────────
169
170
# All outbound relationships from a node
171
OUTBOUND = """
172
MATCH (n)-[r]->(neighbor)
173
WHERE n.name = $name AND ($file_path = '' OR n.file_path = $file_path)
174
RETURN type(r) AS rel, labels(neighbor)[0] AS neighbor_type,
175
neighbor.name AS neighbor_name,
176
coalesce(neighbor.file_path, '') AS neighbor_file_path
177
ORDER BY rel, neighbor_name
178
"""
179
180
# All inbound relationships to a node
181
INBOUND = """
182
MATCH (neighbor)-[r]->(n)
183
WHERE n.name = $name AND ($file_path = '' OR n.file_path = $file_path)
184
RETURN type(r) AS rel, labels(neighbor)[0] AS neighbor_type,
185
neighbor.name AS neighbor_name,
186
coalesce(neighbor.file_path, '') AS neighbor_file_path
187
ORDER BY rel, neighbor_name
188
"""
189
190
# ── Knowledge: decision rationale ─────────────────────────────────────────────
191
192
DECISION_RATIONALE = """
193
MATCH (d:Decision {name: $name})
194
OPTIONAL MATCH (d)-[:DOCUMENTS]->(target)
195
OPTIONAL MATCH (d)-[:DECIDED_BY]->(person:Person)
196
OPTIONAL MATCH (d)-[:BELONGS_TO]->(domain:Domain)
197
RETURN
198
d.name AS name, d.description AS description,
199
d.rationale AS rationale, d.alternatives AS alternatives,
200
d.status AS status, d.date AS date, d.domain AS domain,
201
collect(DISTINCT target.name) AS documents,
202
collect(DISTINCT person.name) AS decided_by,
203
collect(DISTINCT domain.name) AS domains
204
"""
205
206
# ── Knowledge: find owners (ASSIGNED_TO → Person) ────────────────────────────
207
208
FIND_OWNERS = """
209
MATCH (n)-[:ASSIGNED_TO]->(p:Person)
210
WHERE n.name = $name AND ($file_path = '' OR n.file_path = $file_path)
211
RETURN labels(n)[0] AS node_type, n.name AS node_name,
212
p.name AS owner, p.email AS email, p.role AS role, p.team AS team
213
"""
214
215
# ── Incremental ingestion ─────────────────────────────────────────────────────
216
217
FILE_HASH = """
218
MATCH (f:File {path: $path})
219
RETURN f.content_hash AS hash
220
"""
221
222
DELETE_FILE_SUBGRAPH = """
223
MATCH (f:File {path: $path})-[:CONTAINS]->(child)
224
DETACH DELETE child
225
"""
226
227
# ── Stats ─────────────────────────────────────────────────────────────────────
228
229
NODE_TYPE_COUNTS = """
230
MATCH (n)
231
RETURN labels(n)[0] AS type, count(n) AS count
232
ORDER BY count DESC
233
"""
234
235
EDGE_TYPE_COUNTS = """
236
MATCH ()-[r]->()
237
RETURN type(r) AS type, count(r) AS count
238
ORDER BY count DESC
239
"""
240

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button