summaryrefslogtreecommitdiff
path: root/script/vm/runner.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-25 01:23:50 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-25 01:23:50 +0800
commit125d943a7faec97b7169d0088a12ba6a44a14c16 (patch)
tree40b5a7d8d55571334c5ddecd302fe89c34969c84 /script/vm/runner.lua
parent163da759468164bc020fb4801bf06f1a190af7ad (diff)
downloadlua-language-server-125d943a7faec97b7169d0088a12ba6a44a14c16.zip
add `---@cast`
Diffstat (limited to 'script/vm/runner.lua')
-rw-r--r--script/vm/runner.lua66
1 files changed, 64 insertions, 2 deletions
diff --git a/script/vm/runner.lua b/script/vm/runner.lua
index 19233964..75610ee5 100644
--- a/script/vm/runner.lua
+++ b/script/vm/runner.lua
@@ -13,15 +13,16 @@ mt.__index = mt
mt.index = 1
---@class parser.object
----@field _hasSorted boolean
+---@field _casts parser.object[]
---@class vm.runner.step
----@field type 'truthy' | 'falsy' | 'as' | 'add' | 'remove' | 'object' | 'save' | 'push' | 'merge'
+---@field type 'truthy' | 'falsy' | 'as' | 'add' | 'remove' | 'object' | 'save' | 'push' | 'merge' | 'cast'
---@field pos integer
---@field order? integer
---@field node? vm.node
---@field object? parser.object
---@field name? string
+---@field cast? parser.object
---@field tag? string
---@field copy? boolean
---@field new? boolean
@@ -250,21 +251,58 @@ function mt:_compileBlock(block)
end
end
+---@return parser.object[]
+function mt:_getCasts()
+ local root = guide.getRoot(self.loc)
+ if not root._casts then
+ root._casts = {}
+ local docs = root.docs
+ for _, doc in ipairs(docs) do
+ if doc.type == 'doc.cast' and doc.loc then
+ root._casts[#root._casts+1] = doc
+ end
+ end
+ end
+ return root._casts
+end
+
function mt:_preCompile()
+ local startPos = self.loc.start
+ local finishPos = 0
+
for _, ref in ipairs(self.loc.ref) do
self.steps[#self.steps+1] = {
type = 'object',
object = ref,
pos = ref.range or ref.start,
}
+ if ref.start > finishPos then
+ finishPos = ref.start
+ end
local block = guide.getParentBlock(ref)
self:_compileBlock(block)
end
+
for i, step in ipairs(self.steps) do
if step.type ~= 'object' then
step.order = i
end
end
+
+ local casts = self:_getCasts()
+ for _, cast in ipairs(casts) do
+ if cast.loc[1] == self.loc[1]
+ and cast.start > startPos
+ and cast.finish < finishPos
+ and guide.getLocal(self.loc, self.loc[1], cast.start) == self.loc then
+ self.steps[#self.steps+1] = {
+ type = 'cast',
+ cast = cast,
+ pos = cast.start,
+ }
+ end
+ end
+
table.sort(self.steps, function (a, b)
if a.pos == b.pos then
return (a.order or 0) < (b.order or 0)
@@ -363,6 +401,30 @@ function mt:launch(callback)
topNode = node
elseif step.type == 'merge' then
node:merge(step.ref2.node)
+ elseif step.type == 'cast' then
+ topNode = node:copy()
+ for _, cast in ipairs(step.cast.casts) do
+ if cast.mode == '+' then
+ if cast.optional then
+ topNode:addOptional()
+ end
+ if cast.extends then
+ topNode:merge(vm.compileNode(cast.extends))
+ end
+ elseif cast.mode == '-' then
+ if cast.optional then
+ topNode:removeOptional()
+ end
+ if cast.extends then
+ topNode:removeNode(vm.compileNode(cast.extends))
+ end
+ else
+ if cast.extends then
+ topNode:clear()
+ topNode:merge(vm.compileNode(cast.extends))
+ end
+ end
+ end
end
end
end