Skip to content
Snippets Groups Projects
Commit 22d7f6c2 authored by 最萌小汐's avatar 最萌小汐
Browse files

resolve #624 `different-requires`

parent fdab3eae
Branches
No related tags found
No related merge requests found
......@@ -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`
......
......@@ -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.'
......
......@@ -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 = '字段必须定义在类之后。'
......
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
......@@ -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
......
......@@ -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',
......
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"',
},
}
......@@ -3,3 +3,4 @@ require 'crossfile.references'
require 'crossfile.allreferences'
require 'crossfile.hover'
require 'crossfile.completion'
require 'crossfile.diagnostic'
......@@ -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'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment