Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lua/hopcsharp/database/query.lua
Original file line number Diff line number Diff line change
Expand Up @@ -273,20 +273,26 @@ M.get_reference_by_name_and_current_namespace = function(name, namespaces)
WHERE (r.name = '%s' OR r.name GLOB '%s' OR r.name || 'Attribute' = '%s')
-- or we have using with that namespace
-- or we are in the same namespace
AND ((u.namespace IN (%s)) OR (n.name IN (%s)))
-- or there are references in a nested namespaces
AND ((u.namespace IN (%s)) OR (n.name IN (%s)) OR (n.name GLOB %s))
ORDER BY
r.name ASC,
n.name ASC,
f.path ASC
]]

-- TODO check if GLOB didn't introduce table scan
-- TODO cover in tests
-- TODO comment and explain why we are doing it
local namespace_glob = "'" .. namespaces[1] .. "*'"

for i, namespace in ipairs(namespaces) do
namespaces[i] = '"' .. namespace .. '"'
end

local namespace_string = table.concat(namespaces, ',')

return string.format(query, name, name .. '<*>', name, namespace_string, namespace_string)
return string.format(query, name, name .. '<*>', name, namespace_string, namespace_string, namespace_glob)
end

M.get_reference_by_name_and_type = function(name, type)
Expand Down
7 changes: 7 additions & 0 deletions lua/hopcsharp/hop/providers/definition.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ M.__by_name_type_and_current_namespace = function(current_word, node)
table.insert(namespace, vim.treesitter.get_node_text(nn, 0, nil))
end

-- TODO cover in tests to make sure it is needed
-- insert outer namespace that are not included by usings
-- because namespace has access to all types defined in outer namespaces
for _, n in ipairs(utils.__get_outer_namespaces(namespace[1] or '')) do
table.insert(namespace, n)
end

local db = database.__get_db()
return db:eval(query.get_definition_by_name_type_and_namespace(name, node_type, namespace))
end,
Expand Down
3 changes: 2 additions & 1 deletion lua/hopcsharp/hop/providers/reference.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ M.__by_name_and_current_namespace = function(current_word, node)
end

local db = database.__get_db()
return db:eval(query.get_reference_by_name_and_current_namespace(name, namespace))
return db:eval(query.get_reference_by_name_and_current_namespace(name, namespace)),
dbutils.get_reference_type_name
end,
}
end
Expand Down
31 changes: 31 additions & 0 deletions lua/hopcsharp/hop/providers/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,35 @@ M.__get_node_modifiers = function(node)
return modifiers
end

---@param namespace string Namespace name
---@return string[] List of outer namespaces
M.__get_outer_namespaces = function(namespace)
local namespaces = {}

if namespace == nil then
return namespaces
end

if namespace == '' then
return namespaces
end

local parts = {}
for part in string.gmatch(namespace, '([^%.]+)') do
table.insert(parts, part)
end

local i = 1
while i < #parts do
local n = {}
for j = 1, i, 1 do
table.insert(n, parts[j])
end
i = i + 1
table.insert(namespaces, table.concat(n, '.'))
end

return namespaces
end

return M
36 changes: 36 additions & 0 deletions test/hop/providers/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,40 @@ describe('hop.providers.utils', function()
local modifiers = utils.__get_node_modifiers(vim.treesitter.get_node())
assert(#modifiers == 0)
end)

it('__get_outer_namespaces - outmost namespace', function()
local namespaces = utils.__get_outer_namespaces('NoNesting')
assert(#namespaces == 0)
end)

it('__get_outer_namespaces - one outer namespace', function()
local namespaces = utils.__get_outer_namespaces('One.Two')
assert(#namespaces == 1)
assert(namespaces[1] == 'One')
end)

it('__get_outer_namespaces - two outer namespace', function()
local namespaces = utils.__get_outer_namespaces('One.Two.Three')
assert(#namespaces == 2)
assert(namespaces[1] == 'One')
assert(namespaces[2] == 'One.Two')
end)

it('__get_outer_namespaces - happy', function()
local namespaces = utils.__get_outer_namespaces('This.Is.My.Namespace')
assert(#namespaces == 3)
assert(namespaces[1] == 'This')
assert(namespaces[2] == 'This.Is')
assert(namespaces[3] == 'This.Is.My')
end)

it('__get_outer_namespaces - nil', function()
local namespaces = utils.__get_outer_namespaces(nil)
assert(#namespaces == 0)
end)

it('__get_outer_namespaces - empty', function()
local namespaces = utils.__get_outer_namespaces('')
assert(#namespaces == 0)
end)
end)
Loading