summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-10-25 00:55:15 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-10-25 00:55:15 +0800
commite3edc5d1880a392e065a71926b6f8ff113ea300c (patch)
tree1b64dc28b4bdacd6ef44769fb38588c286a3adea
parenta90a48c328045dd3f89da78a77f977ceb2cc7ae0 (diff)
downloadlua-language-server-e3edc5d1880a392e065a71926b6f8ff113ea300c.zip
diagnostic for invisible fields
#1316
-rw-r--r--locale/en-us/script.lua4
-rw-r--r--locale/pt-br/script.lua4
-rw-r--r--locale/zh-cn/script.lua4
-rw-r--r--locale/zh-tw/script.lua4
-rw-r--r--script/core/diagnostics/init.lua43
-rw-r--r--script/core/diagnostics/invisible.lua55
-rw-r--r--script/proto/diagnostic.lua1
-rw-r--r--test/diagnostics/common.lua61
8 files changed, 152 insertions, 24 deletions
diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua
index ca17cdf0..5aa93a4c 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -144,6 +144,10 @@ DIAG_UNKNOWN_OPERATOR =
'Unknown operator `{}`.'
DIAG_UNREACHABLE_CODE =
'Unreachable code.'
+DIAG_INVISIBLE_PRIVATE =
+'Field `{field}` is private, it can only be accessed in class `{class}`.'
+DIAG_INVISIBLE_PROTECTED =
+'Field `{field}` is protected, it can only be accessed in class `{class}` and its subclasses.'
MWS_NOT_SUPPORT =
'{} does not support multi workspace for now, I may need to restart to support the new workspace ...'
diff --git a/locale/pt-br/script.lua b/locale/pt-br/script.lua
index e93ff85f..e58dc201 100644
--- a/locale/pt-br/script.lua
+++ b/locale/pt-br/script.lua
@@ -144,6 +144,10 @@ DIAG_UNKNOWN_OPERATOR = -- TODO: need translate!
'Unknown operator `{}`.'
DIAG_UNREACHABLE_CODE = -- TODO: need translate!
'Unreachable code.'
+DIAG_INVISIBLE_PRIVATE = -- TODO: need translate!
+'Field `{field}` is private, it can only be accessed in class `{class}`.'
+DIAG_INVISIBLE_PROTECTED = -- TODO: need translate!
+'Field `{field}` is protected, it can only be accessed in class `{class}` and its subclasses.'
MWS_NOT_SUPPORT =
'{} não é suportado múltiplos espaços de trabalho por enquanto, posso precisar reiniciar para estabelecer um novo espaço de trabalho ...'
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index 04d5e115..a0384e8f 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -144,6 +144,10 @@ DIAG_UNKNOWN_OPERATOR =
'未知的运算符 `{}`。'
DIAG_UNREACHABLE_CODE =
'不可达的代码。'
+DIAG_INVISIBLE_PRIVATE =
+'字段 `{field}` 是私有的,只能在 `{class}` 类中才能访问。'
+DIAG_INVISIBLE_PROTECTED =
+'字段 `{field}` 收到保护,只能在 `{class}` 类极其子类中才能访问。'
MWS_NOT_SUPPORT =
'{} 目前还不支持多工作目录,我可能需要重启才能支持新的工作目录...'
diff --git a/locale/zh-tw/script.lua b/locale/zh-tw/script.lua
index 8f03d7ca..b76d2fd1 100644
--- a/locale/zh-tw/script.lua
+++ b/locale/zh-tw/script.lua
@@ -144,6 +144,10 @@ DIAG_UNKNOWN_OPERATOR = -- TODO: need translate!
'Unknown operator `{}`.'
DIAG_UNREACHABLE_CODE = -- TODO: need translate!
'Unreachable code.'
+DIAG_INVISIBLE_PRIVATE = -- TODO: need translate!
+'Field `{field}` is private, it can only be accessed in class `{class}`.'
+DIAG_INVISIBLE_PROTECTED = -- TODO: need translate!
+'Field `{field}` is protected, it can only be accessed in class `{class}` and its subclasses.'
MWS_NOT_SUPPORT =
'{} 目前還不支援多工作目錄,我可能需要重新啟動才能支援新的工作目錄...'
diff --git a/script/core/diagnostics/init.lua b/script/core/diagnostics/init.lua
index c33de6ce..e3f2c416 100644
--- a/script/core/diagnostics/init.lua
+++ b/script/core/diagnostics/init.lua
@@ -6,29 +6,6 @@ local vm = require "vm.vm"
local util = require 'utility'
local diagd = require 'proto.diagnostic'
--- 把耗时最长的诊断放到最后面
-local diagSort = {
- ['redundant-value'] = 100,
- ['not-yieldable'] = 100,
- ['deprecated'] = 100,
- ['undefined-field'] = 110,
- ['redundant-parameter'] = 110,
- ['cast-local-type'] = 120,
- ['assign-type-mismatch'] = 120,
- ['param-type-mismatch'] = 120,
- ['missing-return'] = 120,
- ['missing-return-value'] = 120,
- ['redundant-return-value'] = 120,
-}
-
-local diagList = {}
-for k in pairs(define.DiagnosticDefaultSeverity) do
- diagList[#diagList+1] = k
-end
-table.sort(diagList, function (a, b)
- return (diagSort[a] or 0) < (diagSort[b] or 0)
-end)
-
local sleepRest = 0.0
---@async
@@ -165,6 +142,21 @@ local function check(uri, name, isScopeDiag, response)
end
end
+local diagList
+local diagCosts = {}
+local function buildDiagList()
+ if not diagList then
+ diagList = {}
+ for name in pairs(define.DiagnosticDefaultSeverity) do
+ diagList[#diagList+1] = name
+ end
+ end
+ table.sort(diagList, function (a, b)
+ return (diagCosts[a] or 0) < (diagCosts[b] or 0)
+ end)
+ return diagList
+end
+
---@async
---@param uri uri
---@param isScopeDiag boolean
@@ -176,9 +168,12 @@ return function (uri, isScopeDiag, response, checked)
return nil
end
- for _, name in ipairs(diagList) do
+ for _, name in ipairs(buildDiagList()) do
await.delay()
+ local clock = os.clock()
check(uri, name, isScopeDiag, response)
+ local cost = os.clock() - clock
+ diagCosts[name] = (diagCosts[name] or 0) + cost
if checked then
checked(name)
end
diff --git a/script/core/diagnostics/invisible.lua b/script/core/diagnostics/invisible.lua
new file mode 100644
index 00000000..0bd369a4
--- /dev/null
+++ b/script/core/diagnostics/invisible.lua
@@ -0,0 +1,55 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local lang = require 'language'
+local vm = require 'vm.vm'
+local await = require 'await'
+
+local checkTypes = {'getfield', 'setfield', 'getmethod', 'setmethod', 'getindex', 'setindex'}
+
+---@async
+return function (uri, callback)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+
+ ---@async
+ guide.eachSourceTypes(state.ast, checkTypes, function (src)
+ local child = src.field or src.method or src.index
+ if not child then
+ return
+ end
+ local key = guide.getKeyName(src)
+ if not key then
+ return
+ end
+ await.delay()
+ local defs = vm.getDefs(src)
+ for _, def in ipairs(defs) do
+ if not vm.isVisible(src.node, def) then
+ if vm.getVisibleType(def) == 'private' then
+ callback {
+ start = child.start,
+ finish = child.finish,
+ uri = uri,
+ message = lang.script('DIAG_INVISIBLE_PRIVATE', {
+ field = key,
+ class = vm.getParentClass(def):getName(),
+ }),
+ }
+ else
+ callback {
+ start = child.start,
+ finish = child.finish,
+ uri = uri,
+ message = lang.script('DIAG_INVISIBLE_PROTECTED', {
+ field = key,
+ class = vm.getParentClass(def):getName(),
+ }),
+ }
+ end
+ break
+ end
+ end
+ end)
+end
diff --git a/script/proto/diagnostic.lua b/script/proto/diagnostic.lua
index f6645e89..be30bcec 100644
--- a/script/proto/diagnostic.lua
+++ b/script/proto/diagnostic.lua
@@ -184,6 +184,7 @@ m.register {
'close-non-object',
'deprecated',
'discard-returns',
+ 'invisible',
} {
group = 'strict',
severity = 'Warning',
diff --git a/test/diagnostics/common.lua b/test/diagnostics/common.lua
index f7cbbb0d..0231cc86 100644
--- a/test/diagnostics/common.lua
+++ b/test/diagnostics/common.lua
@@ -2081,3 +2081,64 @@ end
print(1)
]]
+
+TEST [[
+---@class A
+---@field private x number
+---@field protected y number
+---@field public z number
+local t
+print(t.x)
+]]
+
+TEST [[
+---@class A
+---@field private x number
+---@field protected y number
+---@field public z number
+
+---@type A
+local t
+
+print(t.<!x!>)
+]]
+
+TEST [[
+---@class A
+---@field private x number
+---@field protected y number
+---@field public z number
+
+---@class B: A
+local t
+
+print(t.y)
+]]
+
+TEST [[
+---@class A
+---@field private x number
+---@field protected y number
+---@field public z number
+
+---@class B: A
+
+---@type B
+local t
+
+print(t.<!y!>)
+]]
+
+TEST [[
+---@class A
+---@field private x number
+---@field protected y number
+---@field public z number
+
+---@class B: A
+
+---@type B
+local t
+
+print(t.z)
+]]