142 lines
3.6 KiB
Lua
142 lines
3.6 KiB
Lua
-- Tree node representation for DAP variables
|
|
local Content = require("ow.dap.hover.content")
|
|
local log = require("ow.log")
|
|
|
|
---@class ow.dap.hover.Node
|
|
---@field item ow.dap.Item The DAP item this node represents
|
|
---@field parent ow.dap.hover.Node? Parent node
|
|
---@field children ow.dap.hover.Node[] Child nodes
|
|
---@field is_expanded boolean Whether this node is expanded
|
|
---@field line_number integer Buffer line number where this node is displayed
|
|
---@field is_last_child boolean Whether this is the last child of its parent
|
|
local Node = {}
|
|
Node.__index = Node
|
|
|
|
---Create a new tree node
|
|
---@param item ow.dap.Item
|
|
---@param parent ow.dap.hover.Node?
|
|
---@return ow.dap.hover.Node
|
|
function Node.new(item, parent)
|
|
return setmetatable({
|
|
item = item,
|
|
parent = parent,
|
|
children = {},
|
|
is_expanded = false,
|
|
line_number = -1,
|
|
is_last_child = false,
|
|
}, Node)
|
|
end
|
|
|
|
---Check if this node represents a container (struct/array)
|
|
---@return boolean
|
|
function Node:is_container()
|
|
return self.item.variablesReference and self.item.variablesReference > 0
|
|
or false
|
|
end
|
|
|
|
---Get the tree prefix for this node (├─, └─, │, etc.)
|
|
---@return string
|
|
function Node:get_tree_prefix()
|
|
if not self.parent then
|
|
return "" -- Root node has no prefix
|
|
end
|
|
|
|
local prefix = ""
|
|
|
|
-- Walk up the tree to build the prefix
|
|
local node = self.parent
|
|
while node and node.parent do
|
|
if node.is_last_child then
|
|
prefix = " " .. prefix
|
|
else
|
|
prefix = "│ " .. prefix
|
|
end
|
|
node = node.parent
|
|
end
|
|
|
|
-- Add the final branch character
|
|
if self.is_last_child then
|
|
prefix = prefix .. "└─ "
|
|
else
|
|
prefix = prefix .. "├─ "
|
|
end
|
|
|
|
return prefix
|
|
end
|
|
|
|
---@return boolean
|
|
function Node:is_c_array_element()
|
|
return self.item.name:match("^%[?%d+%]?$") ~= nil
|
|
end
|
|
|
|
---@return boolean
|
|
function Node:is_c_pointer_child()
|
|
return self.parent
|
|
and self.parent.item.type:match(
|
|
"%*%s*[const%s]*[volatile%s]*[restrict%s]*$"
|
|
) ~= nil
|
|
or false
|
|
end
|
|
|
|
---@return string
|
|
function Node:format_c_expression()
|
|
if self:is_c_array_element() then
|
|
return string.format(
|
|
"%s = (%s) %s",
|
|
self.item.name,
|
|
self.item.type,
|
|
self.item.value
|
|
)
|
|
end
|
|
|
|
if self:is_c_pointer_child() then
|
|
return string.format("*%s = %s", self.parent.item.name, self.item.value)
|
|
end
|
|
|
|
return string.format(
|
|
"%s %s = %s",
|
|
self.item.type,
|
|
self.item.name,
|
|
self.item.value
|
|
)
|
|
end
|
|
|
|
---Format this node as highlighted content
|
|
---@param session dap.Session DAP session for making requests
|
|
---@return ow.dap.hover.Content
|
|
function Node:format(session)
|
|
local content = Content.new()
|
|
|
|
-- Add expansion marker for containers
|
|
if self:is_container() then
|
|
local marker = self.is_expanded and "-" or "+"
|
|
content:add(marker .. " ", "@comment")
|
|
else
|
|
content:add(" ")
|
|
end
|
|
|
|
-- Add tree prefix
|
|
local tree_prefix = self:get_tree_prefix()
|
|
if tree_prefix ~= "" then
|
|
content:add(tree_prefix, "@comment")
|
|
end
|
|
|
|
local stmt
|
|
if session.filetype == "c" or session.filetype == "cpp" then
|
|
stmt = self:format_c_expression()
|
|
else
|
|
error(
|
|
string.format("Formatting for %s not implemented", session.filetype)
|
|
)
|
|
end
|
|
content:add_with_treesitter(stmt, session.filetype)
|
|
|
|
if self.item.value == "" then
|
|
content:add("...", "@comment")
|
|
end
|
|
|
|
return content
|
|
end
|
|
|
|
return Node
|