From 2caf08855f99bbf816708a1497512d16b631289a Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 6 Nov 2016 11:19:59 +0100 Subject: nimsuggest supports include files properly; added the compiler itself as a testcase --- compiler/modulegraphs.nim | 18 +++++++++++++++++- compiler/modules.nim | 1 + tools/nimsuggest/nimsuggest.nim | 10 ++++------ tools/nimsuggest/tests/tinclude.nim | 7 +++++++ 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 tools/nimsuggest/tests/tinclude.nim diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 2c1671789..9a3caa663 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -25,7 +25,7 @@ ## - Its dependent module stays the same. ## -import ast, intsets +import ast, intsets, tables type ModuleGraph* = ref object @@ -34,6 +34,8 @@ type deps*: IntSet # the dependency graph or potentially its transitive closure. suggestMode*: bool # whether we are in nimsuggest mode or not. invalidTransitiveClosure: bool + inclToMod*: Table[int32, int32] # mapping of include file to the + # first module that included it {.this: g.} @@ -42,11 +44,13 @@ proc newModuleGraph*(): ModuleGraph = initStrTable(result.packageSyms) result.deps = initIntSet() result.modules = @[] + result.inclToMod = initTable[int32, int32]() proc resetAllModules*(g: ModuleGraph) = initStrTable(packageSyms) deps = initIntSet() modules = @[] + inclToMod = initTable[int32, int32]() proc getModule*(g: ModuleGraph; fileIdx: int32): PSym = if fileIdx >= 0 and fileIdx < modules.len: @@ -61,6 +65,18 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: int32) = # this improve efficiency quite a lot: invalidTransitiveClosure = true +proc addIncludeDep*(g: ModuleGraph; module, includeFile: int32) = + discard hasKeyOrPut(inclToMod, includeFile, module) + +proc parentModule*(g: ModuleGraph; fileIdx: int32): int32 = + ## returns 'fileIdx' if the file belonging to this index is + ## directly used as a module or else the module that first + ## references this include file. + if fileIdx >= 0 and fileIdx < modules.len and modules[fileIdx] != nil: + result = fileIdx + else: + result = inclToMod.getOrDefault(fileIdx) + proc transitiveClosure(g: var IntSet; n: int) = # warshall's algorithm for k in 0..= 2: graph.symFromInfo(gTrackPos) else: usageSym if u != nil: diff --git a/tools/nimsuggest/tests/tinclude.nim b/tools/nimsuggest/tests/tinclude.nim new file mode 100644 index 000000000..77492d745 --- /dev/null +++ b/tools/nimsuggest/tests/tinclude.nim @@ -0,0 +1,7 @@ +discard """ +$nimsuggest --tester compiler/nim.nim +>def compiler/semexprs.nim:13:50 +def;;skType;;ast.PSym;;PSym;;*ast.nim;;668;;2;;"";;100 +>def compiler/semexprs.nim:13:50 +def;;skType;;ast.PSym;;PSym;;*ast.nim;;668;;2;;"";;100 +""" -- cgit 1.4.1-2-gfad0 0'>20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92



























































































                                                                                           
local _M = {}

if module then
    mbox = _M
end 

function _M.split_message(message_s)
    local message = {}
    message_s = string.gsub(message_s, "\r\n", "\n")
    string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
    string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
    if not message.body then
        string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
    end
    if not message.headers and not message.body then
        message.headers = message_s
    end
    return message.headers or "", message.body or ""
end

function _M.split_headers(headers_s)
    local headers = {}
    headers_s = string.gsub(headers_s, "\r\n", "\n")
    headers_s = string.gsub(headers_s, "\n[ ]+", " ")
    string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(headers, h) end)
    return headers
end

function _M.parse_header(header_s)
    header_s = string.gsub(header_s, "\n[ ]+", " ")
    header_s = string.gsub(header_s, "\n+", "")
    local _, __, name, value = string.find(header_s, "([^%s:]-):%s*(.*)")
    return name, value
end

function _M.parse_headers(headers_s)
    local headers_t = _M.split_headers(headers_s)
    local headers = {}
    for i = 1, #headers_t do
        local name, value = _M.parse_header(headers_t[i])
        if name then
            name = string.lower(name)
            if headers[name] then
                headers[name] = headers[name] .. ", " .. value
            else headers[name] = value end
        end
    end
    return headers
end

function _M.parse_from(from)
    local _, __, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>")
    if not address then
        _, __, address = string.find(from, "%s*(.+)%s*")
    end
    name = name or ""
    address = address or ""
    if name == "" then name = address end
    name = string.gsub(name, '"', "")
    return name, address
end

function _M.split_mbox(mbox_s)
    local mbox = {}
    mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
    local nj, i, j = 1, 1, 1
    while 1 do
        i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
        if not i then break end
        local message = string.sub(mbox_s, j, i-1)
        table.insert(mbox, message)
        j = nj+1
    end
    return mbox
end

function _M.parse(mbox_s)
    local mbox = _M.split_mbox(mbox_s)
    for i = 1, #mbox do
        mbox[i] = _M.parse_message(mbox[i])
    end
    return mbox
end

function _M.parse_message(message_s)
    local message = {}
    message.headers, message.body = _M.split_message(message_s)
    message.headers = _M.parse_headers(message.headers)
    return message
end

return _M