summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-10-20 16:58:57 +0800
committer最萌小汐 <sumneko@hotmail.com>2020-10-20 16:58:57 +0800
commit135f38d1b4f4d7b989f738bead5b59bdaf58f7e1 (patch)
tree0057af75111840f34da65a43cd8df8ce92f63f85
parentbb319039fdf41326f23ef0c7288123889434b0a8 (diff)
downloadlua-language-server-135f38d1b4f4d7b989f738bead5b59bdaf58f7e1.zip
luadoc的第一步
-rw-r--r--script-beta/config.lua3
-rw-r--r--script-beta/core/find-source.lua5
-rw-r--r--script-beta/core/reference.lua4
-rw-r--r--script-beta/files.lua11
-rw-r--r--script-beta/parser/guide.lua117
-rw-r--r--script-beta/parser/luadoc.lua12
-rw-r--r--script-beta/provider/provider.lua3
-rw-r--r--script-beta/vm/eachRef.lua2
-rw-r--r--script-beta/vm/getDocs.lua58
-rw-r--r--script-beta/vm/guideInterface.lua5
-rw-r--r--script-beta/vm/init.lua1
-rw-r--r--test-beta/references/init.lua23
12 files changed, 218 insertions, 26 deletions
diff --git a/script-beta/config.lua b/script-beta/config.lua
index bc6bf863..fce52234 100644
--- a/script-beta/config.lua
+++ b/script-beta/config.lua
@@ -142,6 +142,9 @@ local ConfigTemplate = {
color = {
mode = {'Semantic', String},
},
+ luadoc = {
+ enable = {true, Boolean},
+ },
plugin = {
enable = {false, Boolean},
path = {'.vscode/lua-plugin/*.lua', String},
diff --git a/script-beta/core/find-source.lua b/script-beta/core/find-source.lua
index 4788d539..32de102c 100644
--- a/script-beta/core/find-source.lua
+++ b/script-beta/core/find-source.lua
@@ -4,9 +4,10 @@ return function (ast, offset, accept)
local len = math.huge
local result
guide.eachSourceContain(ast.ast, offset, function (source)
- if source.finish - source.start < len and accept[source.type] then
+ local start, finish = guide.getStartFinish(source)
+ if finish - start < len and accept[source.type] then
result = source
- len = source.finish - source.start
+ len = finish - start
end
end)
return result
diff --git a/script-beta/core/reference.lua b/script-beta/core/reference.lua
index 56580d0b..8bec1836 100644
--- a/script-beta/core/reference.lua
+++ b/script-beta/core/reference.lua
@@ -48,6 +48,10 @@ local accept = {
['setglobal'] = true,
['getglobal'] = true,
['function'] = true,
+
+ ['doc.type.name'] = true,
+ ['doc.class.name'] = true,
+ ['doc.extends.name'] = true,
}
return function (uri, offset)
diff --git a/script-beta/files.lua b/script-beta/files.lua
index 9e72ddd8..800d6d4d 100644
--- a/script-beta/files.lua
+++ b/script-beta/files.lua
@@ -234,6 +234,9 @@ function m.getAst(uri)
state.uri = file.uri
state.ast.uri = file.uri
file.ast = state
+ if config.config.luadoc.enable then
+ parser:luadoc(state)
+ end
else
log.error(err)
file.ast = false
@@ -348,6 +351,14 @@ function m.onWatch(ev, ...)
end
end
+function m.flushCache()
+ for _, file in pairs(m.fileMap) do
+ file.cacheActiveTime = math.huge
+ file.ast = nil
+ file.cache = {}
+ end
+end
+
local function init()
--TODO 可以清空文件缓存,之后看要不要启用吧
--timer.loop(10, function ()
diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua
index afd763bf..1ae96097 100644
--- a/script-beta/parser/guide.lua
+++ b/script-beta/parser/guide.lua
@@ -44,7 +44,7 @@ local breakBlockTypes = {
}
m.childMap = {
- ['main'] = {'#'},
+ ['main'] = {'#', 'docs'},
['repeat'] = {'#', 'filter'},
['while'] = {'filter', '#'},
['in'] = {'keys', '#'},
@@ -75,7 +75,21 @@ m.childMap = {
['getfield'] = {'node', 'field'},
['list'] = {'#'},
['binary'] = {1, 2},
- ['unary'] = {1}
+ ['unary'] = {1},
+
+ ['doc'] = {'#'},
+ ['doc.class'] = {'class', 'extends'},
+ ['doc.type'] = {'#types', '#enums'},
+ ['doc.alias'] = {'alias', 'extends'},
+ ['doc.param'] = {'param', 'extends'},
+ ['doc.return'] = {'#returns'},
+ ['doc.field'] = {'field', 'extends'},
+ ['doc.generic'] = {'#generics'},
+ ['doc.generic.object'] = {'generic', 'extends'},
+ ['doc.vararg'] = {'vararg'},
+ ['doc.type.table'] = {'key', 'value'},
+ ['doc.type.function'] = {'#args', '#returns'},
+ ['doc.overload'] = {'overload'},
}
m.actionMap = {
@@ -327,24 +341,70 @@ function m.getLabel(block, name)
error('guide.getLocal overstack')
end
+function m.getStartFinish(source)
+ local start = source.start
+ local finish = source.finish
+ if not start then
+ local first = source[1]
+ if not first then
+ return nil, nil
+ end
+ local last = source[#source]
+ start = first.start
+ finish = last.finish
+ end
+ return start, finish
+end
+
+function m.getRange(source)
+ local start = source.vstart or source.start
+ local finish = source.range or source.finish
+ if not start then
+ local first = source[1]
+ if not first then
+ return nil, nil
+ end
+ local last = source[#source]
+ start = first.vstart or first.start
+ finish = last.range or last.finish
+ end
+ return start, finish
+end
+
--- 判断source是否包含offset
function m.isContain(source, offset)
- return source.start <= offset and source.finish >= offset - 1
+ local start, finish = m.getStartFinish(source)
+ if not start then
+ return false
+ end
+ return start <= offset and finish >= offset - 1
end
--- 判断offset在source的影响范围内
---
--- 主要针对赋值等语句时,key包含value
function m.isInRange(source, offset)
- return (source.vstart or source.start) <= offset and (source.range or source.finish) >= offset - 1
+ local start, finish = m.getRange(source)
+ if not start then
+ return false
+ end
+ return start <= offset and finish >= offset - 1
end
-function m.isBetween(source, start, finish)
- return source.start <= finish and source.finish >= start - 1
+function m.isBetween(source, tStart, tFinish)
+ local start, finish = m.getStartFinish(source)
+ if not start then
+ return false
+ end
+ return start <= tFinish and finish >= tStart - 1
end
-function m.isBetweenRange(source, start, finish)
- return (source.vstart or source.start) <= finish and (source.range or source.finish) >= start - 1
+function m.isBetweenRange(source, tStart, tFinish)
+ local start, finish = m.getRange(source)
+ if not start then
+ return false
+ end
+ return start <= tFinish and finish >= tStart - 1
end
--- 添加child
@@ -357,8 +417,14 @@ function m.addChilds(list, obj, map)
for i = 1, #obj do
list[#list+1] = obj[i]
end
- else
+ elseif obj[key] then
list[#list+1] = obj[key]
+ elseif type(key) == 'string'
+ and key:sub(1, 1) == '#' then
+ key = key:sub(2)
+ for i = 1, #obj[key] do
+ list[#list+1] = obj[key][i]
+ end
end
end
end
@@ -856,7 +922,27 @@ local function stepRefOfGlobal(obj, mode)
return results
end
-function m.getStepRef(obj, mode)
+local function stepRefOfDocType(status, obj, mode)
+ local results = {}
+ local name = obj[1]
+ if not name or not status.interface.docType then
+ return results
+ end
+ local docs = status.interface.docType(name)
+ for i = 1, #docs do
+ local doc = docs[i]
+ if mode == 'def' then
+ if doc.type == 'doc.class.name' then
+ results[#results+1] = doc
+ end
+ else
+ results[#results+1] = doc
+ end
+ end
+ return results
+end
+
+function m.getStepRef(status, obj, mode)
if obj.type == 'getlocal'
or obj.type == 'setlocal' then
return stepRefOfLocal(obj.node, mode)
@@ -877,6 +963,11 @@ function m.getStepRef(obj, mode)
if obj.type == 'library' then
return { obj }
end
+ if obj.type == 'doc.class.name'
+ or obj.type == 'doc.type.name'
+ or obj.type == 'doc.extends.name' then
+ return stepRefOfDocType(status, obj, mode)
+ end
return nil
end
@@ -1076,6 +1167,10 @@ function m.isGlobal(source)
return false
end
+function m.isDoc(source)
+ return source.type:sub(1, 4) == 'doc.'
+end
+
--- 根据函数的调用参数,获取:调用,参数索引
function m.getCallAndArgIndex(callarg)
local callargs = callarg.parent
@@ -2024,7 +2119,7 @@ function m.searchRefs(status, obj, mode)
end
-- 检查单步引用
- local res = m.getStepRef(obj, mode)
+ local res = m.getStepRef(status, obj, mode)
if res then
for i = 1, #res do
status.results[#status.results+1] = res[i]
diff --git a/script-beta/parser/luadoc.lua b/script-beta/parser/luadoc.lua
index ebab1ee9..c84cf52b 100644
--- a/script-beta/parser/luadoc.lua
+++ b/script-beta/parser/luadoc.lua
@@ -671,7 +671,10 @@ return function (_, state)
table.sort(comments, function (a, b)
return a.start < b.start
end)
- ast.docs = {}
+ ast.docs = {
+ type = 'doc',
+ parent = ast,
+ }
pushError = state.pushError
@@ -679,6 +682,13 @@ return function (_, state)
local doc = buildLuaDoc(comment)
if doc then
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
end
end
end
diff --git a/script-beta/provider/provider.lua b/script-beta/provider/provider.lua
index c747027c..094ac027 100644
--- a/script-beta/provider/provider.lua
+++ b/script-beta/provider/provider.lua
@@ -62,6 +62,9 @@ local function updateConfig()
then
workspace.reload()
end
+ if not util.equal(oldConfig.luadoc, newConfig.luadoc) then
+ files.flushCache()
+ end
if newConfig.completion.enable then
completion.enable()
diff --git a/script-beta/vm/eachRef.lua b/script-beta/vm/eachRef.lua
index babfa4d8..429cbb73 100644
--- a/script-beta/vm/eachRef.lua
+++ b/script-beta/vm/eachRef.lua
@@ -5,7 +5,7 @@ local await = require 'await'
local function getRefs(source, simple)
local results = {}
- local lock = vm.lock('eachDef', source)
+ local lock = vm.lock('eachRef', source)
if not lock then
return results
end
diff --git a/script-beta/vm/getDocs.lua b/script-beta/vm/getDocs.lua
new file mode 100644
index 00000000..5c8e6304
--- /dev/null
+++ b/script-beta/vm/getDocs.lua
@@ -0,0 +1,58 @@
+local files = require 'files'
+local util = require 'utility'
+local guide = require 'parser.guide'
+local vm = require 'vm.vm'
+
+local function getTypesOfFile(uri)
+ local classes = {}
+ local ast = files.getAst(uri)
+ if not ast or not ast.ast.docs then
+ return classes
+ end
+ guide.eachSource(ast.ast.docs, function (src)
+ if src.type == 'doc.type.name'
+ or src.type == 'doc.class.name'
+ or src.type == 'doc.extends.name' then
+ local name = src[1]
+ if name then
+ if not classes[name] then
+ classes[name] = {}
+ end
+ classes[name][#classes[name]+1] = src
+ end
+ end
+ end)
+ return classes
+end
+
+local function getDocTypes(name)
+ local results = {}
+ for uri in files.eachFile() do
+ local cache = files.getCache(uri)
+ cache.classes = cache.classes or getTypesOfFile(uri)
+ if name == '*' then
+ for _, sources in util.sortPairs(cache.classes) do
+ for _, source in ipairs(sources) do
+ results[#results+1] = source
+ end
+ end
+ else
+ if cache.classes[name] then
+ for _, source in ipairs(cache.classes[name]) do
+ results[#results+1] = source
+ end
+ end
+ end
+ end
+ return results
+end
+
+function vm.getDocTypes(name)
+ local cache = vm.getCache('getDocTypes')[name]
+ if cache ~= nil then
+ return cache
+ end
+ cache = getDocTypes(name)
+ vm.getCache('getDocTypes')[name] = cache
+ return cache
+end
diff --git a/script-beta/vm/guideInterface.lua b/script-beta/vm/guideInterface.lua
index a77184f3..4d651882 100644
--- a/script-beta/vm/guideInterface.lua
+++ b/script-beta/vm/guideInterface.lua
@@ -85,6 +85,11 @@ function vm.interface.global(name)
return vm.getGlobals(name)
end
+function vm.interface.docType(name)
+ await.delay()
+ return vm.getDocTypes(name)
+end
+
function vm.interface.link(uri)
await.delay()
return vm.getLinksTo(uri)
diff --git a/script-beta/vm/init.lua b/script-beta/vm/init.lua
index 7621859f..b9e8e147 100644
--- a/script-beta/vm/init.lua
+++ b/script-beta/vm/init.lua
@@ -1,5 +1,6 @@
local vm = require 'vm.vm'
require 'vm.getGlobals'
+require 'vm.getDocs'
require 'vm.getLibrary'
require 'vm.getInfer'
require 'vm.getClass'
diff --git a/test-beta/references/init.lua b/test-beta/references/init.lua
index 3573da55..5bca58ab 100644
--- a/test-beta/references/init.lua
+++ b/test-beta/references/init.lua
@@ -48,6 +48,7 @@ function TEST(script)
end
assert(founded(target, positions))
else
+ local results = core('', pos)
assert(#target == 0)
end
end
@@ -262,14 +263,14 @@ local <!t!>
<!t!>.<!f!> = <?t?>
]]
---TEST [[
------@class <!Class!>
------@type <?Class?>
------@type <!Class!>
---]]
---
---TEST [[
------@class <?Class?>
------@type <!Class!>
------@type <!Class!>
---]]
+TEST [[
+---@class <!Class!>
+---@type <?Class?>
+---@type <!Class!>
+]]
+
+TEST [[
+---@class <?Class?>
+---@type <!Class!>
+---@type <!Class!>
+]]