summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2023-01-16 21:06:06 +0800
committer最萌小汐 <sumneko@hotmail.com>2023-01-16 21:06:06 +0800
commit5aaecf51b9fccddf52ed3e4749757a03819fae61 (patch)
tree87ceb62c6eb926cb54d8ba794697f0d3ddd0b1e3 /script
parenta6798e6adb81da6b7f833bc39da0a6368178a090 (diff)
downloadlua-language-server-5aaecf51b9fccddf52ed3e4749757a03819fae61.zip
support `---@meta [name]`
once declared `name`, user can only require this file by declared name meta file can not be required with name `_`
Diffstat (limited to 'script')
-rw-r--r--script/core/semantic-tokens.lua8
-rw-r--r--script/parser/guide.lua1
-rw-r--r--script/parser/luadoc.lua2
-rw-r--r--script/vm/doc.lua26
-rw-r--r--script/workspace/require-path.lua39
5 files changed, 72 insertions, 4 deletions
diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua
index b1ec6ac4..60a94281 100644
--- a/script/core/semantic-tokens.lua
+++ b/script/core/semantic-tokens.lua
@@ -694,6 +694,14 @@ local Care = util.switch()
type = define.TokenTypes.operator,
}
end)
+ : case 'doc.meta.name'
+ : call(function (source, options, results)
+ results[#results+1] = {
+ start = source.start,
+ finish = source.finish,
+ type = define.TokenTypes.namespace,
+ }
+ end)
---@param state table
---@param results table
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index e3c466c0..7f569d71 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -178,6 +178,7 @@ local childMap = {
['doc.cast'] = {'name', '#casts'},
['doc.cast.block'] = {'extends'},
['doc.operator'] = {'op', 'exp', 'extends'},
+ ['doc.meta'] = {'name'},
}
---@type table<string, fun(obj: parser.object, list: parser.object[])>
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 1a88d385..545f9d95 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -1116,8 +1116,10 @@ local docSwitch = util.switch()
end)
: case 'meta'
: call(function ()
+ local requireName = parseName('doc.meta.name')
return {
type = 'doc.meta',
+ name = requireName,
start = getFinish(),
finish = getFinish(),
}
diff --git a/script/vm/doc.lua b/script/vm/doc.lua
index f0f7c54c..a6ea248f 100644
--- a/script/vm/doc.lua
+++ b/script/vm/doc.lua
@@ -44,12 +44,38 @@ function vm.isMetaFile(uri)
for _, doc in ipairs(status.ast.docs) do
if doc.type == 'doc.meta' then
cache.isMeta = true
+ cache.metaName = doc.name
return true
end
end
return false
end
+---@param uri uri
+---@return string?
+function vm.getMetaName(uri)
+ if not vm.isMetaFile(uri) then
+ return nil
+ end
+ local cache = files.getCache(uri)
+ if not cache then
+ return nil
+ end
+ if not cache.metaName then
+ return nil
+ end
+ return cache.metaName[1]
+end
+
+---@param uri uri
+---@return boolean
+function vm.isMetaFileRequireable(uri)
+ if not vm.isMetaFile(uri) then
+ return false
+ end
+ return vm.getMetaName(uri) ~= '_'
+end
+
---@param doc parser.object
---@return table<string, boolean>?
function vm.getValidVersions(doc)
diff --git a/script/workspace/require-path.lua b/script/workspace/require-path.lua
index f65af868..d7ca8e26 100644
--- a/script/workspace/require-path.lua
+++ b/script/workspace/require-path.lua
@@ -59,12 +59,24 @@ end
---@param path string
---@return require-manager.visibleResult[]
function mt:getRequireResultByPath(path)
+ local vm = require 'vm'
local uri = furi.encode(path)
+ local result = {}
+ if vm.isMetaFile(uri) then
+ local metaName = vm.getMetaName(uri)
+ if metaName then
+ if vm.isMetaFileRequireable(uri) then
+ result[#result+1] = {
+ name = metaName,
+ }
+ end
+ return result
+ end
+ end
local searchers = config.get(self.scp.uri, 'Lua.runtime.path')
local strict = config.get(self.scp.uri, 'Lua.runtime.pathStrict')
local libUri = files.getLibraryUri(self.scp.uri, uri)
local libraryPath = libUri and furi.decode(libUri)
- local result = {}
for _, searcher in ipairs(searchers) do
local isAbsolute = searcher:match '^[/\\]'
or searcher:match '^%a+%:'
@@ -157,14 +169,29 @@ end
--- 查找符合指定require name的所有uri
---@param name string
---@return uri[]
----@return table<uri, string>
+---@return table<uri, string>?
function mt:searchUrisByRequireName(name)
+ local vm = require 'vm'
local searchers = config.get(self.scp.uri, 'Lua.runtime.path')
local strict = config.get(self.scp.uri, 'Lua.runtime.pathStrict')
local separator = config.get(self.scp.uri, 'Lua.completion.requireSeparator')
local path = name:gsub('%' .. separator, '/')
local results = {}
local searcherMap = {}
+ local excludes = {}
+
+ for uri in files.eachFile(self.scp.uri) do
+ if vm.isMetaFileRequireable(uri) then
+ local metaName = vm.getMetaName(uri)
+ if metaName == name then
+ results[#results+1] = uri
+ return results
+ end
+ if metaName then
+ excludes[uri] = true
+ end
+ end
+ end
for _, searcher in ipairs(searchers) do
local fspath = searcher:gsub('%?', (path:gsub('%%', '%%%%')))
@@ -172,7 +199,9 @@ function mt:searchUrisByRequireName(name)
local tail = '/' .. furi.encode(fspath):gsub('^file:[/]*', '')
for uri in files.eachFile(self.scp.uri) do
if not searcherMap[uri]
- and util.stringEndWith(uri, tail) then
+ and not excludes[uri]
+ and util.stringEndWith(uri, tail)
+ and (not vm.isMetaFile(uri) or vm.isMetaFileRequireable(uri)) then
local parentUri = files.getLibraryUri(self.scp.uri, uri) or self.scp.uri
if parentUri == nil or parentUri == '' then
parentUri = furi.encode '/'
@@ -223,7 +252,7 @@ function mt:findUrisByRequireName(suri, name)
for _, uri in ipairs(cache.results) do
if uri ~= suri then
results[#results+1] = uri
- searcherMap[uri] = cache.searcherMap[uri]
+ searcherMap[uri] = cache.searcherMap and cache.searcherMap[uri]
end
end
return results, searcherMap
@@ -242,6 +271,8 @@ end
---@param uri uri
---@param name string
+---@return uri[]
+---@return table<uri, string>?
function m.findUrisByRequireName(uri, name)
local scp = scope.getScope(uri)
---@type require-manager