(lua) types are now guessed for type annotations

This made me to do small adjustments to the tree extractor, and it now
can retrieve fixed positions from the tree. If no node_type name is
specified, it will put all nodes fetched from fixed positions to ["_"]
= values
This commit is contained in:
Daniel Mathiot
2021-08-26 12:28:46 +02:00
parent d90b697104
commit fddd50553e
4 changed files with 68 additions and 31 deletions

View File

@@ -64,7 +64,7 @@ return {
end, end,
}, },
}, },
} },
}, },
template = { template = {
@@ -74,7 +74,7 @@ return {
jsdoc = { jsdoc = {
{ nil, "/* */", { no_results = true } }, { nil, "/* */", { no_results = true } },
{ nil, "/**" }, { nil, "/**" },
{ "class_tag", " * @classdesc" , { before_first_item = { " * ", " * @class" } }}, { "class_tag", " * @classdesc", { before_first_item = { " * ", " * @class" } } },
{ "parameters", " * @param {any} %s " }, { "parameters", " * @param {any} %s " },
{ "return_statement", " * @returns {any} " }, { "return_statement", " * @returns {any} " },
{ nil, " */" }, { nil, " */" },

View File

@@ -21,7 +21,7 @@ local common_function_extractor = function(node)
} }
end end
local extract_from_var = function (node) local extract_from_var = function(node)
local tree = { local tree = {
{ {
retrieve = "first", retrieve = "first",
@@ -31,10 +31,13 @@ local extract_from_var = function (node)
{ retrieve = "first", node_type = "field_expression", extract = true }, { retrieve = "first", node_type = "field_expression", extract = true },
}, },
}, },
{
position = 2,
extract = true,
},
} }
local nodes = neogen.utilities.nodes:matching_nodes_from(node, tree) local nodes = neogen.utilities.nodes:matching_nodes_from(node, tree)
local res = neogen.utilities.extractors:extract_from_matched(nodes) return nodes
return res
end end
return { return {
@@ -67,7 +70,8 @@ return {
["local_variable_declaration|variable_declaration"] = { ["local_variable_declaration|variable_declaration"] = {
["0"] = { ["0"] = {
extract = function(node) extract = function(node)
local res = extract_from_var(node) local nodes = extract_from_var(node)
local res = neogen.utilities.extractors:extract_from_matched(nodes)
return { return {
class_name = res.identifier, class_name = res.identifier,
} }
@@ -79,14 +83,20 @@ return {
["local_variable_declaration|variable_declaration"] = { ["local_variable_declaration|variable_declaration"] = {
["0"] = { ["0"] = {
extract = function(node) extract = function(node)
result = {} local result = {}
local res = extract_from_var(node)
result.type = {} result.type = {}
if res.identifier then
vim.list_extend(result.type, res.identifier) local nodes = extract_from_var(node)
local res = neogen.utilities.extractors:extract_from_matched(nodes, { type = true })
-- We asked the extract_from_var function to find the type node at right assignment.
-- We check if it found it, or else will put `any` in the type
if res["_"] then
vim.list_extend(result.type, res["_"])
else
if res.identifier or res.field_expression then
vim.list_extend(result.type, { "any" })
end end
if res.field_expression then
vim.list_extend(result.type, res.field_expression)
end end
return result return result
end, end,
@@ -112,7 +122,7 @@ return {
{ "vararg", "- @vararg any" }, { "vararg", "- @vararg any" },
{ "return_statement", "- @return any" }, { "return_statement", "- @return any" },
{ "class_name", "- @class any" }, { "class_name", "- @class any" },
{ "type", "- @type any" }, { "type", "- @type %s" },
}, },
}, },
} }

View File

@@ -4,15 +4,24 @@ neogen.utilities.extractors = {
--- Extract the content from each node from data --- Extract the content from each node from data
--- @param _ any self --- @param _ any self
--- @param data table a list of k,v values where k is the node_type and v a table of nodes --- @param data table a list of k,v values where k is the node_type and v a table of nodes
--- @param opts table|nil optional configurations (supported: type = true will get node's type instead of node's text)
--- @return any result the same table as data but with node texts instead --- @return any result the same table as data but with node texts instead
extract_from_matched = function(_, data) extract_from_matched = function(_, data, opts)
opts = opts or {}
local result = {} local result = {}
for k, v in pairs(data) do for k, v in pairs(data) do
local get_type = function(node)
return node:type()
end
local get_text = function(node) local get_text = function(node)
return ts_utils.get_node_text(node)[1] return ts_utils.get_node_text(node)[1]
end end
if opts.type == true then
result[k] = vim.tbl_map(get_type, v)
else
result[k] = vim.tbl_map(get_text, v) result[k] = vim.tbl_map(get_text, v)
end end
end
return result return result
end, end,
} }

View File

@@ -2,17 +2,26 @@ neogen.utilities.nodes = {
--- Get a list of child nodes that match the provided node name --- Get a list of child nodes that match the provided node name
--- @param _ any --- @param _ any
--- @param parent userdata the parent's node --- @param parent userdata the parent's node
--- @param node_name string the node type to search for (if multiple childrens, separate each one with "|") --- @param node_name string|nil the node type to search for (if multiple childrens, separate each one with "|")
--- @return table a table of nodes that matched the name --- @return table a table of nodes that matched the name
matching_child_nodes = function(_, parent, node_name) matching_child_nodes = function(_, parent, node_name)
local results = {} local results = {}
-- Return all nodes if there is no node name
if node_name == nil then
for child in parent:iter_children() do
if child:named() then
table.insert(results, child)
end
end
else
local split = vim.split(node_name, "|", true) local split = vim.split(node_name, "|", true)
for child in parent:iter_children() do for child in parent:iter_children() do
if vim.tbl_contains(split, child:type()) then if vim.tbl_contains(split, child:type()) then
table.insert(results, child) table.insert(results, child)
end end
end end
end
return results return results
end, end,
@@ -20,6 +29,7 @@ neogen.utilities.nodes = {
--- @param parent userdata the parent node --- @param parent userdata the parent node
--- @param tree table a nested table : { retrieve = "all|first", node_type = node_name, subtree = tree } --- @param tree table a nested table : { retrieve = "all|first", node_type = node_name, subtree = tree }
--- If you want to extract the node, do not specify the subtree and instead: extract = true --- If you want to extract the node, do not specify the subtree and instead: extract = true
--- Optional: you can specify position = number instead of retrieve, and it will fetch the child node at position number
--- @param result table the table of results --- @param result table the table of results
--- @return table result a table of k,v where k are node_types and v all matched nodes --- @return table result a table of k,v where k are node_types and v all matched nodes
matching_nodes_from = function(self, parent, tree, result) matching_nodes_from = function(self, parent, tree, result)
@@ -30,20 +40,28 @@ neogen.utilities.nodes = {
local matched = self:matching_child_nodes(parent, subtree.node_type) local matched = self:matching_child_nodes(parent, subtree.node_type)
-- Only keep first matched child node -- Only keep first matched child node
if subtree.retrieve == nil then
if type(subtree.position) == "number" then
matched = { matched[subtree.position] }
else
assert(false, "please require position if retrieve is nil")
end
end
if subtree.retrieve == "first" and #matched ~= 0 then if subtree.retrieve == "first" and #matched ~= 0 then
matched = { matched[1] } matched = { matched[1] }
end end
for _, child in pairs(matched) do for _, child in pairs(matched) do
-- Add to results
if subtree.extract == true then if subtree.extract == true then
if result[subtree.node_type] == nil then local name = subtree.node_type or "_"
result[subtree.node_type] = {} if result[name] == nil then
result[name] = {}
end end
table.insert(result[subtree.node_type], child) table.insert(result[name], child)
else else
local test = self:matching_nodes_from(child, subtree.subtree, result) local nodes = self:matching_nodes_from(child, subtree.subtree, result)
result = vim.tbl_deep_extend("keep", result, test) result = vim.tbl_deep_extend("keep", result, nodes)
end end
end end
end end