From f760c5e7f1f989ab426cd93a439775b6623ac51a Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Fri, 12 May 2023 14:33:09 +0300 Subject: [PATCH 1/8] Fix nil check when env not defined --- lua/laravel/environment/resolver.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index 8518327..bc59a5b 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -6,12 +6,12 @@ local utils = require "laravel.utils" return function(env_check, auto_discovery, default) return function(environments) local env_name = utils.get_env "NVIM_LARAVEL_ENV" - if env_check and env_name ~= "" then + if env_check and env_name ~= nil then local environment = environments[env_name] if environment == nil then utils.notify( "Environment resolver", - { msg = "NVIM_LARAVEL_ENV define as " .. env_name .. " but there is no environment define", level = "ERROR" } + { msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", level = "ERROR" } ) return nil else From a449be8f3655fddf2b963f379fdac04ce4171514 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Fri, 12 May 2023 14:50:23 +0300 Subject: [PATCH 2/8] fix style --- lua/laravel/environment/resolver.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index bc59a5b..4ba33f5 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -11,7 +11,10 @@ return function(env_check, auto_discovery, default) if environment == nil then utils.notify( "Environment resolver", - { msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", level = "ERROR" } + { + msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", + level = "ERROR", + } ) return nil else From e82e550b99cd700c80608b99b5fcc7ca1ab7f735 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Fri, 12 May 2023 15:03:37 +0300 Subject: [PATCH 3/8] more style --- lua/laravel/environment/resolver.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index 4ba33f5..74d4c7d 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -9,13 +9,10 @@ return function(env_check, auto_discovery, default) if env_check and env_name ~= nil then local environment = environments[env_name] if environment == nil then - utils.notify( - "Environment resolver", - { - msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", - level = "ERROR", - } - ) + utils.notify("Environment resolver", { + msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", + level = "ERROR", + }) return nil else return environment From 6c8addea4af6a8e4dc794b1ca1ef7ca32a91df88 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Sat, 3 Jun 2023 14:57:40 +0300 Subject: [PATCH 4/8] add related picker --- lua/laravel/telescope/make_entry.lua | 32 +++++++ lua/laravel/user-commands/laravel.lua | 3 + lua/telescope/_extensions/laravel.lua | 125 ++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) diff --git a/lua/laravel/telescope/make_entry.lua b/lua/laravel/telescope/make_entry.lua index 24edf03..ea87556 100644 --- a/lua/laravel/telescope/make_entry.lua +++ b/lua/laravel/telescope/make_entry.lua @@ -65,4 +65,36 @@ function make_entry.gen_from_laravel_routes(opts) end end +function make_entry.gen_from_model_relations(opts) + opts = opts or {} + + local displayer = entry_display.create { + separator = " ", + hl_chars = { ["["] = "TelescopeBorder", ["]"] = "TelescopeBorder" }, + items = { + { width = 40 }, + { width = 20 }, + { remaining = true }, + }, + } + + local make_display = function(entry) + return displayer { + { entry.value.class_name, "TelescopeResultsConstant" }, + { entry.value.type, "TelescopeResultsIdentifier" }, + { entry.value.extra_information or "", "TelescopeResultsFunction" }, + } + end + + return function(relation) + local class_parts = vim.split(relation.class, "\\") + relation.class_name = class_parts[#class_parts] + return make_entry.set_default_entry_mt({ + value = relation, + ordinal = relation.class_name, + display = make_display, + }, opts) + end +end + return make_entry diff --git a/lua/laravel/user-commands/laravel.lua b/lua/laravel/user-commands/laravel.lua index 1592799..b59fd89 100644 --- a/lua/laravel/user-commands/laravel.lua +++ b/lua/laravel/user-commands/laravel.lua @@ -15,6 +15,9 @@ local commands = { ["test:watch"] = function() return application.run("artisan", { "test" }, { runner = "watch" }) end, + ["related"] = function() + return require("telescope").extensions.laravel.related() + end, } return { diff --git a/lua/telescope/_extensions/laravel.lua b/lua/telescope/_extensions/laravel.lua index eba1c46..2459c33 100644 --- a/lua/telescope/_extensions/laravel.lua +++ b/lua/telescope/_extensions/laravel.lua @@ -10,6 +10,12 @@ local make_entry = require "laravel.telescope.make_entry" local laravel_commands = require "laravel.commands" local laravel_routes = require "laravel.routes" local application = require "laravel.application" +local lsp = require "laravel._lsp" + +---@class ModelRelation +---@field class string +---@field type string +---@field extra_information string --- runs a command from telescope ---@param command LaravelCommand @@ -213,9 +219,128 @@ local routes = function(opts) :find() end +local related = function(opts) + opts = opts or {} + + local file_type = vim.bo.filetype + local lang = vim.treesitter.language.get_lang(file_type) + if lang ~= "php" then + return false + end + + local get_model_class_name = function() + local query = vim.treesitter.query.parse( + lang, + [[ (namespace_definition name: (namespace_name) @namespace) + (class_declaration name: (name) @class) ]] + ) + local tree = vim.treesitter.get_parser():parse()[1]:root() + local bufNr = vim.fn.bufnr() + local class = "" + for id, node, _ in query:iter_captures(tree, bufNr, tree:start(), tree:end_()) do + if query.captures[id] == "class" then + class = class .. "\\" .. vim.treesitter.get_node_text(node, 0) + elseif query.captures[id] == "namespace" then + class = vim.treesitter.get_node_text(node, 0) .. class + end + end + return class + end + + local class = get_model_class_name() + if class ~= "" then + local result, ok = application.run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) + if not ok then + return nil + end + + if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then + return nil + end + + local model_info = vim.fn.json_decode(result.out[1]) + if model_info == nil then + return nil + end + + ---@return ModelRelation|nil + local build_relation = function(info, relation_type) + if next(info) == nil then + return nil + end + if relation_type == "observers" and info["observer"][2] ~= nil then + return { + class = info["observer"][2], + type = relation_type, + extra_information = info["event"], + } + elseif relation_type == "relations" then + return { + class = info["related"], + type = relation_type, + extra_information = info["type"] .. " " .. info["name"], + } + elseif relation_type == "policy" then + return { + class = info[1], + type = relation_type, + extra_information = "", + } + end + return nil + end + + local relations = {} + local types = { "observers", "relations", "policy" } + for _, relation_type in ipairs(types) do + if model_info[relation_type] ~= vim.NIL and #model_info[relation_type] > 0 then + if type(model_info[relation_type]) == "table" and model_info[relation_type][1] ~= vim.NIL then + for _, info in ipairs(model_info[relation_type]) do + local relation = build_relation(info, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + else + local relation = build_relation({ model_info[relation_type] }, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + end + end + + pickers + .new(opts, { + prompt_title = "Related Files", + finder = finders.new_table { + results = relations, + entry_maker = make_entry.gen_from_model_relations(opts), + }, + sorter = conf.prefilter_sorter { + sorter = conf.generic_sorter(opts or {}), + }, + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + local action = vim.fn.split(entry.value.class, "@") + lsp.go_to(action[1], action[2]) + end) + end) + + return true + end, + }) + :find() + end +end + return telescope.register_extension { exports = { commands = commands, routes = routes, + related = related, }, } From c049c6f82be87764f93115b265f2e29daaac83e3 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Sat, 3 Jun 2023 14:59:38 +0300 Subject: [PATCH 5/8] add description to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c28d8c0..98899b8 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ return { keys = { { "la", ":Laravel artisan" }, { "lr", ":Laravel routes" }, + { "lm", ":Laravel related" }, { "lt", function() @@ -192,6 +193,7 @@ You can run `shell` as tinker will open a new terminal `Laravel cache:clear` purge the cache clears the cache for commands. `Laravel commands` shows the list of artisan commands and executes it. `Laravel routes` show the list of routes and goes to the implementation. +`Laravel related` show the list of model related classes, includes observers, policy and relations and goes to the implementation. `Laravel test` runs the application tests `Laravel test:watch` runs the application tests and keep monitoring the changes From e3b759741a25bf4351cdab9c8fd0eb7fa088fbfa Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Sat, 26 Aug 2023 19:46:10 +0300 Subject: [PATCH 6/8] separate picker into separate file and better logs --- lua/telescope/_extensions/laravel.lua | 121 +------------------------ lua/telescope/pickers/related.lua | 125 ++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 119 deletions(-) create mode 100644 lua/telescope/pickers/related.lua diff --git a/lua/telescope/_extensions/laravel.lua b/lua/telescope/_extensions/laravel.lua index 2459c33..846cb46 100644 --- a/lua/telescope/_extensions/laravel.lua +++ b/lua/telescope/_extensions/laravel.lua @@ -1,3 +1,4 @@ +local make_related = require "telescope.pickers.related" local telescope = require "telescope" local actions = require "telescope.actions" local action_state = require "telescope.actions.state" @@ -219,128 +220,10 @@ local routes = function(opts) :find() end -local related = function(opts) - opts = opts or {} - - local file_type = vim.bo.filetype - local lang = vim.treesitter.language.get_lang(file_type) - if lang ~= "php" then - return false - end - - local get_model_class_name = function() - local query = vim.treesitter.query.parse( - lang, - [[ (namespace_definition name: (namespace_name) @namespace) - (class_declaration name: (name) @class) ]] - ) - local tree = vim.treesitter.get_parser():parse()[1]:root() - local bufNr = vim.fn.bufnr() - local class = "" - for id, node, _ in query:iter_captures(tree, bufNr, tree:start(), tree:end_()) do - if query.captures[id] == "class" then - class = class .. "\\" .. vim.treesitter.get_node_text(node, 0) - elseif query.captures[id] == "namespace" then - class = vim.treesitter.get_node_text(node, 0) .. class - end - end - return class - end - - local class = get_model_class_name() - if class ~= "" then - local result, ok = application.run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) - if not ok then - return nil - end - - if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then - return nil - end - - local model_info = vim.fn.json_decode(result.out[1]) - if model_info == nil then - return nil - end - - ---@return ModelRelation|nil - local build_relation = function(info, relation_type) - if next(info) == nil then - return nil - end - if relation_type == "observers" and info["observer"][2] ~= nil then - return { - class = info["observer"][2], - type = relation_type, - extra_information = info["event"], - } - elseif relation_type == "relations" then - return { - class = info["related"], - type = relation_type, - extra_information = info["type"] .. " " .. info["name"], - } - elseif relation_type == "policy" then - return { - class = info[1], - type = relation_type, - extra_information = "", - } - end - return nil - end - - local relations = {} - local types = { "observers", "relations", "policy" } - for _, relation_type in ipairs(types) do - if model_info[relation_type] ~= vim.NIL and #model_info[relation_type] > 0 then - if type(model_info[relation_type]) == "table" and model_info[relation_type][1] ~= vim.NIL then - for _, info in ipairs(model_info[relation_type]) do - local relation = build_relation(info, relation_type) - if relation ~= nil then - table.insert(relations, relation) - end - end - else - local relation = build_relation({ model_info[relation_type] }, relation_type) - if relation ~= nil then - table.insert(relations, relation) - end - end - end - end - - pickers - .new(opts, { - prompt_title = "Related Files", - finder = finders.new_table { - results = relations, - entry_maker = make_entry.gen_from_model_relations(opts), - }, - sorter = conf.prefilter_sorter { - sorter = conf.generic_sorter(opts or {}), - }, - attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - vim.schedule(function() - local action = vim.fn.split(entry.value.class, "@") - lsp.go_to(action[1], action[2]) - end) - end) - - return true - end, - }) - :find() - end -end - return telescope.register_extension { exports = { commands = commands, routes = routes, - related = related, + related = make_related(pickers, application, lsp, make_entry, finders, conf, actions, action_state), }, } diff --git a/lua/telescope/pickers/related.lua b/lua/telescope/pickers/related.lua new file mode 100644 index 0000000..806cc43 --- /dev/null +++ b/lua/telescope/pickers/related.lua @@ -0,0 +1,125 @@ +local make_related = function(pickers, application, lsp, make_entry, finders, conf, actions, action_state) + local utils = require "laravel.utils" + return function(opts) + opts = opts or {} + + local file_type = vim.bo.filetype + local lang = vim.treesitter.language.get_lang(file_type) + if lang ~= "php" then + return false + end + + local get_model_class_name = function() + local query = vim.treesitter.query.parse( + lang, + [[ (namespace_definition name: (namespace_name) @namespace) + (class_declaration name: (name) @class) ]] + ) + local tree = vim.treesitter.get_parser():parse()[1]:root() + local bufNr = vim.fn.bufnr() + local class = "" + for id, node, _ in query:iter_captures(tree, bufNr, tree:start(), tree:end_()) do + if query.captures[id] == "class" then + class = class .. "\\" .. vim.treesitter.get_node_text(node, 0) + elseif query.captures[id] == "namespace" then + class = vim.treesitter.get_node_text(node, 0) .. class + end + end + return class + end + + local class = get_model_class_name() + if class ~= "" then + local result, ok = application.run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) + if not ok then + utils.notify("Artisan", { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" }) + return nil + end + + if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then + utils.notify("Artisan", { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" }) + return nil + end + + local model_info = vim.fn.json_decode(result.out[1]) + if model_info == nil then + utils.notify("Artisan", { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" }) + return nil + end + + ---@return ModelRelation|nil + local build_relation = function(info, relation_type) + if next(info) == nil then + return nil + end + if relation_type == "observers" and info["observer"][2] ~= nil then + return { + class = info["observer"][2], + type = relation_type, + extra_information = info["event"], + } + elseif relation_type == "relations" then + return { + class = info["related"], + type = relation_type, + extra_information = info["type"] .. " " .. info["name"], + } + elseif relation_type == "policy" then + return { + class = info[1], + type = relation_type, + extra_information = "", + } + end + return nil + end + + local relations = {} + local types = { "observers", "relations", "policy" } + for _, relation_type in ipairs(types) do + if model_info[relation_type] ~= vim.NIL and #model_info[relation_type] > 0 then + if type(model_info[relation_type]) == "table" and model_info[relation_type][1] ~= vim.NIL then + for _, info in ipairs(model_info[relation_type]) do + local relation = build_relation(info, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + else + local relation = build_relation({ model_info[relation_type] }, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + end + end + + pickers + .new(opts, { + prompt_title = "Related Files", + finder = finders.new_table { + results = relations, + entry_maker = make_entry.gen_from_model_relations(opts), + }, + sorter = conf.prefilter_sorter { + sorter = conf.generic_sorter(opts or {}), + }, + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + local action = vim.fn.split(entry.value.class, "@") + lsp.go_to(action[1], action[2]) + end) + end) + + return true + end, + }) + :find() + end + end +end + +return make_related; From 4aec90d94b5cc67749dda288a779164a455dc892 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Sat, 26 Aug 2023 19:48:19 +0300 Subject: [PATCH 7/8] fix linter issues --- lua/telescope/pickers/related.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lua/telescope/pickers/related.lua b/lua/telescope/pickers/related.lua index 806cc43..ec7aff3 100644 --- a/lua/telescope/pickers/related.lua +++ b/lua/telescope/pickers/related.lua @@ -32,18 +32,27 @@ local make_related = function(pickers, application, lsp, make_entry, finders, co if class ~= "" then local result, ok = application.run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) if not ok then - utils.notify("Artisan", { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" }) + utils.notify( + "Artisan", + { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" } + ) return nil end if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then - utils.notify("Artisan", { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" }) + utils.notify( + "Artisan", + { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + ) return nil end local model_info = vim.fn.json_decode(result.out[1]) if model_info == nil then - utils.notify("Artisan", { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" }) + utils.notify( + "Artisan", + { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + ) return nil end @@ -122,4 +131,4 @@ local make_related = function(pickers, application, lsp, make_entry, finders, co end end -return make_related; +return make_related From be55b707eb9356d86b4d041e979c2647a76e5277 Mon Sep 17 00:00:00 2001 From: Deniss Levskoi Date: Sat, 26 Aug 2023 19:49:44 +0300 Subject: [PATCH 8/8] more style fixes --- lua/telescope/pickers/related.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/telescope/pickers/related.lua b/lua/telescope/pickers/related.lua index ec7aff3..860578e 100644 --- a/lua/telescope/pickers/related.lua +++ b/lua/telescope/pickers/related.lua @@ -13,7 +13,7 @@ local make_related = function(pickers, application, lsp, make_entry, finders, co local query = vim.treesitter.query.parse( lang, [[ (namespace_definition name: (namespace_name) @namespace) - (class_declaration name: (name) @class) ]] + (class_declaration name: (name) @class) ]] ) local tree = vim.treesitter.get_parser():parse()[1]:root() local bufNr = vim.fn.bufnr()