summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-04-02 18:31:52 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-04-02 18:31:52 +0800
commitaed420ac2c4cad689b91fb6acd9f5796f9776f54 (patch)
tree6ba4437929189f208feb6976ab8192f3693e17f4
parentb5b6a3d67bdcc4843d2453e5be6ee1c50819e86e (diff)
parente5947d5cb525d0c3376d36be657c0f940d8bfaf8 (diff)
downloadlua-language-server-aed420ac2c4cad689b91fb6acd9f5796f9776f54.zip
Merge branch '1.21.0'
-rw-r--r--.vscode/settings.json3
-rw-r--r--changelog.md5
-rw-r--r--script/config.lua7
-rw-r--r--script/core/completion.lua11
-rw-r--r--script/core/definition.lua3
-rw-r--r--script/core/diagnostics/init.lua8
-rw-r--r--script/core/diagnostics/redundant-parameter.lua12
-rw-r--r--script/core/document-symbol.lua13
-rw-r--r--script/core/guide.lua53
-rw-r--r--script/core/highlight.lua3
-rw-r--r--script/core/hover/arg.lua4
-rw-r--r--script/core/hover/init.lua6
-rw-r--r--script/core/reference.lua3
-rw-r--r--script/core/rename.lua6
-rw-r--r--script/core/signature.lua9
-rw-r--r--script/core/workspace-symbol.lua3
-rw-r--r--script/parser/compile.lua41
-rw-r--r--script/parser/luadoc.lua4
-rw-r--r--script/provider/completion.lua14
-rw-r--r--script/provider/provider.lua75
-rw-r--r--script/provider/semantic-tokens.lua10
-rw-r--r--test/completion/init.lua6
-rw-r--r--test/references/init.lua48
-rw-r--r--test/type_inference/init.lua73
24 files changed, 320 insertions, 100 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 617c3816..248a92a6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -15,7 +15,8 @@
"LOCALE"
],
"Lua.diagnostics.disable": [
- "close-non-object"
+ "close-non-object",
+ "undefined-field"
],
"Lua.runtime.version": "Lua 5.4",
// Just some comment
diff --git a/changelog.md b/changelog.md
index 6c66be3a..0e5310b5 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
# changelog
+## 1.21.0
+* `CHG` `LuaDoc`: supports `---@param self TYPE`
+* `CHG` completion: does not show suggests after `\n`, `{` and `,`, unless your setting `editor.acceptSuggestionOnEnter` is `off`
+* `FIX` [#482](https://github.com/sumneko/lua-language-server/issues/482)
+
## 1.20.1
`2021-3-27`
* `FIX` telemetry window blocks initializing
diff --git a/script/config.lua b/script/config.lua
index effd3016..7991e1ad 100644
--- a/script/config.lua
+++ b/script/config.lua
@@ -198,9 +198,10 @@ local ConfigTemplate = {
}
local OtherTemplate = {
- associations = {{}, Hash(String, String)},
- exclude = {{}, Hash(String, Boolean)},
- semantic = {'', Or(Boolean, String)},
+ associations = {{}, Hash(String, String)},
+ exclude = {{}, Hash(String, Boolean)},
+ semantic = {'', Or(Boolean, String)},
+ acceptSuggestionOnEnter = {'on', String},
}
local function init()
diff --git a/script/core/completion.lua b/script/core/completion.lua
index 60dbea7c..f710b953 100644
--- a/script/core/completion.lua
+++ b/script/core/completion.lua
@@ -1282,9 +1282,6 @@ local function getFuncParamByCallIndex(func, index)
if not func.args or #func.args == 0 then
return nil
end
- if func.parent.type == 'setmethod' then
- return func.args[index - 1]
- end
if index > #func.args then
if func.args[#func.args].type == '...' then
return func.args[#func.args]
@@ -1630,12 +1627,12 @@ local function tryLuaDocByErr(ast, offset, err, docState, results)
local label = {}
local insertText = {}
for i, arg in ipairs(func.args) do
- if arg[1] then
+ if arg[1] and not arg.dummy then
label[#label+1] = arg[1]
- if i == 1 then
- insertText[i] = ('%s ${%d:any}'):format(arg[1], i)
+ if #label == 1 then
+ insertText[#insertText+1] = ('%s ${%d:any}'):format(arg[1], #label)
else
- insertText[i] = ('---@param %s ${%d:any}'):format(arg[1], i)
+ insertText[#insertText+1] = ('---@param %s ${%d:any}'):format(arg[1], #label)
end
end
end
diff --git a/script/core/definition.lua b/script/core/definition.lua
index 8fa9bce0..b26bb922 100644
--- a/script/core/definition.lua
+++ b/script/core/definition.lua
@@ -137,6 +137,9 @@ return function (uri, offset)
end
for _, src in ipairs(defs) do
+ if src.dummy then
+ goto CONTINUE
+ end
if values[src] then
goto CONTINUE
end
diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua
index a164437f..fcfcc9ad 100644
--- a/script/core/diagnostics/init.lua
+++ b/script/core/diagnostics/init.lua
@@ -38,10 +38,18 @@ local function check(uri, name, results)
local severity = define.DiagnosticSeverity[level]
local clock = os.clock()
+ local mark = {}
require('core.diagnostics.' .. name)(uri, function (result)
if vm.isDiagDisabledAt(uri, result.start, name) then
return
end
+ if result.start == 0 then
+ return
+ end
+ if mark[result.start] then
+ return
+ end
+ mark[result.start] = true
result.level = severity or result.level
result.code = name
results[#results+1] = result
diff --git a/script/core/diagnostics/redundant-parameter.lua b/script/core/diagnostics/redundant-parameter.lua
index fc446f7c..c5bcd5a5 100644
--- a/script/core/diagnostics/redundant-parameter.lua
+++ b/script/core/diagnostics/redundant-parameter.lua
@@ -10,18 +10,12 @@ local function countCallArgs(source)
if not source.args then
return 0
end
- if source.node and source.node.type == 'getmethod' then
- result = result + 1
- end
result = result + #source.args
return result
end
local function countFuncArgs(source)
local result = 0
- if source.parent and source.parent.type == 'setmethod' then
- result = result + 1
- end
if not source.args or #source.args == 0 then
return result
end
@@ -34,9 +28,6 @@ end
local function countOverLoadArgs(source, doc)
local result = 0
- if source.parent and source.parent.type == 'setmethod' then
- result = result + 1
- end
local func = doc.overload
if not func.args or #func.args == 0 then
return result
@@ -107,6 +98,9 @@ return function (uri, callback)
if delta <= 0 then
return
end
+ if callArgs == 1 and source.node.type == 'getmethod' then
+ return
+ end
for i = #source.args - delta + 1, #source.args do
local arg = source.args[i]
if arg then
diff --git a/script/core/document-symbol.lua b/script/core/document-symbol.lua
index fead4153..cc87e3ca 100644
--- a/script/core/document-symbol.lua
+++ b/script/core/document-symbol.lua
@@ -26,12 +26,16 @@ local function buildFunctionParams(func)
return ''
end
local params = {}
- for i, arg in ipairs(func.args) do
+ for _, arg in ipairs(func.args) do
+ if arg.dummy then
+ goto CONTINUE
+ end
if arg.type == '...' then
- params[i] = '...'
+ params[#params+1] = '...'
else
- params[i] = arg[1] or ''
+ params[#params+1] = arg[1] or ''
end
+ ::CONTINUE::
end
return table.concat(params, ', ')
end
@@ -172,6 +176,9 @@ local function buildValue(source, text, symbols)
end
local function buildSet(source, text, used, symbols)
+ if source.dummy then
+ return
+ end
local value = source.value
if value and value.type == 'function' then
used[value] = true
diff --git a/script/core/guide.lua b/script/core/guide.lua
index 9c0fac76..5e3b6693 100644
--- a/script/core/guide.lua
+++ b/script/core/guide.lua
@@ -570,10 +570,10 @@ end
--- 遍历所有指定类型的source
function m.eachSourceType(ast, type, callback)
- local cache = ast.typeCache
+ local cache = ast._typeCache
if not cache then
cache = {}
- ast.typeCache = cache
+ ast._typeCache = cache
m.eachSource(ast, function (source)
local tp = source.type
if not tp then
@@ -1399,10 +1399,6 @@ function m.getCallAndArgIndex(callarg)
end
end
local call = callargs.parent
- local node = call.node
- if node.type == 'getmethod' then
- index = index + 1
- end
return call, index
end
@@ -1753,12 +1749,11 @@ local function stepRefOfGeneric(status, typeUnit, args, mode)
if docArg.type == 'doc.param' then
local paramName = docArg.param[1]
for _, source in ipairs(doc.bindSources) do
- if source.type == 'local'
- and source[1] == paramName
- and source.parent.type == 'funcargs' then
- for index, arg in ipairs(source.parent) do
- if arg == source then
- genericIndex = index
+ if source.type == 'function'
+ and source.args then
+ for i, arg in ipairs(source.args) do
+ if arg[1] == paramName then
+ genericIndex = i
break
end
end
@@ -2244,7 +2239,6 @@ function m.checkSameSimpleInCallInSameFile(status, func, args, index)
end
end
end
- -- generic cannot cache
cache[index] = results
end
return results
@@ -3008,11 +3002,7 @@ function m.searchSameFields(status, simple, mode)
local queues, starts, forces = allocQueue()
local queueLen = 0
local locks = {}
- local function pushQueue(obj, start, force)
- if obj.type == 'getlocal'
- or obj.type == 'setlocal' then
- obj = obj.node
- end
+ local function appendQueue(obj, start, force)
local lock = locks[start]
if not lock then
lock = {}
@@ -3026,25 +3016,32 @@ function m.searchSameFields(status, simple, mode)
queues[queueLen] = obj
starts[queueLen] = start
forces[queueLen] = force
- if obj.type == 'local' and obj.ref then
- for _, ref in ipairs(obj.ref) do
+ if obj.mirror then
+ if not lock[obj.mirror] then
+ lock[obj.mirror] = true
queueLen = queueLen + 1
- queues[queueLen] = ref
+ queues[queueLen] = obj.mirror
starts[queueLen] = start
forces[queueLen] = force
end
end
+ end
+ local function pushQueue(obj, start, force)
+ if obj.type == 'getlocal'
+ or obj.type == 'setlocal' then
+ obj = obj.node
+ end
+ appendQueue(obj, start, force)
+ if obj.type == 'local' and obj.ref then
+ for _, ref in ipairs(obj.ref) do
+ appendQueue(ref, start, force)
+ end
+ end
if m.isGlobal(obj) then
local refs = m.checkSameSimpleInGlobal(status, obj)
if refs then
for _, ref in ipairs(refs) do
- if not lock[ref] then
- lock[ref] = true
- queueLen = queueLen + 1
- queues[queueLen] = ref
- starts[queueLen] = start
- forces[queueLen] = force
- end
+ appendQueue(ref, start, force)
end
end
end
diff --git a/script/core/highlight.lua b/script/core/highlight.lua
index 01f9178a..e79bb797 100644
--- a/script/core/highlight.lua
+++ b/script/core/highlight.lua
@@ -167,6 +167,9 @@ return function (uri, offset)
local source = findSource(ast, offset, accept)
if source then
find(source, uri, function (target)
+ if target.dummy then
+ return
+ end
local kind
if target.type == 'getfield' then
target = target.field
diff --git a/script/core/hover/arg.lua b/script/core/hover/arg.lua
index e8939034..324d28af 100644
--- a/script/core/hover/arg.lua
+++ b/script/core/hover/arg.lua
@@ -26,6 +26,9 @@ local function asFunction(source, oop)
if source.args then
for i = 1, #source.args do
local arg = source.args[i]
+ if arg.dummy then
+ goto CONTINUE
+ end
local name = arg.name or guide.getKeyName(arg)
if name then
args[#args+1] = ('%s%s: %s'):format(
@@ -36,6 +39,7 @@ local function asFunction(source, oop)
else
args[#args+1] = ('%s'):format(vm.getInferType(arg))
end
+ ::CONTINUE::
end
end
if oop then
diff --git a/script/core/hover/init.lua b/script/core/hover/init.lua
index 9c08ad7e..81285ef2 100644
--- a/script/core/hover/init.lua
+++ b/script/core/hover/init.lua
@@ -21,9 +21,6 @@ local function eachFunctionAndOverload(value, callback)
end
local function getHoverAsValue(source)
- local oop = source.type == 'method'
- or source.type == 'getmethod'
- or source.type == 'setmethod'
local label = getLabel(source)
local desc = getDesc(source)
if not desc then
@@ -49,9 +46,6 @@ local function getHoverAsFunction(source)
local defs = 0
local protos = 0
local other = 0
- local oop = source.type == 'method'
- or source.type == 'getmethod'
- or source.type == 'setmethod'
local mark = {}
for _, def in ipairs(values) do
def = guide.getObjectValue(def) or def
diff --git a/script/core/reference.lua b/script/core/reference.lua
index e0febc9c..7620b09e 100644
--- a/script/core/reference.lua
+++ b/script/core/reference.lua
@@ -66,6 +66,9 @@ return function (uri, offset)
local results = {}
for _, src in ipairs(vm.getRefs(source, 5)) do
+ if src.dummy then
+ goto CONTINUE
+ end
local root = guide.getRoot(src)
if not root then
goto CONTINUE
diff --git a/script/core/rename.lua b/script/core/rename.lua
index eee9d351..da82b0a6 100644
--- a/script/core/rename.lua
+++ b/script/core/rename.lua
@@ -196,10 +196,10 @@ local function renameField(source, newname, callback)
callback(source, func.start, parent.finish, newstr)
local pl = text:find('(', parent.finish, true)
if pl then
- if func.args then
- callback(source, pl + 1, pl, 'self, ')
- else
+ if text:find('^%s*%)', pl + 1) then
callback(source, pl + 1, pl, 'self')
+ else
+ callback(source, pl + 1, pl, 'self, ')
end
end
end
diff --git a/script/core/signature.lua b/script/core/signature.lua
index 1c9cb812..61234fd4 100644
--- a/script/core/signature.lua
+++ b/script/core/signature.lua
@@ -69,8 +69,13 @@ local function makeSignatures(call, pos)
or node.type == 'getmethod'
or node.type == 'setmethod'
local index
- local args = call.args
- if args then
+ if call.args then
+ local args = {}
+ for _, arg in ipairs(call.args) do
+ if not arg.dummy then
+ args[#args+1] = arg
+ end
+ end
for i, arg in ipairs(args) do
if arg.start <= pos and arg.finish >= pos then
index = i
diff --git a/script/core/workspace-symbol.lua b/script/core/workspace-symbol.lua
index c024cf1d..ae420d32 100644
--- a/script/core/workspace-symbol.lua
+++ b/script/core/workspace-symbol.lua
@@ -5,6 +5,9 @@ local define = require 'proto.define'
local await = require 'await'
local function buildSource(uri, source, key, results)
+ if source.dummy then
+ return
+ end
if source.type == 'local'
or source.type == 'setlocal'
or source.type == 'setglobal' then
diff --git a/script/parser/compile.lua b/script/parser/compile.lua
index 392f0682..04fc19c7 100644
--- a/script/parser/compile.lua
+++ b/script/parser/compile.lua
@@ -1,6 +1,8 @@
-local guide = require 'core.guide'
-local type = type
-local os = os
+local guide = require 'parser.guide'
+local type = type
+local tableInsert = table.insert
+local pairs = pairs
+local os = os
local specials = {
['_G'] = true,
@@ -73,6 +75,24 @@ local vmMap = {
end,
['call'] = function (obj)
Compile(obj.node, obj)
+ if obj.node and obj.node.type == 'getmethod' then
+ if not obj.args then
+ obj.args = {
+ type = 'callargs',
+ start = obj.start,
+ finish = obj.finish,
+ parent = obj,
+ }
+ end
+ local newNode = {}
+ for k, v in pairs(obj.node.node) do
+ newNode[k] = v
+ end
+ newNode.mirror = obj.node.node
+ newNode.dummy = true
+ obj.node.node.mirror = newNode
+ tableInsert(obj.args, 1, newNode)
+ end
Compile(obj.args, obj)
end,
['callargs'] = function (obj)
@@ -126,15 +146,24 @@ local vmMap = {
Compile(obj.node, obj)
Compile(obj.method, obj)
local value = obj.value
- value.localself = {
+ local localself = {
type = 'local',
start = 0,
finish = 0,
method = obj,
effect = obj.finish,
tag = 'self',
+ dummy = true,
[1] = 'self',
}
+ if not value.args then
+ value.args = {
+ type = 'funcargs',
+ start = obj.start,
+ finish = obj.finish,
+ }
+ end
+ tableInsert(value.args, 1, localself)
Compile(value, obj)
end,
['function'] = function (obj)
@@ -142,10 +171,6 @@ local vmMap = {
local LastLocalCount = LocalCount
Block = obj
LocalCount = 0
- if obj.localself then
- Compile(obj.localself, obj)
- obj.localself = nil
- end
Compile(obj.args, obj)
for i = 1, #obj do
Compile(obj[i], obj)
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 7e133aa2..74e53718 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -1148,10 +1148,6 @@ local function bindParamAndReturnIndex(binded)
return
end
local paramIndex = 0
- local parent = func.parent
- if parent.type == 'setmethod' then
- paramIndex = paramIndex + 1
- end
local paramMap = {}
for _, param in ipairs(func.args) do
paramIndex = paramIndex + 1
diff --git a/script/provider/completion.lua b/script/provider/completion.lua
index 9cf3a39a..1adcc47a 100644
--- a/script/provider/completion.lua
+++ b/script/provider/completion.lua
@@ -1,4 +1,6 @@
-local proto = require 'proto'
+local proto = require 'proto'
+local nonil = require 'without-check-nil'
+local client = require 'provider.client'
local isEnable = false
@@ -15,6 +17,11 @@ local function enable()
if isEnable then
return
end
+ nonil.enable()
+ if not client.info.capabilities.textDocument.completion.dynamicRegistration then
+ return
+ end
+ nonil.disable()
isEnable = true
log.debug('Enable completion.')
proto.awaitRequest('client/registerCapability', {
@@ -35,6 +42,11 @@ local function disable()
if not isEnable then
return
end
+ nonil.enable()
+ if not client.info.capabilities.textDocument.completion.dynamicRegistration then
+ return
+ end
+ nonil.disable()
isEnable = false
log.debug('Disable completion.')
proto.awaitRequest('client/unregisterCapability', {
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index e9974250..11b87405 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -18,6 +18,8 @@ local lang = require 'language'
local plugin = require 'plugin'
local progress = require 'progress'
local tm = require 'text-merger'
+local vm = require 'vm'
+local nonil = require 'without-check-nil'
local function updateConfig()
local diagnostics = require 'provider.diagnostic'
@@ -40,6 +42,10 @@ local function updateConfig()
scopeUri = workspace.uri,
section = 'editor.semanticHighlighting.enabled',
},
+ {
+ scopeUri = workspace.uri,
+ section = 'editor.acceptSuggestionOnEnter',
+ },
},
})
if not configs or not configs[1] then
@@ -49,9 +55,10 @@ local function updateConfig()
local updated = configs[1]
local other = {
- associations = configs[2],
- exclude = configs[3],
- semantic = configs[4],
+ associations = configs[2],
+ exclude = configs[3],
+ semantic = configs[4],
+ acceptSuggestionOnEnter = configs[5],
}
local oldConfig = util.deepCopy(config.config)
@@ -115,29 +122,38 @@ proto.on('initialized', function (params)
updateConfig()
local registrations = {}
- -- 监视文件变化
- registrations[#registrations+1] = {
- id = 'workspace/didChangeWatchedFiles',
- method = 'workspace/didChangeWatchedFiles',
- registerOptions = {
- watchers = {
- {
- globPattern = '**/',
- kind = 1 | 2 | 4,
- }
+ nonil.enable()
+ if client.info.capabilities.workspace.didChangeWatchedFiles.dynamicRegistration then
+ -- 监视文件变化
+ registrations[#registrations+1] = {
+ id = 'workspace/didChangeWatchedFiles',
+ method = 'workspace/didChangeWatchedFiles',
+ registerOptions = {
+ watchers = {
+ {
+ globPattern = '**/',
+ kind = 1 | 2 | 4,
+ }
+ },
},
- },
- }
+ }
+ end
- -- 监视配置变化
- registrations[#registrations+1] = {
- id = 'workspace/didChangeConfiguration',
- method = 'workspace/didChangeConfiguration',
- }
+ if client.info.capabilities.workspace.didChangeConfiguration.dynamicRegistration then
+ -- 监视配置变化
+ registrations[#registrations+1] = {
+ id = 'workspace/didChangeConfiguration',
+ method = 'workspace/didChangeConfiguration',
+ }
+ end
- proto.awaitRequest('client/registerCapability', {
- registrations = registrations
- })
+ nonil.disable()
+
+ if #registrations ~= 0 then
+ proto.awaitRequest('client/registerCapability', {
+ registrations = registrations
+ })
+ end
workspace.reload()
return true
end)
@@ -288,6 +304,7 @@ proto.on('textDocument/hover', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local hover = core.byUri(uri, offset)
if not hover then
@@ -314,6 +331,7 @@ proto.on('textDocument/definition', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
@@ -343,6 +361,7 @@ proto.on('textDocument/references', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
@@ -364,6 +383,7 @@ proto.on('textDocument/documentHighlight', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
@@ -387,6 +407,7 @@ proto.on('textDocument/rename', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local result = core.rename(uri, offset, params.newName)
if not result then
@@ -412,6 +433,7 @@ proto.on('textDocument/prepareRename', function (params)
if not files.exists(uri) then
return nil
end
+ vm.flushCache()
local offset = files.offsetOfWord(uri, params.position)
local result = core.prepareRename(uri, offset)
if not result then
@@ -436,6 +458,13 @@ proto.on('textDocument/completion', function (params)
if not files.exists(uri) then
return nil
end
+ if config.other.acceptSuggestionOnEnter ~= 'off' then
+ if params.context.triggerCharacter == '\n'
+ or params.context.triggerCharacter == '{'
+ or params.context.triggerCharacter == ',' then
+ return
+ end
+ end
await.setPriority(1000)
local clock = os.clock()
local offset = files.offset(uri, params.position)
diff --git a/script/provider/semantic-tokens.lua b/script/provider/semantic-tokens.lua
index bc8f81b9..268b8648 100644
--- a/script/provider/semantic-tokens.lua
+++ b/script/provider/semantic-tokens.lua
@@ -4,6 +4,7 @@ local client = require 'provider.client'
local json = require "json"
local config = require 'config'
local lang = require 'language'
+local nonil = require 'without-check-nil'
local isEnable = false
@@ -23,9 +24,11 @@ local function enable()
if isEnable then
return
end
- if not client.info.capabilities.textDocument.semanticTokens then
+ nonil.enable()
+ if not client.info.capabilities.textDocument.semanticTokens.dynamicRegistration then
return
end
+ nonil.disable()
isEnable = true
log.debug('Enable semantic tokens.')
proto.awaitRequest('client/registerCapability', {
@@ -80,6 +83,11 @@ local function disable()
if not isEnable then
return
end
+ nonil.enable()
+ if not client.info.capabilities.textDocument.semanticTokens.dynamicRegistration then
+ return
+ end
+ nonil.disable()
isEnable = false
log.debug('Disable semantic tokens.')
proto.awaitRequest('client/unregisterCapability', {
diff --git a/test/completion/init.lua b/test/completion/init.lua
index ba3c5be5..fb042fe9 100644
--- a/test/completion/init.lua
+++ b/test/completion/init.lua
@@ -1515,7 +1515,11 @@ end
insertText = [[
a ${1:any}
---@param b ${2:any}
----@param c ${3:any}]]
+---@param c ${3:any}]],
+ },
+ {
+ label = 'self',
+ kind = define.CompletionItemKind.Interface,
},
{
label = 'a',
diff --git a/test/references/init.lua b/test/references/init.lua
index 8494e12b..c4e5018a 100644
--- a/test/references/init.lua
+++ b/test/references/init.lua
@@ -386,3 +386,51 @@ end
local v1 = Master:foobar("", Dog)
v1.<!eat!>()
]]
+
+TEST [[
+---@class A
+local <?A?>
+
+---@generic T
+---@param self T
+---@return T
+function m.f(self) end
+
+local <!b!> = m.f(<!A!>)
+]]
+
+TEST [[
+---@class A
+local <?A?>
+
+---@generic T
+---@param self T
+---@return T
+function m:f() end
+
+local <!b!> = m.f(<!A!>)
+]]
+
+TEST [[
+---@class A
+local <?A?>
+
+---@generic T
+---@param self T
+---@return T
+function <!A!>.f(self) end
+
+local <!b!> = <!A!>:f()
+]]
+
+TEST [[
+---@class A
+local <?A?>
+
+---@generic T
+---@param self T
+---@return T
+function <!A!>:f() end
+
+local <!b!> = <!A!>:f()
+]]
diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua
index f45e6a9e..02355a94 100644
--- a/test/type_inference/init.lua
+++ b/test/type_inference/init.lua
@@ -606,3 +606,76 @@ function m:f()
return <?self?>
end
]]
+
+TEST 'Cls' [[
+---@class Cls
+local Cls = {}
+
+---@generic T
+---@param self T
+---@return T
+function Cls.new(self) return self end
+
+local <?test?> = Cls:new()
+]]
+
+TEST 'Cls' [[
+---@class Cls
+local Cls = {}
+
+---@generic T
+---@param self T
+---@return T
+function Cls:new() return self end
+
+local <?test?> = Cls:new()
+]]
+
+TEST 'Cls' [[
+---@class Cls
+local Cls = {}
+
+---@generic T
+---@param self T
+---@return T
+function Cls.new(self) return self end
+
+local <?test?> = Cls.new(Cls)
+]]
+
+TEST 'Cls' [[
+---@class Cls
+local Cls = {}
+
+---@generic T
+---@param self T
+---@return T
+function Cls:new() return self end
+
+local <?test?> = Cls.new(Cls)
+]]
+
+TEST 'Rct' [[
+---@class Obj
+local Obj = {}
+
+---@generic T
+---@param self T
+---@return T
+function Obj.new(self) return self end
+
+
+---@class Pnt:Obj
+local Pnt = {x = 0, y = 0}
+
+
+---@class Rct:Pnt
+local Rct = {w = 0, h = 0}
+
+
+local <?test?> = Rct.new(Rct)
+
+-- local test = Rct:new()
+
+return test
+]]