summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Emmerich <tandanu@deadlybossmods.com>2024-01-28 13:08:48 +0100
committerPaul Emmerich <tandanu@deadlybossmods.com>2024-01-28 13:08:48 +0100
commit1a1e671b0abd0380d4bd02f7adabda023bda9a64 (patch)
tree67b7e7ee059a1fcdc11fd44e76a6ceb079a2a8dd
parent9185dfad1286942b4914657e4c0e9ad28cb2aaa8 (diff)
downloadlua-language-server-1a1e671b0abd0380d4bd02f7adabda023bda9a64.zip
Add group param for luadoc generated by plugins
This allows binding multiple generated luadoc annotations to a single node easily by explicitly specifying their bind group.
-rw-r--r--script/parser/luadoc.lua8
-rw-r--r--script/plugins/astHelper.lua23
-rw-r--r--test/plugins/ast/test.lua60
3 files changed, 82 insertions, 9 deletions
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 227808a0..c59bc5c1 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -2002,7 +2002,10 @@ local function bindDocs(state)
state.ast.docs.groups[#state.ast.docs.groups+1] = binded
end
binded[#binded+1] = doc
- if isTailComment(text, doc) then
+ if doc.specialBindGroup then
+ bindDocWithSources(sources, doc.specialBindGroup)
+ binded = nil
+ elseif isTailComment(text, doc) and doc.type ~= "doc.class" and doc.type ~= "doc.field" then
bindDocWithSources(sources, binded)
binded = nil
else
@@ -2130,7 +2133,7 @@ local function luadoc(state)
end
return {
- buildAndBindDoc = function (ast, src, comment)
+ buildAndBindDoc = function (ast, src, comment, group)
local doc = buildLuaDoc(comment)
if doc then
local pluginDocs = ast.state.pluginDocs or {}
@@ -2138,6 +2141,7 @@ return {
doc.special = src
doc.originalComment = comment
doc.virtual = true
+ doc.specialBindGroup = group
ast.state.pluginDocs = pluginDocs
return doc
end
diff --git a/script/plugins/astHelper.lua b/script/plugins/astHelper.lua
index 506f5e92..bfe2dd27 100644
--- a/script/plugins/astHelper.lua
+++ b/script/plugins/astHelper.lua
@@ -23,14 +23,27 @@ end
---@param ast parser.object
---@param source parser.object local/global variable
---@param classname string
-function _M.addClassDoc(ast, source, classname)
+---@param group table?
+function _M.addClassDoc(ast, source, classname, group)
+ return _M.addDoc(ast, source, "class", classname, group)
+end
+
+--- give the local/global variable a luadoc comment
+---@param ast parser.object
+---@param source parser.object local/global variable
+---@param key string
+---@param value string
+---@param group table?
+function _M.addDoc(ast, source, key, value, group)
if source.type ~= 'local' and not guide.isGlobal(source) then
return false
end
- --TODO fileds
- --TODO callers
- local comment = _M.buildComment("class", classname, source.start - 1)
- return luadoc.buildAndBindDoc(ast, source, comment)
+ local comment = _M.buildComment(key, value, source.start - 1)
+ local doc = luadoc.buildAndBindDoc(ast, source, comment, group)
+ if group then
+ group[#group+1] = doc
+ end
+ return doc
end
---remove `ast` function node `index` arg, the variable will be the function local variable
diff --git a/test/plugins/ast/test.lua b/test/plugins/ast/test.lua
index 95e87694..a01b9e2e 100644
--- a/test/plugins/ast/test.lua
+++ b/test/plugins/ast/test.lua
@@ -3,11 +3,14 @@ local guide = require 'parser.guide'
local helper = require 'plugins.astHelper'
---@diagnostic disable: await-in-sync
-local function TestPlugin(script, plugin, checker)
+---@param ... function checkers
+local function TestPlugin(script, plugin, ...)
local state = parser.compile(script, "Lua", "Lua 5.4")
state.ast = plugin(TESTURI, state.ast) or state.ast
parser.luadoc(state)
- checker(state)
+ for i = 1, select('#', ...) do
+ select(i, ...)(state)
+ end
end
local function isDocClass(ast)
@@ -62,6 +65,47 @@ local function TestSelfIsClass(state, next)
end)
end
+local function TestAHasField(state, next)
+ local foundFields = false
+ local cb = function (source)
+ if not source.bindDocs or not source.bindDocs[1].class or source.bindDocs[1].class[1] ~= "A" then
+ return
+ end
+ assert(#source.bindDocs == 1)
+ assert(#source.bindDocs[1].fields >= 2)
+ assert(source.bindDocs[1].fields[1].field[1] == "x")
+ assert(source.bindDocs[1].fields[2].field[1] == "y")
+ foundFields = true
+ end
+ guide.eachSourceType(state.ast, "local", cb)
+ guide.eachSourceType(state.ast, "setglobal", cb)
+ assert(foundFields)
+end
+
+local function plugin_AddMultipleDocs(uri, ast)
+ guide.eachSourceType(ast, "call", function(source)
+ local node = source.node
+ if guide.getKeyName(node) ~= 'Class' then
+ return
+ end
+ local wants = {
+ ['local'] = true,
+ ['setglobal'] = true
+ }
+ local classnameNode = guide.getParentTypes(source, wants)
+ if not classnameNode then
+ return
+ end
+ local classname = guide.getKeyName(classnameNode)
+ if classname then
+ local group = {}
+ helper.addClassDoc(ast, classnameNode, classname, group)
+ helper.addDoc(ast, classnameNode, "field", "x number", group)
+ helper.addDoc(ast, classnameNode, "field", "y string", group)
+ end
+ end)
+end
+
local function TestPlugin1(script)
TestPlugin(script, plugin_AddClass, TestAIsClass)
end
@@ -70,6 +114,10 @@ local function TestPlugin2(script)
TestPlugin(script, plugin_AddClassAtParam, TestSelfIsClass)
end
+local function TestPlugin3(script)
+ TestPlugin(script, plugin_AddMultipleDocs, TestAIsClass, TestAHasField)
+end
+
TestPlugin1 [[
local A = Class(function() end)
]]
@@ -86,4 +134,12 @@ TestPlugin2 [[
function ctor(self) end
]]
+TestPlugin3 [[
+ local A = Class()
+]]
+
+TestPlugin3 [[
+ A = Class()
+]]
+
require 'plugins.ast.helper'