-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode_symbols.lua
More file actions
117 lines (100 loc) · 3.5 KB
/
Copy pathcode_symbols.lua
File metadata and controls
117 lines (100 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
-- MCP Tool: code_symbols
-- Extract all symbols from source code as a flat, searchable list
-- Returns JSON-friendly output: name, kind, line — ideal for AI consumption
-- Entry kind: function.lua
local json = require("json")
local treesitter = require("treesitter")
local parser = require("parser")
local queries = require("queries")
--- Run query and collect symbols with a given symbol_kind label
local function extract(lang, pattern, root, code, symbol_kind, results)
if not pattern then return end
local query, err = treesitter.query(lang, pattern)
if err then return end
local captures = query:captures(root, code)
if not captures then return end
local seen = {}
for _, cap in ipairs(captures) do
if cap.name == "name" then
local text = cap.text
local key = text .. ":" .. symbol_kind
if not seen[key] then
seen[key] = true
local pos = parser.node_pos(cap.node)
table.insert(results, {
name = text,
kind = symbol_kind,
line = pos.start_line,
end_line = pos.end_line,
})
end
end
end
end
local function call(arguments)
local code, lang, err = parser.resolve_source(arguments)
if err then return "Error: " .. err end
local tree, root, parse_err = parser.parse(lang, code)
if parse_err then return "Error: " .. parse_err end
local patterns = queries.get_patterns(lang)
local symbols = {}
if patterns then
extract(lang, patterns.functions, root, code, "function", symbols)
extract(lang, patterns.types, root, code, "type", symbols)
extract(lang, patterns.imports, root, code, "import", symbols)
extract(lang, patterns.variables, root, code, "variable", symbols)
if patterns.exports then
extract(lang, patterns.exports, root, code, "export", symbols)
end
end
-- Sort by line number
table.sort(symbols, function(a, b) return a.line < b.line end)
-- Optional filter by kind
if arguments.kind and arguments.kind ~= "" then
local filter = arguments.kind
local filtered = {}
for _, s in ipairs(symbols) do
if s.kind == filter then
table.insert(filtered, s)
end
end
symbols = filtered
end
-- Optional filter by name pattern
if arguments.filter and arguments.filter ~= "" then
local pat = arguments.filter
local filtered = {}
for _, s in ipairs(symbols) do
if string.find(s.name, pat) then
table.insert(filtered, s)
end
end
symbols = filtered
end
if #symbols == 0 then
return "No symbols found."
end
-- Format output
local lines = {}
table.insert(lines, string.format(
"# Symbols (%s) — %d found", lang, #symbols
))
table.insert(lines, "")
table.insert(lines, string.format(
"%-10s %-12s %s", "Line", "Kind", "Name"
))
table.insert(lines, string.rep("-", 50))
for _, s in ipairs(symbols) do
local range
if s.end_line and s.end_line ~= s.line then
range = string.format("L%d-%d", s.line, s.end_line)
else
range = string.format("L%d", s.line)
end
table.insert(lines, string.format(
"%-10s %-12s %s", range, s.kind, s.name
))
end
return table.concat(lines, "\n")
end
return { call = call }