summaryrefslogtreecommitdiff
path: root/server/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/core')
-rw-r--r--server/src/core/completion.lua83
-rw-r--r--server/src/core/definition.lua205
-rw-r--r--server/src/core/diagnostics.lua27
-rw-r--r--server/src/core/implementation.lua21
4 files changed, 178 insertions, 158 deletions
diff --git a/server/src/core/completion.lua b/server/src/core/completion.lua
index 4a487441..d0da95cd 100644
--- a/server/src/core/completion.lua
+++ b/server/src/core/completion.lua
@@ -397,6 +397,14 @@ local function searchEmmyKeyword(vm, source, word, callback)
end
end
+local function searchEmmyClass(vm, source, word, callback)
+ vm.emmyMgr:eachClass(function (class)
+ if matchKey(word, class:getName()) then
+ callback(class:getName(), class:getSource(), CompletionItemKind.Class)
+ end
+ end)
+end
+
local function searchSource(vm, source, word, callback)
if source.type == 'keyword' then
searchAsKeyowrd(vm, source, word, callback)
@@ -430,6 +438,9 @@ local function searchSource(vm, source, word, callback)
searchEmmyKeyword(vm, source, word, callback)
return
end
+ if source:get 'target class' then
+ searchEmmyClass(vm, source, word, callback)
+ end
end
local function searchInRequire(vm, select, source, callback)
@@ -650,11 +661,9 @@ local function makeList(source, pos, word)
end, list
end
-local function searchToclose(text, word, callback, pos)
- if #word > 0 then
- pos = pos - 1
- end
- if text:sub(pos, pos) ~= '*' then
+local function searchToclose(text, source, word, callback)
+ local pos = source.start
+ if text:sub(pos-1, pos-1) ~= '*' then
return false
end
if not matchKey(word, 'toclose') then
@@ -685,7 +694,62 @@ local function keywordSource(vm, word, pos)
}
end
-return function (vm, text, pos, word, oldText)
+local function findStartPos(pos, buf)
+ local res = nil
+ for i = pos, 1, -1 do
+ local c = buf:sub(i, i)
+ if c:find '[%w_]' then
+ res = i
+ else
+ break
+ end
+ end
+ if not res then
+ for i = pos, 1, -1 do
+ local c = buf:sub(i, i)
+ if c == '.' or c == ':' or c == '|' then
+ res = i
+ break
+ elseif c == '#' or c == '@' then
+ res = i + 1
+ break
+ elseif c:find '[%s%c]' then
+ else
+ break
+ end
+ end
+ end
+ if not res then
+ return pos
+ end
+ return res
+end
+
+local function findWord(position, text)
+ local word = text
+ for i = position, 1, -1 do
+ local c = text:sub(i, i)
+ if not c:find '[%w_]' then
+ word = text:sub(i+1, position)
+ break
+ end
+ end
+ return word:match('^([%w_]*)')
+end
+
+local function getSource(vm, pos, text, filter)
+ local word = findWord(pos, text)
+ local source = findSource(vm, pos, filter)
+ if source then
+ return source, pos, word
+ end
+ pos = findStartPos(pos, text)
+ source = findSource(vm, pos, filter)
+ or keywordSource(vm, word, pos)
+ return source, pos, word
+end
+
+return function (vm, text, pos, oldText)
local filter = {
['name'] = true,
['string'] = true,
@@ -695,10 +759,7 @@ return function (vm, text, pos, word, oldText)
['emmyIncomplete'] = true,
['call'] = true,
}
- local source = findSource(vm, pos, filter)
- or findSource(vm, pos-1, filter)
- or findSource(vm, pos+1, filter)
- or keywordSource(vm, word, pos)
+ local source, pos, word = getSource(vm, pos, text, filter)
if not source then
return nil
end
@@ -709,7 +770,7 @@ return function (vm, text, pos, word, oldText)
end
end
local callback, list = makeList(source, pos, word)
- if searchToclose(text, word, callback, pos) then
+ if searchToclose(text, source, word, callback) then
return list
end
searchSpecial(vm, source, word, callback, pos)
diff --git a/server/src/core/definition.lua b/server/src/core/definition.lua
index a7296bfb..335d2185 100644
--- a/server/src/core/definition.lua
+++ b/server/src/core/definition.lua
@@ -1,9 +1,8 @@
-local function parseValueSimily(vm, source, lsp)
+local function parseValueSimily(callback, vm, source, lsp)
local key = source[1]
if not key then
return nil
end
- local positions = {}
vm:eachSource(function (other)
if other == source then
goto CONTINUE
@@ -14,140 +13,43 @@ local function parseValueSimily(vm, source, lsp)
and other:action() == 'set'
and source:bindValue() ~= other:bindValue()
then
- positions[#positions+1] = {
- other.start,
- other.finish,
- }
+ callback(other)
end
:: CONTINUE ::
end)
- if #positions == 0 then
- return nil
- end
- return positions
end
-local function parseValueCrossFile(vm, source, lsp)
+local function parseValueCrossFile(callback, vm, source, lsp)
local value = source:bindValue()
- local positions = {}
- value:eachInfo(function (info, src)
- if info.type == 'local' and src.uri == value.uri then
- positions[#positions+1] = {
- src.start,
- src.finish,
- value.uri,
- }
- return true
- end
- end)
- if #positions > 0 then
- return positions
- end
-
value:eachInfo(function (info, src)
- if info.type == 'set' and src.uri == value.uri then
- positions[#positions+1] = {
- src.start,
- src.finish,
- value.uri,
- }
- end
- end)
- if #positions > 0 then
- return positions
- end
-
- value:eachInfo(function (info, src)
- if info.type == 'return' and src.uri == value.uri then
- positions[#positions+1] = {
- src.start,
- src.finish,
- value.uri,
- }
+ if src.uri == value.uri then
+ if info.type == 'local' or info.type == 'set' or info.type == 'return' then
+ callback(src)
+ end
end
end)
- if #positions > 0 then
- return positions
- end
-
- local destVM = lsp:getVM(value.uri)
- if not destVM then
- positions[#positions+1] = {
- 0, 0, value.uri,
- }
- return positions
- end
-
- local result = parseValueSimily(destVM, source, lsp)
- if result then
- for _, position in ipairs(result) do
- positions[#positions+1] = position
- position[3] = value.uri
- end
- end
- if #positions > 0 then
- return positions
- end
-
return nil
end
-local function parseLocal(vm, source, lsp)
+local function parseLocal(callback, vm, source, lsp)
local positions = {}
local loc = source:bindLocal()
local locSource = loc:getSource()
- if locSource:get 'arg' then
- positions[#positions+1] = {
- locSource.start,
- locSource.finish,
- locSource:getUri(),
- }
- return positions
- end
+ --if locSource:get 'arg' then
+ -- callback(locSource)
+ --end
local value = source:bindValue()
if value and value.uri ~= '' and value.uri ~= vm.uri then
- local positions = parseValueCrossFile(vm, source, lsp)
- if positions and #positions > 0 then
- return positions
- end
+ parseValueCrossFile(callback, vm, source, lsp)
end
- positions[#positions+1] = {
- locSource.start,
- locSource.finish,
- locSource:getUri(),
- }
+ callback(locSource)
if #positions == 0 then
return nil
end
return positions
end
-local function parseValue(vm, source, lsp)
- local positions = {}
- local mark = {}
-
- local function callback(src)
- if source == src then
- return
- end
- if mark[src] then
- return
- end
- mark[src] = true
- if src.start == 0 then
- return
- end
- local uri = src.uri
- if uri == '' then
- uri = nil
- end
- positions[#positions+1] = {
- src.start,
- src.finish,
- uri,
- }
- end
-
+local function parseValue(callback, vm, source, lsp)
if source:bindValue() then
source:bindValue():eachInfo(function (info, src)
if info.type == 'set' or info.type == 'local' or info.type == 'return' then
@@ -165,56 +67,79 @@ local function parseValue(vm, source, lsp)
end
end)
end
- if #positions == 0 then
- return nil
- end
- return positions
end
-local function parseLabel(vm, label, lsp)
- local positions = {}
+local function parseLabel(callback, vm, label, lsp)
label:eachInfo(function (info, src)
if info.type == 'set' then
- positions[#positions+1] = {
- src.start,
- src.finish,
- }
+ callback(src)
end
end)
- if #positions == 0 then
- return nil
- end
- return positions
end
-local function jumpUri(vm, source, lsp)
+local function jumpUri(callback, vm, source, lsp)
local uri = source:get 'target uri'
- local positions = {}
- positions[#positions+1] = {
- 0, 0, uri,
+ callback {
+ start = 0,
+ finish = 0,
+ uri = uri
}
- return positions
+end
+
+local function parseClass(callback, vm, source)
+ local className = source:get 'target class'
+ vm.emmyMgr:eachClass(className, function (class)
+ local src = class:getSource()
+ callback(src)
+ end)
+end
+
+local function makeList(source)
+ local list = {}
+ local mark = {}
+ return list, function (src)
+ if source == src then
+ return
+ end
+ if mark[src] then
+ return
+ end
+ mark[src] = true
+ local uri = src.uri
+ if uri == '' then
+ uri = nil
+ end
+ list[#list+1] = {
+ src.start,
+ src.finish,
+ src.uri
+ }
+ end
end
return function (vm, source, lsp)
if not source then
return nil
end
+ local list, callback = makeList(source)
if source:bindLocal() then
- return parseLocal(vm, source, lsp)
- end
- if source:bindValue() then
- return parseValue(vm, source, lsp)
- or parseValueSimily(vm, source, lsp)
+ parseLocal(callback, vm, source, lsp)
+ elseif source:bindValue() then
+ parseValue(callback, vm, source, lsp)
+ --parseValueSimily(callback, vm, source, lsp)
end
if source:bindLabel() then
- return parseLabel(vm, source:bindLabel(), lsp)
+ parseLabel(callback, vm, source:bindLabel(), lsp)
end
if source:get 'target uri' then
- return jumpUri(vm, source, lsp)
+ jumpUri(callback, vm, source, lsp)
end
if source:get 'in index' then
- return parseValue(vm, source, lsp)
- or parseValueSimily(vm, source, lsp)
+ parseValue(callback, vm, source, lsp)
+ --parseValueSimily(callback, vm, source, lsp)
+ end
+ if source:get 'target class' then
+ parseClass(callback, vm, source)
end
+ return list
end
diff --git a/server/src/core/diagnostics.lua b/server/src/core/diagnostics.lua
index d49f8da2..0732b7e3 100644
--- a/server/src/core/diagnostics.lua
+++ b/server/src/core/diagnostics.lua
@@ -439,10 +439,6 @@ function mt:checkEmmyClass(source, callback)
local related = {}
local current = class
for _ = 1, 10 do
- if parent:getName() == class:getName() then
- callback(source.start, source.finish, lang.script.DIAG_CYCLIC_EXTENDS, related)
- break
- end
local extends = current.extends
if not extends then
break
@@ -452,20 +448,37 @@ function mt:checkEmmyClass(source, callback)
finish = current:getSource().finish,
uri = current:getSource().uri,
}
- current = parent
- parent = self.vm.emmyMgr:eachClass(extends, function (parent)
+ current = self.vm.emmyMgr:eachClass(extends, function (parent)
return parent
end)
- if not parent then
+ if not current then
+ break
+ end
+ if current:getName() == class:getName() then
+ callback(source.start, source.finish, lang.script.DIAG_CYCLIC_EXTENDS, related)
break
end
end
end
+function mt:checkEmmyType(source, callback)
+ for _, tpsource in ipairs(source) do
+ local name = tpsource[1]
+ local class = self.vm.emmyMgr:eachClass(name, function (class)
+ return class
+ end)
+ if not class then
+ callback(tpsource.start, tpsource.finish, lang.script.DIAG_UNDEFINED_CLASS)
+ end
+ end
+end
+
function mt:searchEmmyLua(callback)
self.vm:eachSource(function (source)
if source.type == 'emmyClass' then
self:checkEmmyClass(source, callback)
+ elseif source.type == 'emmyType' then
+ self:checkEmmyType(source, callback)
end
end)
end
diff --git a/server/src/core/implementation.lua b/server/src/core/implementation.lua
index 1b8006b1..450b9a0c 100644
--- a/server/src/core/implementation.lua
+++ b/server/src/core/implementation.lua
@@ -166,6 +166,20 @@ local function jumpUri(vm, source, lsp)
return positions
end
+local function parseClass(vm, source)
+ local className = source:get 'target class'
+ local positions = {}
+ vm.emmyMgr:eachClass(className, function (class)
+ local src = class:getSource()
+ positions[#positions+1] = {
+ src.start,
+ src.finish,
+ src.uri,
+ }
+ end)
+ return positions
+end
+
return function (vm, source, lsp)
if not source then
return nil
@@ -180,4 +194,11 @@ return function (vm, source, lsp)
if source:get 'target uri' then
return jumpUri(vm, source, lsp)
end
+ if source:get 'in index' then
+ return parseValue(vm, source, lsp)
+ or parseValueSimily(vm, source, lsp)
+ end
+ if source:get 'target class' then
+ return parseClass(vm, source)
+ end
end