Skip to content

Commit ea442c6

Browse files
committed
Fixed edge case for inifine recursion
1 parent b765e9d commit ea442c6

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

lua/clapi/parser/init.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ local tsparsers = require("nvim-treesitter.parsers")
44
local async = require("plenary.async")
55
local lsp = require("clapi.lsp")
66

7+
--- Keeps track of the analyzed files to avoid infinite recursion
8+
local files_analyzed = {}
9+
10+
--- We clear the table to reset the analyzed files.
11+
--- This is important because the value persist between builtint executions
12+
local function clear_files_analyzed()
13+
files_analyzed = {}
14+
end
15+
716
---@class ParserModule
817
local M = {}
918

@@ -110,6 +119,14 @@ local get_parent_file = async.wrap(function(opts, callback)
110119

111120
local filepath =
112121
lsp.get_file_from_position({ bufnr = opts.bufnr, position = { character = char, line = line } })
122+
123+
if files_analyzed[filepath] then
124+
callback(nil)
125+
return
126+
end
127+
128+
files_analyzed[filepath] = true
129+
113130
if not filepath or filepath == "" then
114131
-- error already printed in get_file_from_position
115132
callback(nil)
@@ -312,9 +329,11 @@ M.parse_file = async.wrap(function(opts, callback)
312329
end
313330
end
314331

332+
clear_files_analyzed()
315333
callback(result)
316334
end)
317335
else
336+
clear_files_analyzed()
318337
callback(result)
319338
end
320339
end, 2)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
local parser = require("clapi.parser.init")
2+
local t = require("plenary.async.tests")
3+
4+
t.describe("parser.parse_file with recursive inheritance", function()
5+
t.it("should handle recursive inheritance without infinite loops", function()
6+
local src_root_dir = vim.fn.getcwd() .. "/tests/clapi/functional/resources/code/php/example/src"
7+
local filename = src_root_dir .. "/Course/Recursive.php"
8+
vim.cmd("edit " .. filename)
9+
local bufnr = vim.api.nvim_get_current_buf()
10+
local client_id = vim.lsp.start({
11+
name = "phpactor",
12+
cmd = { "phpactor", "language-server", "-vvv" },
13+
root_dir = src_root_dir,
14+
capabilities = vim.lsp.protocol.make_client_capabilities(),
15+
})
16+
vim.lsp.buf_attach_client(bufnr, client_id)
17+
vim.wait(3000)
18+
19+
local result = parser.parse_file({
20+
bufnr = bufnr,
21+
show_inherited = true,
22+
})
23+
24+
-- Test that we get results without hanging due to recursion
25+
assert.is_table(result)
26+
27+
-- Verify the expected methods are found
28+
local found_get_subscribed_services = false
29+
local found_get_view_handler = false
30+
31+
for _, item in ipairs(result) do
32+
if item.text == "[Function] getSubscribedServices" or
33+
item.text == "[Function] BaseAbstractFOSRestController::getSubscribedServices" then
34+
found_get_subscribed_services = true
35+
end
36+
if item.text == "[Function] getViewHandler" or
37+
item.text == "[Function] AbstractFOSRestController::getViewHandler" then
38+
found_get_view_handler = true
39+
end
40+
end
41+
42+
assert.is_true(found_get_subscribed_services, "Should find getSubscribedServices method")
43+
assert.is_true(found_get_view_handler, "Should find getViewHandler method")
44+
end)
45+
end)

0 commit comments

Comments
 (0)