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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ return {
keys = {
{ "<leader>la", ":Laravel artisan<cr>" },
{ "<leader>lr", ":Laravel routes<cr>" },
{ "<leader>lm", ":Laravel related<cr>" },
{
"<leader>lt",
function()
Expand Down Expand Up @@ -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

Expand Down
32 changes: 32 additions & 0 deletions lua/laravel/telescope/make_entry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions lua/laravel/user-commands/laravel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 8 additions & 0 deletions lua/telescope/_extensions/laravel.lua
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The luacheck is failing due wrong indent. please fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do, it will take some time as there are some personal things I am going through and work has piled up as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adalessa i am back and will do the changes soon

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adalessa fixes are pushed, please check.

Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -10,6 +11,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
Expand Down Expand Up @@ -217,5 +224,6 @@ return telescope.register_extension {
exports = {
commands = commands,
routes = routes,
related = make_related(pickers, application, lsp, make_entry, finders, conf, actions, action_state),
},
}
134 changes: 134 additions & 0 deletions lua/telescope/pickers/related.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
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", "<cr>", 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