summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--locale/en-us/script.lua1
-rw-r--r--locale/zh-cn/script.lua1
-rw-r--r--script/core/diagnostics/different-requires.lua52
-rw-r--r--script/parser/guide.lua3
-rw-r--r--script/proto/define.lua2
-rw-r--r--test/crossfile/diagnostic.lua137
-rw-r--r--test/crossfile/init.lua1
-rw-r--r--test/diagnostics/init.lua1
9 files changed, 199 insertions, 1 deletions
diff --git a/changelog.md b/changelog.md
index ed39ed42..f5f9eac0 100644
--- a/changelog.md
+++ b/changelog.md
@@ -6,6 +6,8 @@
+ `Lua.diagnostics.ignoredFiles`
+ `Lua.completion.showWord`
+ `Lua.completion.requireSeparator`
+* `NEW` diagnostics:
+ + `different-requires`
* `CHG` hover: improve showing multi defines
* `CHG` hover: improve showing multi comments at enums
* `CHG` hint: `Lua.hint.paramName` now supports `Disable`, `Literal` and `All`
diff --git a/locale/en-us/script.lua b/locale/en-us/script.lua
index 35e1df8f..16a66b0a 100644
--- a/locale/en-us/script.lua
+++ b/locale/en-us/script.lua
@@ -41,6 +41,7 @@ DIAG_COSE_NON_OBJECT = 'Cannot close a value of this type. (Unless set `__clo
DIAG_COUNT_DOWN_LOOP = 'Do you mean `{}` ?'
DIAG_IMPLICIT_ANY = 'Can not infer type.'
DIAG_DEPRECATED = 'Deprecated.'
+DIAG_DIFFERENT_REQUIRES = 'The same file is required with different names.'
DIAG_CIRCLE_DOC_CLASS = 'Circularly inherited classes.'
DIAG_DOC_FIELD_NO_CLASS = 'The field must be defined after the class.'
diff --git a/locale/zh-cn/script.lua b/locale/zh-cn/script.lua
index 94787304..f1e9d95f 100644
--- a/locale/zh-cn/script.lua
+++ b/locale/zh-cn/script.lua
@@ -41,6 +41,7 @@ DIAG_COSE_NON_OBJECT = '无法 close 此类型的值。(除非给此类型
DIAG_COUNT_DOWN_LOOP = '你的意思是 `{}` 吗?'
DIAG_IMPLICIT_ANY = '无法推测出类型。'
DIAG_DEPRECATED = '已废弃。'
+DIAG_DIFFERENT_REQUIRES = '使用了不同的名字 require 了同一个文件。'
DIAG_CIRCLE_DOC_CLASS = '循环继承的类。'
DIAG_DOC_FIELD_NO_CLASS = '字段必须定义在类之后。'
diff --git a/script/core/diagnostics/different-requires.lua b/script/core/diagnostics/different-requires.lua
new file mode 100644
index 00000000..9e3dfc8f
--- /dev/null
+++ b/script/core/diagnostics/different-requires.lua
@@ -0,0 +1,52 @@
+local files = require 'files'
+local guide = require 'parser.guide'
+local lang = require 'language'
+local config = require 'config'
+local vm = require 'vm'
+local ws = require 'workspace'
+
+return function (uri, callback)
+ local state = files.getState(uri)
+ if not state then
+ return
+ end
+ local cache = vm.getCache 'different-requires'
+ guide.eachSpecialOf(state.ast, 'require', function (source)
+ local call = source.next
+ if not call or call.type ~= 'call' then
+ return
+ end
+ local arg1 = call.args and call.args[1]
+ if not arg1 or arg1.type ~= 'string' then
+ return
+ end
+ local literal = arg1[1]
+ local results = ws.findUrisByRequirePath(literal)
+ local result = results and results[1]
+ if not result then
+ return
+ end
+ local other = cache[result]
+ if not other then
+ cache[result] = {
+ source = arg1,
+ require = literal,
+ }
+ return
+ end
+ if other.require ~= literal then
+ callback {
+ start = arg1.start,
+ finish = arg1.finish,
+ related = {
+ {
+ start = other.source.start,
+ finish = other.source.finish,
+ uri = guide.getUri(other.source),
+ }
+ },
+ message = lang.script('DIAG_DIFFERENT_REQUIRES'),
+ }
+ end
+ end)
+end
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index 378d2613..6dcfbf95 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -722,6 +722,9 @@ function m.eachSource(ast, callback)
end
--- 获取指定的 special
+---@param ast parser.guide.object
+---@param name string
+---@param callback fun(source: parser.guide.object)
function m.eachSpecialOf(ast, name, callback)
local root = m.getRoot(ast)
if not root.specials then
diff --git a/script/proto/define.lua b/script/proto/define.lua
index a07a3903..9fbbea35 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -74,6 +74,7 @@ m.DiagnosticDefaultSeverity = {
['count-down-loop'] = 'Warning',
['no-implicit-any'] = 'Information',
['deprecated'] = 'Warning',
+ ['different-requires'] = 'Warning',
['duplicate-doc-class'] = 'Warning',
['undefined-doc-class'] = 'Warning',
@@ -125,6 +126,7 @@ m.DiagnosticDefaultNeededFileStatus = {
['count-down-loop'] = 'Any',
['no-implicit-any'] = 'None',
['deprecated'] = 'Opened',
+ ['different-requires'] = 'Any',
['duplicate-doc-class'] = 'Any',
['undefined-doc-class'] = 'Any',
diff --git a/test/crossfile/diagnostic.lua b/test/crossfile/diagnostic.lua
new file mode 100644
index 00000000..3d4eb552
--- /dev/null
+++ b/test/crossfile/diagnostic.lua
@@ -0,0 +1,137 @@
+local files = require 'files'
+local furi = require 'file-uri'
+local core = require 'core.diagnostics'
+local config = require 'config'
+local platform = require 'bee.platform'
+
+config.get 'Lua.diagnostics.neededFileStatus'['deprecated'] = 'Any'
+
+rawset(_G, 'TEST', true)
+
+local function catch_target(script, sep)
+ local list = {}
+ local cur = 1
+ local cut = 0
+ while true do
+ local start, finish = script:find(('<%%%s.-%%%s>'):format(sep, sep), cur)
+ if not start then
+ break
+ end
+ list[#list+1] = { start - cut, finish - 4 - cut }
+ cur = finish + 1
+ cut = cut + 4
+ end
+ local new_script = script:gsub(('<%%%s(.-)%%%s>'):format(sep, sep), '%1')
+ return new_script, list
+end
+
+local function founded(targets, results)
+ if #targets ~= #results then
+ return false
+ end
+ for _, target in ipairs(targets) do
+ for _, result in ipairs(results) do
+ if target[1] == result[1]
+ and target[2] == result[2]
+ and target[3] == result[3]
+ then
+ goto NEXT
+ end
+ end
+ do return false end
+ ::NEXT::
+ end
+ return true
+end
+
+function TEST(datas)
+ files.removeAll()
+
+ local targetList = {}
+ local sourceUri
+ for _, data in ipairs(datas) do
+ local uri = furi.encode(data.path)
+ local new, list = catch_target(data.content, '!')
+ for _, position in ipairs(list) do
+ targetList[#targetList+1] = {
+ position[1],
+ position[2],
+ uri,
+ }
+ end
+ data.content = new
+ files.setText(uri, new)
+ end
+
+ local result = {}
+ for _, data in ipairs(datas) do
+ local uri = furi.encode(data.path)
+ local results = {}
+ core(uri, function (result)
+ for _, res in ipairs(result) do
+ results[#results+1] = res
+ end
+ end)
+ for i, position in ipairs(results) do
+ result[i] = {
+ position.start,
+ position.finish,
+ uri,
+ }
+ end
+ end
+ assert(founded(targetList, result))
+end
+
+TEST {
+ {
+ path = 'f/a.lua',
+ content = '',
+ },
+ {
+ path = 'b.lua',
+ content = 'require "a"',
+ },
+ {
+ path = 'c.lua',
+ content = 'require <!"f.a"!>',
+ },
+}
+
+TEST {
+ {
+ path = 'f/a.lua',
+ content = '',
+ },
+ {
+ path = 'a.lua',
+ content = '',
+ },
+ {
+ path = 'b.lua',
+ content = 'require "a"',
+ },
+ {
+ path = 'c.lua',
+ content = 'require "f.a"',
+ },
+}
+
+TEST {
+ {
+ path = 'a.lua',
+ content = '',
+ },
+ {
+ path = 'f/a.lua',
+ content = '',
+ },
+ {
+ path = 'b.lua',
+ content = 'require "a"',
+ },
+ {
+ path = 'c.lua',
+ content = 'require "f.a"',
+ },
+}
diff --git a/test/crossfile/init.lua b/test/crossfile/init.lua
index a7402815..1ed2a943 100644
--- a/test/crossfile/init.lua
+++ b/test/crossfile/init.lua
@@ -3,3 +3,4 @@ require 'crossfile.references'
require 'crossfile.allreferences'
require 'crossfile.hover'
require 'crossfile.completion'
+require 'crossfile.diagnostic'
diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua
index b90b4b26..54ac73ef 100644
--- a/test/diagnostics/init.lua
+++ b/test/diagnostics/init.lua
@@ -2,7 +2,6 @@ local core = require 'core.diagnostics'
local files = require 'files'
local config = require 'config'
local util = require 'utility'
-local define = require 'proto.define'
config.get 'Lua.diagnostics.neededFileStatus'['deprecated'] = 'Any'