Skip to content
Merged
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
1 change: 1 addition & 0 deletions .luarc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"runtime.path": ["lua/?.lua", "lua/?/init.lua"],
"workspace": {
"library": [
"lua/",
"${3rd}/busted/library",
"${3rd}/luassert/library",
"${3rd}/luv/library"
Expand Down
4 changes: 2 additions & 2 deletions lua/explorer_view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions lua/explorer_viewmodel.lua
Original file line number Diff line number Diff line change
@@ -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")
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions lua/presentation/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
22 changes: 7 additions & 15 deletions lua/solution/parser.lua
Original file line number Diff line number Diff line change
@@ -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")
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 = {}

Expand Down
10 changes: 5 additions & 5 deletions lua/solution/project_types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
15 changes: 9 additions & 6 deletions lua/solution/solution.lua
Original file line number Diff line number Diff line change
@@ -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<string, dotnet_explorer.Project> A map of project GUIDs to Project objects
---@field header SolutionHeader The parsed solution header information
---@field projects_by_guid table<string, Project> A map of project GUIDs to Project objects
---@field nested_projects table<string, string> 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)
Expand All @@ -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
23 changes: 23 additions & 0 deletions lua/solution/solution_header.lua
Original file line number Diff line number Diff line change
@@ -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
20 changes: 13 additions & 7 deletions lua/tree/builder.lua
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down