diff --git a/.luarc.json b/.luarc.json index 172b542..477ac4d 100644 --- a/.luarc.json +++ b/.luarc.json @@ -14,6 +14,7 @@ "runtime.path": ["lua/?.lua", "lua/?/init.lua"], "workspace": { "library": [ + "lua/", "${3rd}/busted/library", "${3rd}/luassert/library", "${3rd}/luv/library" diff --git a/lua/explorer_view.lua b/lua/explorer_view.lua index c242547..1b82c45 100644 --- a/lua/explorer_view.lua +++ b/lua/explorer_view.lua @@ -13,7 +13,7 @@ local ExplorerView = {} ExplorerView.__index = ExplorerView ---Creates a new ExplorerView ----@param config table Configuration options +---@param config table|nil Configuration options ---@return ExplorerView function ExplorerView.new(config) local self = setmetatable({}, ExplorerView) @@ -158,7 +158,7 @@ end local instance = nil ---Gets the singleton instance of ExplorerView ----@param config table Configuration options +---@param config table|nil Configuration options ---@return ExplorerView local function get_instance(config) if not instance then diff --git a/lua/explorer_viewmodel.lua b/lua/explorer_viewmodel.lua index 21d8413..d8841e0 100644 --- a/lua/explorer_viewmodel.lua +++ b/lua/explorer_viewmodel.lua @@ -1,6 +1,7 @@ -- explorer_viewmodel.lua -- Represents the state of the tree and persists between buffer open/close require("tree.node") +require("solution.solution") local solution_parser = require("solution").Parser local tree_builder = require("tree.builder") local node_module = require("tree.node") @@ -188,6 +189,7 @@ function ExplorerViewModel:activate_node_at_line(line_number) end -- Create a singleton instance +---@class ExplorerViewModel local instance = ExplorerViewModel.new() -- Add a getter for the tree property to make it more explicit diff --git a/lua/presentation/renderer.lua b/lua/presentation/renderer.lua index ccba279..c4927e3 100644 --- a/lua/presentation/renderer.lua +++ b/lua/presentation/renderer.lua @@ -6,7 +6,7 @@ local M = {} local has_devicons, devicons = pcall(require, "nvim-web-devicons") --- Gets the appropriate icon for a node based on its type and name ----@param node dotnet_explorer.TreeNode The tree node +---@param node TreeNode The tree node ---@return string|nil icon The icon to display ---@return string|nil highlight The highlight group name local function get_icon(node) @@ -46,7 +46,7 @@ end -- Renders a tree directly to a buffer with colored icons ---@param buf_id number The buffer ID to render to ----@param tree dotnet_explorer.TreeNode The tree to render +---@param tree TreeNode The tree to render ---@param opts? table Optional configuration { namespace_id?: number, clear_buffer?: boolean, window_width?: number } ---@return number namespace_id The namespace ID used for highlights function M.render_tree(buf_id, tree, opts) @@ -59,7 +59,7 @@ function M.render_tree(buf_id, tree, opts) local highlights = {} --- Recursive function to build lines and highlight data - ---@param node dotnet_explorer.TreeNode + ---@param node TreeNode local function build_node(node, indent) local icon, hl_group = get_icon(node) if not icon then @@ -121,7 +121,7 @@ function M.render_tree(buf_id, tree, opts) }) if is_open then - -- Sort children by name + -- Sort chidren by name local sorted_children = {} for _, child in ipairs(node.children) do table.insert(sorted_children, child) diff --git a/lua/solution/parser.lua b/lua/solution/parser.lua index bf23390..81ecaa3 100644 --- a/lua/solution/parser.lua +++ b/lua/solution/parser.lua @@ -1,5 +1,6 @@ -- require("solution.solution") -local Solution = require("solution.solution") +local Solution = require("solution.solution").Solution +local SolutionHeader = require("solution.solution_header").SolutionHeader local M = {} local project_types = require("solution.project_types") @@ -36,7 +37,7 @@ function M.parse_solution(filepath) return solution end ----@class dotnet_explorer.Project +---@class Project ---@field type_guid string The project type GUID ---@field name string The project name ---@field path string The relative normalized path to the project file @@ -51,7 +52,7 @@ Project.__index = Project ---@param name string The project name ---@param path string The relative normalized path to the project file ---@param guid string The unique project GUID ----@return dotnet_explorer.Project +---@return Project function Project.new(type_guid, name, path, guid) local self = setmetatable({}, Project) self.type_guid = type_guid @@ -63,20 +64,11 @@ function Project.new(type_guid, name, path, guid) return self end ----@class dotnet_explorer.SolutionHeader ----@fields visual_studio_version string|nil The Visual Studio version. ----@fields file_version string|nil The solution file format version. ----@fields minimum_visual_studio_version string|nil The minimum Visual Studio version required. - --- Parses the solution header from the given lines. ---@param lines string[] The lines of the solution file. ----@return dotnet_explorer.SolutionHeader +---@return SolutionHeader function M._parse_solution_header(lines) - local header = { - visual_studio_version = nil, - file_version = nil, - minimum_visual_studio_version = nil, - } + local header = SolutionHeader.new(nil, nil, nil) for _, line in ipairs(lines) do local min_vs_version = line:match("MinimumVisualStudioVersion = (.+)") if min_vs_version and not header.minimum_visual_studio_version then @@ -104,7 +96,7 @@ end --- Parses project information from solution file lines ---@param lines string[] The lines of the solution file ----@return dotnet_explorer.Project[] Array of parsed projects +---@return Project[] Array of parsed projects function M._parse_projects(lines) local projects = {} diff --git a/lua/solution/project_types.lua b/lua/solution/project_types.lua index 103e9f9..6f485d0 100644 --- a/lua/solution/project_types.lua +++ b/lua/solution/project_types.lua @@ -156,8 +156,8 @@ local guid_to_type = { } -- Convert GUID to project type --- @param guid string The project type GUID (case-insensitive) --- @return string|nil The project type name, or nil if not found +---@param guid string The project type GUID (case-insensitive) +---@return string|nil The project type name, or nil if not found function M.guid_to_type(guid) if not guid then return nil @@ -169,9 +169,9 @@ function M.guid_to_type(guid) end -- Check if a GUID represents a specific project type --- @param guid string The project type GUID --- @param expected_type string The expected type from M.TYPES --- @return boolean True if the GUID matches the expected type +---@param guid string The project type GUID +---@param expected_type string The expected type from M.TYPES +---@return boolean True if the GUID matches the expected type function M.is_type(guid, expected_type) return M.guid_to_type(guid) == expected_type end diff --git a/lua/solution/solution.lua b/lua/solution/solution.lua index f7dd4b5..5a2b0f4 100644 --- a/lua/solution/solution.lua +++ b/lua/solution/solution.lua @@ -1,16 +1,14 @@ ----@meta - ---@class Solution ---@field path string The absolute path to the solution file ----@field header dotnet_explorer.SolutionHeader The parsed solution header information ----@field projects_by_guid table A map of project GUIDs to Project objects +---@field header SolutionHeader The parsed solution header information +---@field projects_by_guid table A map of project GUIDs to Project objects ---@field nested_projects table A map of child project GUIDs to their parent project GUIDs local Solution = {} Solution.__index = Solution --- Creates a new Solution instance ---@param path string The relative path to the solution file ----@param header dotnet_explorer.SolutionHeader|nil The parsed solution header information +---@param header SolutionHeader|nil The parsed solution header information ---@return Solution function Solution.new(path, header) local self = setmetatable({}, Solution) @@ -27,10 +25,15 @@ function Solution.new(path, header) end --- Adds a project to the solution ----@param project dotnet_explorer.Project The project to add +---@param project Project The project to add function Solution:add_project(project) if not project or not project.guid then error("Invalid project: must have a valid GUID") end self.projects_by_guid[project.guid] = project end + +local M = {} +M.Solution = Solution + +return M diff --git a/lua/solution/solution_header.lua b/lua/solution/solution_header.lua new file mode 100644 index 0000000..377a099 --- /dev/null +++ b/lua/solution/solution_header.lua @@ -0,0 +1,23 @@ +---@class SolutionHeader +---@field visual_studio_version string|nil The Visual Studio version. +---@field file_version string|nil The solution file format version. +---@field minimum_visual_studio_version string|nil The minimum Visual Studio version required. +local SolutionHeader = {} +SolutionHeader.__index = SolutionHeader + +--- Creates a new SolutionHeader instance +---@param visual_studio_version string|nil The Visual Studio version. +---@param file_version string|nil The solution file format version. +---@param minimum_visual_studio_version string|nil The minimum Visual Studio version required. +---@return SolutionHeader +function SolutionHeader.new(visual_studio_version, file_version, minimum_visual_studio_version) + local self = setmetatable({}, { SolutionHeader }) + self.visual_studio_version = visual_studio_version + self.file_version = file_version + self.minimum_visual_studio_version = minimum_visual_studio_version + return self +end + +local M = {} +M.SolutionHeader = SolutionHeader +return M diff --git a/lua/tree/builder.lua b/lua/tree/builder.lua index 31c4a71..cc90b81 100644 --- a/lua/tree/builder.lua +++ b/lua/tree/builder.lua @@ -1,3 +1,5 @@ +require("solution.solution") +require("tree.node") local node_module = require("tree.node") local PROJECT_TYPES = require("solution").PROJECT_TYPES local NodeType = node_module.NodeType @@ -6,6 +8,8 @@ local TreeNode = node_module.TreeNode local M = {} -- Helper function to get sorted keys +---@param t table +---@param sort_func function|nil local function get_sorted_keys(t, sort_func) local keys = {} for k in pairs(t) do @@ -16,14 +20,18 @@ local function get_sorted_keys(t, sort_func) end -- Helper function to sort projects by name +---@param guid_a string +---@param guid_b string +---@param projects_by_guid table +---@return boolean local function sort_projects_by_name(guid_a, guid_b, projects_by_guid) local project_a = projects_by_guid[guid_a] local project_b = projects_by_guid[guid_b] return project_a.name < project_b.name end ----@param solution dotnet_explorer.Solution ----@return dotnet_explorer.TreeNode +---@param solution Solution +---@return TreeNode function M.build_tree(solution) -- Create root solution node local path = vim.fn.fnamemodify(solution.path, ":t") @@ -107,7 +115,7 @@ function M.sort_tree_children(node) end end ----@param project_node dotnet_explorer.TreeNode +---@param project_node TreeNode function M.populate_project_files(project_node) if not project_node.path then return @@ -122,7 +130,7 @@ function M.populate_project_files(project_node) M.add_directory_contents(project_node, project_dir) end ----@param node dotnet_explorer.TreeNode +---@param node TreeNode function M.nest_code_behind_files(node) if not node.children or #node.children == 0 then return @@ -180,9 +188,7 @@ function M.nest_code_behind_files(node) local parent_node = child.parent - vim.notify("Removing child from parent node: " .. parent_node.name, vim.log.levels.DEBUG) if parent_node ~= nil then - vim.notify("Removing child from parent node: " .. parent_node.name, vim.log.levels.DEBUG) parent_node:remove_child(child) end @@ -192,7 +198,7 @@ function M.nest_code_behind_files(node) end end ----@param parent_node dotnet_explorer.TreeNode +---@param parent_node TreeNode ---@param dir_path string function M.add_directory_contents(parent_node, dir_path) -- Check if directory exists and is readable