summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/files.lua17
-rw-r--r--script/parser/guide.lua34
-rw-r--r--script/parser/init.lua2
-rw-r--r--script/parser/luadoc.lua200
-rw-r--r--script/plugins/astHelper.lua66
5 files changed, 234 insertions, 85 deletions
diff --git a/script/files.lua b/script/files.lua
index 62f01136..7998ceed 100644
--- a/script/files.lua
+++ b/script/files.lua
@@ -655,6 +655,17 @@ function m.compileStateAsync(uri, callback)
end)
end
+local function pluginOnTransformAst(uri, state)
+ local plugin = require 'plugin'
+ ---TODO: maybe deepcopy astNode
+ local suc, result = plugin.dispatch('OnTransformAst', uri, state.ast)
+ if not suc then
+ return state
+ end
+ state.ast = result
+ return state
+end
+
---@param uri uri
---@return parser.state?
function m.compileState(uri)
@@ -700,6 +711,12 @@ function m.compileState(uri)
return nil
end
+ state = pluginOnTransformAst(uri, state)
+ if not state then
+ log.error('pluginOnTransformAst failed! discard the file state')
+ return nil
+ end
+
m.compileStateThen(state, file)
return state
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index e7eb3751..103a8cd5 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -419,6 +419,22 @@ function m.getParentType(obj, want)
error('guide.getParentType overstack')
end
+--- 寻找所在父类型
+---@param obj parser.object
+---@return parser.object?
+function m.getParentTypes(obj, wants)
+ for _ = 1, 10000 do
+ obj = obj.parent
+ if not obj then
+ return nil
+ end
+ if wants[obj.type] then
+ return obj
+ end
+ end
+ error('guide.getParentTypes overstack')
+end
+
--- 寻找根区块
---@param obj parser.object
---@return parser.object
@@ -1289,4 +1305,22 @@ function m.isParam(source)
return true
end
+---@param source parser.object
+---@param index integer
+---@return parser.object?
+function m.getParam(source, index)
+ if source.type == 'call' then
+ local args = source.args
+ assert(args.type == 'callargs', 'call.args type is\'t callargs')
+ return args[index]
+ elseif source.type == 'callargs' then
+ return source[index]
+ elseif source.type == 'function' then
+ local args = source.args
+ assert(args.type == 'funcargs', 'function.args type is\'t callargs')
+ return args[index]
+ end
+ return nil
+end
+
return m
diff --git a/script/parser/init.lua b/script/parser/init.lua
index bc004f77..9848ce00 100644
--- a/script/parser/init.lua
+++ b/script/parser/init.lua
@@ -2,7 +2,7 @@ local api = {
compile = require 'parser.compile',
lines = require 'parser.lines',
guide = require 'parser.guide',
- luadoc = require 'parser.luadoc',
+ luadoc = require 'parser.luadoc'.luadoc,
}
return api
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index c022adcb..332211e1 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -291,7 +291,7 @@ local function parseTable(parent)
needCloseParen = true
end
field.name = parseName('doc.field.name', field)
- or parseIndexField(field)
+ or parseIndexField(field)
if not field.name then
pushWarning {
type = 'LUADOC_MISS_FIELD_NAME',
@@ -401,7 +401,7 @@ local function parseTypeUnitFunction(parent)
parent = typeUnit,
}
arg.name = parseName('doc.type.arg.name', arg)
- or parseDots('doc.type.arg.name', arg)
+ or parseDots('doc.type.arg.name', arg)
if not arg.name then
pushWarning {
type = 'LUADOC_MISS_ARG_NAME',
@@ -442,7 +442,7 @@ local function parseTypeUnitFunction(parent)
local name
try(function ()
local returnName = parseName('doc.return.name', typeUnit)
- or parseDots('doc.return.name', typeUnit)
+ or parseDots('doc.return.name', typeUnit)
if not returnName then
return false
end
@@ -646,15 +646,15 @@ end
function parseTypeUnit(parent)
local result = parseFunction(parent)
- or parseTable(parent)
- or parseString(parent)
- or parseCode(parent)
- or parseInteger(parent)
- or parseBoolean(parent)
- or parseParen(parent)
+ or parseTable(parent)
+ or parseString(parent)
+ or parseCode(parent)
+ or parseInteger(parent)
+ or parseBoolean(parent)
+ or parseParen(parent)
if not result then
result = parseName('doc.type.name', parent)
- or parseDots('doc.type.name', parent)
+ or parseDots('doc.type.name', parent)
if not result then
return nil
end
@@ -827,7 +827,7 @@ local docSwitch = util.switch()
while true do
local extend = parseName('doc.extends.name', result)
- or parseTable(result)
+ or parseTable(result)
if not extend then
pushWarning {
type = 'LUADOC_MISS_CLASS_EXTENDS_NAME',
@@ -896,7 +896,7 @@ local docSwitch = util.switch()
type = 'doc.param',
}
result.param = parseName('doc.param.name', result)
- or parseDots('doc.param.name', result)
+ or parseDots('doc.param.name', result)
if not result.param then
pushWarning {
type = 'LUADOC_MISS_PARAM_NAME',
@@ -951,7 +951,7 @@ local docSwitch = util.switch()
dots.parent = docType
else
docType.name = parseName('doc.return.name', docType)
- or parseDots('doc.return.name', docType)
+ or parseDots('doc.return.name', docType)
end
result.returns[#result.returns+1] = docType
if not checkToken('symbol', ',', 1) then
@@ -990,7 +990,7 @@ local docSwitch = util.switch()
return false
end)
result.field = parseName('doc.field.name', result)
- or parseIndexField(result)
+ or parseIndexField(result)
if not result.field then
pushWarning {
type = 'LUADOC_MISS_FIELD_NAME',
@@ -1514,7 +1514,7 @@ end
local function buildLuaDoc(comment)
local text = comment.text
local startPos = (comment.type == 'comment.short' and text:match '^%-%s*@()')
- or (comment.type == 'comment.long' and text:match '^@()')
+ or (comment.type == 'comment.long' and text:match '^@()')
if not startPos then
return {
type = 'doc.comment',
@@ -1921,6 +1921,14 @@ local function bindDocWithSources(sources, binded)
bindGeneric(binded)
bindCommentsAndFields(binded)
bindReturnIndex(binded)
+
+ -- doc is special node
+ if lastDoc.special then
+ if bindDoc(lastDoc.special, binded) then
+ return
+ end
+ end
+
local row = guide.rowColOf(lastDoc.finish)
local suc = bindDocsBetween(sources, binded, guide.positionOf(row, 0), lastDoc.start)
if not suc then
@@ -1950,13 +1958,14 @@ local function bindDocs(state)
binded = {}
state.ast.docs.groups[#state.ast.docs.groups+1] = binded
end
- binded[#binded+1] = doc
+ binded[#binded+1] = doc
if isTailComment(text, doc) then
bindDocWithSources(sources, binded)
binded = nil
else
local nextDoc = state.ast.docs[i+1]
- if not isNextLine(doc, nextDoc) then
+ if nextDoc and nextDoc.special
+ or not isNextLine(doc, nextDoc) then
bindDocWithSources(sources, binded)
binded = nil
end
@@ -1974,8 +1983,8 @@ local function findTouch(state, doc)
local pos = guide.positionToOffset(state, doc.originalComment.start)
for i = pos - 2, 1, -1 do
local c = text:sub(i, i)
- if c == '\r'
- or c == '\n' then
+ if c == '\r'
+ or c == '\n' then
break
elseif c ~= ' '
and c ~= '\t' then
@@ -1985,82 +1994,105 @@ local function findTouch(state, doc)
end
end
-return function (state)
- local ast = state.ast
- local comments = state.comms
- table.sort(comments, function (a, b)
- return a.start < b.start
- end)
- ast.docs = {
- type = 'doc',
- parent = ast,
- groups = {},
- }
-
- pushWarning = function (err)
- local errs = state.errs
- if err.finish < err.start then
- err.finish = err.start
+return {
+ buildAndBindDoc = function (ast, src, comment)
+ local doc = buildLuaDoc(comment)
+ if doc then
+ local pluginDocs = ast.state.pluginDocs or {}
+ pluginDocs[#pluginDocs+1] = doc
+ doc.special = src
+ doc.originalComment = comment
+ ast.state.pluginDocs = pluginDocs
+ return true
end
- local last = errs[#errs]
- if last then
- if last.start <= err.start and last.finish >= err.finish then
- return
+ return false
+ end,
+ luadoc = function (state)
+ local ast = state.ast
+ local comments = state.comms
+ table.sort(comments, function (a, b)
+ return a.start < b.start
+ end)
+ ast.docs = ast.docs or {
+ type = 'doc',
+ parent = ast,
+ groups = {},
+ }
+
+ pushWarning = function (err)
+ local errs = state.errs
+ if err.finish < err.start then
+ err.finish = err.start
+ end
+ local last = errs[#errs]
+ if last then
+ if last.start <= err.start and last.finish >= err.finish then
+ return
+ end
end
+ err.level = err.level or 'Warning'
+ errs[#errs+1] = err
+ return err
end
- err.level = err.level or 'Warning'
- errs[#errs+1] = err
- return err
- end
- Lines = state.lines
+ Lines = state.lines
- local ci = 1
- NextComment = function (offset, peek)
- local comment = comments[ci + (offset or 0)]
- if not peek then
- ci = ci + 1 + (offset or 0)
+ local ci = 1
+ NextComment = function (offset, peek)
+ local comment = comments[ci + (offset or 0)]
+ if not peek then
+ ci = ci + 1 + (offset or 0)
+ end
+ return comment
end
- return comment
- end
- local function insertDoc(doc, comment)
- ast.docs[#ast.docs+1] = doc
- doc.parent = ast.docs
- if ast.start > doc.start then
- ast.start = doc.start
- end
- if ast.finish < doc.finish then
- ast.finish = doc.finish
- end
- doc.originalComment = comment
- if comment.type == 'comment.long' then
- findTouch(state, doc)
+ local function insertDoc(doc, comment)
+ ast.docs[#ast.docs+1] = doc
+ doc.parent = ast.docs
+ if ast.start > doc.start then
+ ast.start = doc.start
+ end
+ if ast.finish < doc.finish then
+ ast.finish = doc.finish
+ end
+ doc.originalComment = comment
+ if comment.type == 'comment.long' then
+ findTouch(state, doc)
+ end
end
- end
- while true do
- local comment = NextComment()
- if not comment then
- break
- end
- lockResume = false
- local doc, rests = buildLuaDoc(comment)
- if doc then
- insertDoc(doc, comment)
- if rests then
- for _, rest in ipairs(rests) do
- insertDoc(rest, comment)
+ while true do
+ local comment = NextComment()
+ if not comment then
+ break
+ end
+ lockResume = false
+ local doc, rests = buildLuaDoc(comment)
+ if doc then
+ insertDoc(doc, comment)
+ if rests then
+ for _, rest in ipairs(rests) do
+ insertDoc(rest, comment)
+ end
end
end
end
- end
+
+ if ast.state.pluginDocs then
+ for i, doc in ipairs(ast.state.pluginDocs) do
+ insertDoc(doc, doc.originalComment)
+ end
+ table.sort(ast.docs, function (a, b)
+ return a.start < b.start
+ end)
+ end
- ast.docs.start = ast.start
- ast.docs.finish = ast.finish
+ ast.docs.start = ast.start
+ ast.docs.finish = ast.finish
- if #ast.docs == 0 then
- return
- end
+ if #ast.docs == 0 then
+ return
+ end
- bindDocs(state)
-end
+ bindDocs(state)
+ end
+} \ No newline at end of file
diff --git a/script/plugins/astHelper.lua b/script/plugins/astHelper.lua
new file mode 100644
index 00000000..6f303c79
--- /dev/null
+++ b/script/plugins/astHelper.lua
@@ -0,0 +1,66 @@
+local luadoc = require 'parser.luadoc'
+local ssub = require 'core.substring'
+local guide = require 'parser.guide'
+local _M = {}
+
+function _M.buildComment(t, value)
+ return {
+ type = 'comment.short',
+ start = 1,
+ finish = 1,
+ text = "-@" .. t .. " " .. value,
+ }
+end
+
+function _M.InsertDoc(ast, comm)
+ local comms = ast.state.comms or {}
+ comms[#comms+1] = comm
+ ast.state.comms = comms
+end
+
+--- give the local/global variable add doc.class
+---@param ast parser.object
+---@param source parser.object local/global variable
+---@param classname string
+function _M.addClassDoc(ast, source, classname)
+ if source.type ~= 'local' and not guide.isGlobal(source) then
+ return false
+ end
+ --TODO fileds
+ --TODO callers
+ local comment = _M.buildComment("class", classname)
+ comment.start = source.start - 1
+ comment.finish = comment.start
+
+ return luadoc.buildAndBindDoc(ast, source, comment)
+end
+
+---remove `ast` function node `index` arg, the variable will be the function local variable
+---@param source parser.object function node
+---@param index integer
+---@return parser.object?
+function _M.removeArg(source, index)
+ if source.type == 'function' then
+ local arg = table.remove(source.args, index)
+ if not arg then
+ return nil
+ end
+ arg.parent = arg.parent.parent
+ return arg
+ end
+ return nil
+end
+
+--- 把特定函数当成构造函数,`index` 参数是self
+---@param classname string
+---@param source parser.object function node
+---@param index integer
+function _M.addClassDocAtParam(ast, classname, source, index)
+ local arg = _M.removeArg(source, index)
+ if arg then
+ return _M.addClassDoc(ast, arg, classname)
+ end
+ return false
+end
+
+return _M