summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md5
-rw-r--r--script/core/definition.lua2
-rw-r--r--script/core/jump-source.lua33
-rw-r--r--script/core/reference.lua2
-rw-r--r--script/core/type-definition.lua2
-rw-r--r--script/parser/luadoc.lua52
-rw-r--r--script/provider/provider.lua45
-rw-r--r--test/tclient/init.lua1
-rw-r--r--test/tclient/tests/jump-source.lua76
9 files changed, 189 insertions, 29 deletions
diff --git a/changelog.md b/changelog.md
index 6ecdef04..4e9adbe3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,11 @@
local fileName = root / 'script' / 'main.lua' -- `fileName` is `fspath` here
```
+* `NEW` `LuaDoc`: `---@source`:
+ ```lua
+ ---@source file:///xxx.c:50:20
+ XXX = 1 -- when finding definitions of `XXX`, returns `file:///xxx.c:50:20` instead here
+ ```
* `NEW` diagnostics:
* `unknown-operator`
* `unreachable-code`
diff --git a/script/core/definition.lua b/script/core/definition.lua
index e4868532..ac2513e9 100644
--- a/script/core/definition.lua
+++ b/script/core/definition.lua
@@ -4,6 +4,7 @@ local vm = require 'vm'
local findSource = require 'core.find-source'
local guide = require 'parser.guide'
local rpath = require 'workspace.require-path'
+local jumpSource = require 'core.jump-source'
local function sortResults(results)
-- 先按照顺序排序
@@ -197,6 +198,7 @@ return function (uri, offset)
end
sortResults(results)
+ jumpSource(results)
return results
end
diff --git a/script/core/jump-source.lua b/script/core/jump-source.lua
new file mode 100644
index 00000000..76d7324b
--- /dev/null
+++ b/script/core/jump-source.lua
@@ -0,0 +1,33 @@
+local guide = require 'parser.guide'
+
+---@param results table
+return function (results)
+ for _, result in ipairs(results) do
+ if result.target.type == 'doc.field.name' then
+ local doc = result.target.parent.source
+ if doc then
+ result.uri = doc.source
+ result.target.uri = doc.source
+ result.target.start = guide.positionOf(doc.line - 1, 0)
+ result.target.finish = guide.positionOf(doc.line - 1, 0)
+ end
+ else
+ local target = result.target
+ if target.type == 'method'
+ or target.type == 'field' then
+ target = target.parent
+ end
+ if target.bindDocs then
+ for _, doc in ipairs(target.bindDocs) do
+ if doc.type == 'doc.source'
+ and doc.bindSource == target then
+ result.uri = doc.source
+ result.target.uri = doc.source
+ result.target.start = guide.positionOf(doc.line - 1, 0)
+ result.target.finish = guide.positionOf(doc.line - 1, 0)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/script/core/reference.lua b/script/core/reference.lua
index 4c9c193d..a468afde 100644
--- a/script/core/reference.lua
+++ b/script/core/reference.lua
@@ -2,6 +2,7 @@ local guide = require 'parser.guide'
local files = require 'files'
local vm = require 'vm'
local findSource = require 'core.find-source'
+local jumpSource = require 'core.jump-source'
local function sortResults(results)
-- 先按照顺序排序
@@ -132,6 +133,7 @@ return function (uri, position)
end
sortResults(results)
+ jumpSource(results)
return results
end
diff --git a/script/core/type-definition.lua b/script/core/type-definition.lua
index d8434c8c..2140090b 100644
--- a/script/core/type-definition.lua
+++ b/script/core/type-definition.lua
@@ -4,6 +4,7 @@ local vm = require 'vm'
local findSource = require 'core.find-source'
local guide = require 'parser.guide'
local rpath = require 'workspace.require-path'
+local jumpSource = require 'core.jump-source'
local function sortResults(results)
-- 先按照顺序排序
@@ -164,6 +165,7 @@ return function (uri, offset)
end
sortResults(results)
+ jumpSource(results)
return results
end
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 37a1843d..91ed44c0 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -3,6 +3,7 @@ local re = require 'parser.relabel'
local guide = require 'parser.guide'
local compile = require 'parser.compile'
local util = require 'utility'
+local furi = require 'file-uri'
local TokenTypes, TokenStarts, TokenFinishs, TokenContents, TokenMarks
---@type integer
@@ -147,6 +148,7 @@ Symbol <- ({} {
---@field async? boolean
---@field versions? table[]
---@field names? parser.object[]
+---@field source? parser.object
local function parseTokens(text, offset)
Ci = 0
@@ -1403,8 +1405,36 @@ local docSwitch = util.switch()
return result
end)
+ : case 'source'
+ : call(function (doc)
+ local fullSource = doc:sub(#'source' + 1)
+ if not fullSource or fullSource == '' then
+ return
+ end
+ fullSource = util.trim(fullSource)
+ if fullSource == '' then
+ return
+ end
+ local source, line = fullSource:match('^(.-):(%d+)$')
+ source = source or fullSource
+ line = tonumber(line) or 1
+ local uri
+ if furi.split(source) then
+ uri = source
+ else
+ uri = furi.decode(source)
+ end
+ local result = {
+ type = 'doc.source',
+ start = getFinish(),
+ finish = getFinish(),
+ source = uri,
+ line = line,
+ }
+ return result
+ end)
-local function convertTokens()
+local function convertTokens(doc)
local tp, text = nextToken()
if not tp then
return
@@ -1417,7 +1447,7 @@ local function convertTokens()
}
return nil
end
- return docSwitch(text)
+ return docSwitch(text, doc)
end
local function trimTailComment(text)
@@ -1457,7 +1487,7 @@ local function buildLuaDoc(comment)
local doc = text:sub(startPos)
parseTokens(doc, comment.start + startPos)
- local result, rests = convertTokens()
+ local result, rests = convertTokens(doc)
if result then
result.range = comment.finish
local finish = result.firstFinish or result.finish
@@ -1527,7 +1557,8 @@ local function isContinuedDoc(lastDoc, nextDoc)
if nextDoc.type ~= 'doc.field'
and nextDoc.type ~= 'doc.operator'
and nextDoc.type ~= 'doc.comment'
- and nextDoc.type ~= 'doc.overload' then
+ and nextDoc.type ~= 'doc.overload'
+ and nextDoc.type ~= 'doc.source' then
return false
end
end
@@ -1603,7 +1634,8 @@ local function bindDoc(source, binded)
if doc.type == 'doc.class'
or doc.type == 'doc.deprecated'
or doc.type == 'doc.version'
- or doc.type == 'doc.module' then
+ or doc.type == 'doc.module'
+ or doc.type == 'doc.source' then
if source.type == 'function'
or isParam then
goto CONTINUE
@@ -1746,6 +1778,7 @@ end
local function bindCommentsAndFields(binded)
local class
local comments = {}
+ local source
for _, doc in ipairs(binded) do
if doc.type == 'doc.class' then
-- 多个class连续写在一起,只有最后一个class可以绑定source
@@ -1760,6 +1793,10 @@ local function bindCommentsAndFields(binded)
class.fields[#class.fields+1] = doc
doc.class = class
end
+ if source then
+ doc.source = source
+ source.bindSource = doc
+ end
bindCommentsToDoc(doc, comments)
comments = {}
elseif doc.type == 'doc.operator' then
@@ -1774,7 +1811,12 @@ local function bindCommentsAndFields(binded)
comments = {}
elseif doc.type == 'doc.comment' then
comments[#comments+1] = doc
+ elseif doc.type == 'doc.source' then
+ source = doc
+ goto CONTINUE
end
+ source = nil
+ ::CONTINUE::
end
end
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index eb1362eb..18147e80 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -22,6 +22,7 @@ local inspect = require 'inspect'
local markdown = require 'provider.markdown'
local guide = require 'parser.guide'
local fs = require 'bee.filesystem'
+local jumpSource = require 'core.jump-source'
---@async
local function updateConfig(uri)
@@ -376,18 +377,16 @@ m.register 'textDocument/definition' {
for i, info in ipairs(result) do
local targetUri = info.uri
if targetUri then
- if files.exists(targetUri) then
- if client.getAbility 'textDocument.definition.linkSupport' then
- response[i] = converter.locationLink(targetUri
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- , converter.packRange(uri, info.source.start, info.source.finish)
- )
- else
- response[i] = converter.location(targetUri
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- )
- end
+ if client.getAbility 'textDocument.definition.linkSupport' then
+ response[i] = converter.locationLink(targetUri
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ , converter.packRange(uri, info.source.start, info.source.finish)
+ )
+ else
+ response[i] = converter.location(targetUri
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ )
end
end
end
@@ -418,18 +417,16 @@ m.register 'textDocument/typeDefinition' {
for i, info in ipairs(result) do
local targetUri = info.uri
if targetUri then
- if files.exists(targetUri) then
- if client.getAbility 'textDocument.typeDefinition.linkSupport' then
- response[i] = converter.locationLink(targetUri
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- , converter.packRange(uri, info.source.start, info.source.finish)
- )
- else
- response[i] = converter.location(targetUri
- , converter.packRange(targetUri, info.target.start, info.target.finish)
- )
- end
+ if client.getAbility 'textDocument.typeDefinition.linkSupport' then
+ response[i] = converter.locationLink(targetUri
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ , converter.packRange(uri, info.source.start, info.source.finish)
+ )
+ else
+ response[i] = converter.location(targetUri
+ , converter.packRange(targetUri, info.target.start, info.target.finish)
+ )
end
end
end
diff --git a/test/tclient/init.lua b/test/tclient/init.lua
index 070cf337..80aae53a 100644
--- a/test/tclient/init.lua
+++ b/test/tclient/init.lua
@@ -8,4 +8,5 @@ require 'tclient.tests.resolve-completion'
require 'tclient.tests.performance-jass-common'
require 'tclient.tests.hover-pairs'
require 'tclient.tests.change-workspace-folder'
+require 'tclient.tests.jump-source'
require 'tclient.tests.build-meta'
diff --git a/test/tclient/tests/jump-source.lua b/test/tclient/tests/jump-source.lua
new file mode 100644
index 00000000..ff679826
--- /dev/null
+++ b/test/tclient/tests/jump-source.lua
@@ -0,0 +1,76 @@
+local lclient = require 'lclient'
+local util = require 'utility'
+local ws = require 'workspace'
+local files = require 'files'
+local furi = require 'file-uri'
+local fs = require 'bee.filesystem'
+
+---@async
+lclient():start(function (client)
+ client:registerFakers()
+ client:initialize()
+
+ ws.awaitReady()
+
+ client:notify('textDocument/didOpen', {
+ textDocument = {
+ uri = furi.encode('1.lua'),
+ languageId = 'lua',
+ version = 0,
+ text = [[
+---@class AAA
+---@source file:///xxx.lua:50
+---@field x number
+local mt = {}
+
+---@source file:///yyy.lua:30
+function mt:ff() end
+]]
+ }
+ })
+
+ client:notify('textDocument/didOpen', {
+ textDocument = {
+ uri = furi.encode('main.lua'),
+ languageId = 'lua',
+ version = 0,
+ text = [[
+---@type AAA
+local a
+
+print(a.x)
+print(a.ff)
+]]
+ }
+ })
+
+ local locations = client:awaitRequest('textDocument/definition', {
+ textDocument = { uri = furi.encode('main.lua') },
+ position = { line = 3, character = 9 },
+ })
+
+ assert(util.equal(locations, {
+ {
+ uri = 'file:///xxx.lua',
+ range = {
+ start = { line = 49, character = 0 },
+ ['end'] = { line = 49, character = 0 },
+ }
+ }
+ }))
+
+ local locations = client:awaitRequest('textDocument/definition', {
+ textDocument = { uri = furi.encode('main.lua') },
+ position = { line = 4, character = 9 },
+ })
+
+ assert(util.equal(locations, {
+ {
+ uri = 'file:///yyy.lua',
+ range = {
+ start = { line = 29, character = 0 },
+ ['end'] = { line = 29, character = 0 },
+ }
+ }
+ }))
+end)