julia-vscode / SymbolServer.jl
1
using LibGit2, InteractiveUtils
2

3
mutable struct Server
4 35
    storedir::String
5
    context::Pkg.Types.Context
6
    depot::Dict
7
end
8

9
abstract type SymStore end
10
struct ModuleStore <: SymStore
11 35
    name::VarRef
12
    vals::Dict{Symbol,Any}
13
    doc::String
14
    exported::Bool
15
    exportednames::Vector{Symbol}
16
    used_modules::Vector{Symbol}
17
end
18

19 35
ModuleStore(m) = ModuleStore(VarRef(m), Dict{Symbol,Any}(), "", true, unsorted_names(m), Symbol[])
20 35
Base.getindex(m::ModuleStore, k) = m.vals[k]
21 35
Base.setindex!(m::ModuleStore, v, k) = (m.vals[k] = v)
22 35
Base.haskey(m::ModuleStore, k) = haskey(m.vals, k)
23

24
const EnvStore = Dict{Symbol,ModuleStore}
25

26
struct Package
27 35
    name::String
28
    val::ModuleStore
29
    uuid::Base.UUID
30
    sha::Union{Vector{UInt8},Nothing}
31
end
32 0
Package(name::String, val::ModuleStore, uuid::String, sha) = Package(name, val, Base.UUID(uuid), sha)
33

34
struct MethodStore
35 35
    name::Symbol
36
    mod::Symbol
37
    file::String
38
    line::Int32
39
    sig::Vector{Pair{Any,Any}}
40
    kws::Vector{Symbol}
41
    rt::Any
42
end
43

44
struct DataTypeStore <: SymStore
45 35
    name::FakeTypeName
46
    super::FakeTypeName
47
    parameters::Vector{Any}
48
    types::Vector{Any}
49
    fieldnames::Vector{Any}
50
    methods::Vector{MethodStore}
51
    doc::String
52
    exported::Bool
53
end
54

55 10
function DataTypeStore(@nospecialize(t), parent_mod, exported)
56 35
    ur_t = Base.unwrap_unionall(t)
57 35
    parameters = if isdefined(ur_t, :parameters)
58 35
        map(ur_t.parameters) do p
59 20
            _parameter(p)
60
        end
61
    else
62 35
        []
63
    end
64 35
    types = if isdefined(ur_t, :types)
65 35
        map(ur_t.types) do p
66 20
            FakeTypeName(p)
67
        end
68
    else
69 35
        []
70
    end
71 35
    DataTypeStore(FakeTypeName(ur_t), FakeTypeName(ur_t.super), parameters, types, isconcretetype(ur_t) && fieldcount(ur_t) > 0 ? collect(fieldnames(ur_t)) : Symbol[], MethodStore[], _doc(t), exported)
72
end
73

74
struct FunctionStore <: SymStore
75 35
    name::VarRef
76
    methods::Vector{MethodStore}
77
    doc::String
78
    extends::VarRef
79
    exported::Bool
80
end
81

82 10
function FunctionStore(@nospecialize(f), parent_mod, exported)
83 35
    if f isa Core.IntrinsicFunction
84 35
        FunctionStore(VarRef(VarRef(Core.Intrinsics), nameof(f)), MethodStore[], _doc(f), VarRef(VarRef(parentmodule(f)), nameof(f)), exported)
85
    else
86 35
        FunctionStore(VarRef(VarRef(parent_mod), nameof(f)), MethodStore[], _doc(f), VarRef(VarRef(parentmodule(f)), nameof(f)), exported)
87
    end
88
end
89

90
struct GenericStore <: SymStore
91 35
    name::VarRef
92
    typ::Any
93
    doc::String
94
    exported::Bool
95
end
96

97
# adapted from https://github.com/timholy/CodeTracking.jl/blob/afc73a957f5034cc7f02e084a91283c47882f92b/src/utils.jl#L87-L122
98

99
"""
100
    path = maybe_fix_path(path)
101

102
Return a normalized, absolute path for a source file `path`.
103
"""
104 10
function maybe_fix_path(file)
105 35
    if !isabspath(file)
106
        # This may be a Base or Core method
107 35
        newfile = Base.find_source_file(file)
108 35
        if isa(newfile, AbstractString)
109 35
            file = normpath(newfile)
110
        end
111
    end
112 35
    return maybe_fixup_stdlib_path(file)
113
end
114

115 35
safe_isfile(x) = try isfile(x); catch; false end
116
const BUILDBOT_STDLIB_PATH = dirname(abspath(joinpath(String((@which versioninfo()).file), "..", "..", "..")))
117 35
replace_buildbot_stdlibpath(str::String) = replace(str, BUILDBOT_STDLIB_PATH => Sys.STDLIB)
118
"""
119
    path = maybe_fixup_stdlib_path(path::String)
120

121
Return `path` corrected for julia issue [#26314](https://github.com/JuliaLang/julia/issues/26314) if applicable.
122
Otherwise, return the input `path` unchanged.
123

124
Due to the issue mentioned above, location info for methods defined one of Julia's standard libraries
125
are, for non source Julia builds, given as absolute paths on the worker that built the `julia` executable.
126
This function corrects such a path to instead refer to the local path on the users drive.
127
"""
128
function maybe_fixup_stdlib_path(path)
129 35
    if !safe_isfile(path)
130 35
        maybe_stdlib_path = replace_buildbot_stdlibpath(path)
131 35
        safe_isfile(maybe_stdlib_path) && return maybe_stdlib_path
132
    end
133 35
    return path
134
end
135

136
const _global_method_cache = IdDict{Any,Vector{Any}}()
137 5
function methodinfo(@nospecialize(f); types = Tuple, world = typemax(UInt))
138 35
    key = (f, types, world)
139 35
    cached = get(_global_method_cache, key, nothing)
140 35
    if cached === nothing
141 30
        cached = Base._methods(f, types, -1, world)
142 35
        _global_method_cache[key] = cached
143
    end
144 35
    return cached
145
end
146

147 0
function methodlist(@nospecialize(f))
148 0
    ms = methodinfo(f)
149 0
    Method[x[3]::Method for x in ms]
150
end
151

152 0
function sparam_syms(meth::Method)
153 0
    s = Symbol[]
154 0
    sig = meth.sig
155 0
    while sig isa UnionAll
156 0
        push!(s, Symbol(sig.var.name))
157 0
        sig = sig.body
158
    end
159 0
    return s
160
end
161

162 10
function cache_methods(@nospecialize(f), name, env, get_return_type)
163 35
    if isa(f, Core.Builtin)
164 35
        return MethodStore[]
165
    end
166 25
    types = Tuple
167 10
    world = typemax(UInt)
168 30
    ms = Tuple{Module,MethodStore}[]
169 35
    methods0 = try
170 35
        methodinfo(f; types = types, world = world)
171
    catch err
172 35
        return ms
173
    end
174 30
    ind_of_method_w_kws = Int[] # stores the index of methods with kws.
175 10
    i = 1
176 35
    for m in methods0
177
        # Get inferred method return type
178 35
        if get_return_type
179 0
            sparams = Core.svec(sparam_syms(m[3])...)
180 0
            rt = try 
181 0
                @static if isdefined(Core.Compiler, :NativeInterpreter)
182 0
                Core.Compiler.typeinf_type(Core.Compiler.NativeInterpreter(), m[3], m[3].sig, sparams)
183
            else
184 0
                Core.Compiler.typeinf_type(m[3], m[3].sig, sparams, Core.Compiler.Params(world))
185
            end
186
            catch e
187 0
                Any
188
            end
189
        else
190 35
            rt = Any
191
        end
192 35
        file = maybe_fix_path(String(m[3].file))
193 35
        MS = MethodStore(m[3].name, nameof(m[3].module), file, m[3].line, [], Symbol[], FakeTypeName(rt))
194
        # Get signature
195 35
        sig = Base.unwrap_unionall(m[1])
196 35
        argnames = getargnames(m[3])
197 35
        for i = 2:m[3].nargs
198 35
            push!(MS.sig, argnames[i] => FakeTypeName(sig.parameters[i]))
199
        end
200 35
        kws = getkws(m[3])
201 35
        if !isempty(kws)
202 30
            push!(ind_of_method_w_kws, i)
203
        end
204 35
        for kw in kws
205 35
            push!(MS.kws, kw)
206
        end
207 35
        push!(ms, (m[3].module, MS))
208 35
        i += 1
209
    end
210
    # Go back and add kws to methods defined in the same place as others with kws.
211 35
    for i in ind_of_method_w_kws
212 35
        for j = 1:length(ms) # only need to go up to `i`?
213 35
            if ms[j][2].file == ms[i][2].file && ms[j][2].line == ms[i][2].line && isempty(ms[j][2].kws)
214 35
                for kw in ms[i][2].kws
215 35
                    push!(ms[j][2].kws, kw)
216
                end
217
            end
218
        end
219
    end
220

221 35
    func_vr = VarRef(VarRef(parentmodule(f)), name)
222 35
    for i = 1:length(ms)
223 35
        mvr = VarRef(ms[i][1])
224 35
        modstore = _lookup(mvr, env)
225 35
        if modstore !== nothing
226 35
            if !haskey(modstore, name)
227 35
                modstore[name] = FunctionStore(VarRef(mvr, name), MethodStore[ms[i][2]], "", func_vr, false)
228 35
            elseif !(modstore[name] isa DataTypeStore || modstore[name] isa FunctionStore)
229 35
                modstore[name] = FunctionStore(VarRef(mvr, name), MethodStore[ms[i][2]], "", func_vr, false)
230
            else
231 35
                push!(modstore[name].methods, ms[i][2])
232
            end
233
        else
234 35
        end
235
    end
236 35
    return ms
237
end
238

239 35
getargnames(m::Method) = Base.method_argnames(m)
240
@static if length(first(methods(Base.kwarg_decl)).sig.parameters) == 2
241
    getkws = Base.kwarg_decl
242
else
243 0
    function getkws(m::Method)
244 20
        sig = Base.unwrap_unionall(m.sig)
245 20
        length(sig.parameters) == 0 && return []
246 20
        sig.parameters[1] isa Union && return []
247 20
        !isdefined(Base.unwrap_unionall(sig.parameters[1]), :name) && return []
248 20
        fname = Base.unwrap_unionall(sig.parameters[1]).name
249 20
        if isdefined(fname.mt, :kwsorter)
250 20
            Base.kwarg_decl(m, typeof(fname.mt.kwsorter))
251
        else
252 20
            []
253
        end
254
    end
255
end
256

257 0
function apply_to_everything(f, m = nothing, visited = Base.IdSet{Module}())
258 0
    if m isa Module
259 0
        push!(visited, m)
260 0
        for s in unsorted_names(m, all = true, imported = true)
261 0
            (!isdefined(m, s) || s == nameof(m)) && continue
262 0
            x = getfield(m, s)
263 0
            f(x)
264 0
            if x isa Module && !in(x, visited)
265 0
                apply_to_everything(f, x, visited)
266
            end
267
        end
268
    else
269 0
        for m in Base.loaded_modules_array()
270 0
            in(m, visited) || apply_to_everything(f, m, visited)
271
        end
272
    end
273
end
274

275

276

277 10
function oneverything(f, m = nothing, visited = Base.IdSet{Module}())
278 35
    if m isa Module
279 30
        push!(visited, m)
280 35
        state = nothing
281 35
        for s in unsorted_names(m, all = true, imported = true)
282 35
            !isdefined(m, s) && continue
283 35
            x = getfield(m, s)
284 35
            state = f(m, s, x, state)
285 35
            if x isa Module && !in(x, visited)
286 35
                oneverything(f, x, visited)
287
            end
288
        end
289
    else
290 35
        for m in Base.loaded_modules_array()
291 35
            in(m, visited) || oneverything(f, m, visited)
292
        end
293
    end
294
end
295

296
const _global_symbol_cache_by_mod = IdDict{Module,Base.IdSet{Symbol}}()
297 10
function build_namecache(m, s, @nospecialize(x), state::Union{Base.IdSet{Symbol},Nothing} = nothing)
298 35
    if state === nothing
299 35
        state = get(_global_symbol_cache_by_mod, m, nothing)
300 35
        if state === nothing
301 35
            state = _global_symbol_cache_by_mod[m] = Base.IdSet{Symbol}()
302
        end
303
    end
304 35
    push!(state, s)
305
end
306

307 5
function getnames(m::Module)
308 35
    cache = get(_global_symbol_cache_by_mod, m, nothing)
309 35
    if cache === nothing
310 35
        oneverything(build_namecache, m)
311 35
        cache = _global_symbol_cache_by_mod[m]
312
    end
313 35
    return cache
314
end
315

316
function allmodulenames()
317 30
    symbols = Base.IdSet{Symbol}()
318 35
    oneverything((m, s, x, state) -> (x isa Module && push!(symbols, s); return state))
319 10
    return symbols
320
end
321

322 0
function allthingswithmethods()
323 0
    symbols = Base.IdSet{Any}()
324 0
    oneverything(function (m, s, x, state)
325 0
        if !Base.isvarargtype(x) && !isempty(methodlist(x))
326 0
            push!(symbols, x)
327
        end
328 0
        return state
329
    end)
330 0
    return symbols
331
end
332

333 0
function allmethods()
334 0
    ms = Method[]
335 0
    oneverything(function (m, s, x, state)
336 0
        if !Base.isvarargtype(x) && !isempty(methodlist(x))
337 0
            append!(ms, methodlist(x))
338
        end
339 0
        return state
340
    end)
341 0
    return ms
342
end
343

344 35
usedby(outer, inner) = outer !== inner && isdefined(outer, nameof(inner)) && getproperty(outer, nameof(inner)) === inner && all(isdefined(outer, name) || !isdefined(inner, name) for name in unsorted_names(inner))
345 35
istoplevelmodule(m) = parentmodule(m) === m || parentmodule(m) === Main
346

347 10
function getmoduletree(m::Module, amn, visited = Base.IdSet{Module}())
348 35
    push!(visited, m)
349 30
    cache = ModuleStore(m)
350 35
    for s in unsorted_names(m, all = true, imported = true)
351 35
        !isdefined(m, s) && continue
352 35
        x = getfield(m, s)
353 35
        if x isa Module
354 35
            if istoplevelmodule(x)
355 35
                cache[s] = VarRef(x)
356 35
            elseif m === parentmodule(x)
357 35
                cache[s] = getmoduletree(x, amn, visited)
358
            else
359 35
                cache[s] = VarRef(x)
360
            end
361
        end
362
    end
363 35
    for n in amn
364 35
        if n !== nameof(m) && isdefined(m, n)
365 35
            x = getfield(m, n)
366 35
            if x isa Module
367 35
                if !haskey(cache, n)
368 35
                    cache[n] = VarRef(x)
369
                end
370 35
                if x !== Main && usedby(m, x)
371 35
                    push!(cache.used_modules, n)
372
                end
373
            end
374
        end
375
    end
376 35
    cache
377
end
378

379 10
function getenvtree(names = nothing)
380 35
    amn = allmodulenames()
381 35
    EnvStore(nameof(m) => getmoduletree(m, amn) for m in Base.loaded_modules_array() if names === nothing || nameof(m) in names)
382
end
383

384
# faster and more correct split_module_names
385 35
all_names(m) = all_names(m, x -> isdefined(m, x))
386 10
function all_names(m, pred, symbols = Set(Symbol[]), seen = Set(Module[]))
387 35
    push!(seen, m)
388 30
    ns = unsorted_names(m; all = true, imported = false)
389 35
    for n in ns
390 35
        isdefined(m, n) || continue
391 35
        Base.isdeprecated(m, n) && continue
392 35
        val = getfield(m, n)
393 35
        if val isa Module && !(val in seen)
394 35
            all_names(val, pred, symbols, seen)
395
        end
396 35
        if pred(n)
397 35
            push!(symbols, n)
398
        end
399
    end
400 35
    symbols
401
end
402

403 10
function symbols(env::EnvStore, m::Union{Module,Nothing} = nothing, allnames::Base.IdSet{Symbol} = getallns(), visited = Base.IdSet{Module}();  get_return_type = false)
404 35
    if m isa Module
405 35
        cache = _lookup(VarRef(m), env, true)
406 35
        cache === nothing && return
407 30
        push!(visited, m)
408 30
        ns = all_names(m)
409 35
        for s in ns
410 35
            !isdefined(m, s) && continue
411 35
            x = getfield(m, s)
412 35
            if Base.unwrap_unionall(x) isa DataType # Unions aren't handled here.
413 35
                if parentmodule((x)) === m
414 35
                    cache[s] = DataTypeStore(x, m, s in getnames(m))
415 35
                    cache_methods(x, s, env, get_return_type)
416 35
                elseif nameof(x) !== s
417
                    # This needs some finessing.
418 35
                    cache[s] = DataTypeStore(x, m, s in getnames(m))
419 35
                    ms = cache_methods(x, s, env, get_return_type)
420
                    # A slightly difficult case. `s` is probably a shadow binding of `x` but we should store the methods nonetheless.
421
                    # Example: DataFrames.Not points to InvertedIndices.InvertedIndex
422 35
                    for m in ms
423 35
                        push!(cache[s].methods, m[2])
424
                    end
425
                else
426
                    # These are imported variables that are reexported.
427 35
                    cache[s] = VarRef(VarRef(parentmodule(x)), nameof(x))
428
                end
429 35
            elseif x isa Function
430 35
                if parentmodule(x) === m || (x isa Core.IntrinsicFunction && m === Core.Intrinsics)
431 35
                    cache[s] = FunctionStore(x, m, s in getnames(m))
432 35
                    cache_methods(x, s, env, get_return_type)
433 35
                elseif !haskey(cache, s)
434
                    # This will be replaced at a later point by a FunctionStore if methods for `x` are defined within `m`.
435 35
                    if x isa Core.IntrinsicFunction
436 35
                        cache[s] = VarRef(VarRef(Core.Intrinsics), nameof(x))
437
                    else
438 35
                        cache[s] = VarRef(VarRef(parentmodule(x)), nameof(x))
439
                    end
440 35
                elseif !((cache[s] isa FunctionStore || cache[s] isa DataTypeStore) && !isempty(cache[s].methods))
441
                    # These are imported variables that are reexported.
442
                    # We don't want to remove Func/DT stores that have methods (these will be specific to the module)
443 0
                    if x isa Core.IntrinsicFunction
444 0
                        cache[s] = VarRef(VarRef(Core.Intrinsics), nameof(x))
445
                    else
446 30
                        cache[s] = VarRef(VarRef(parentmodule(x)), nameof(x))
447
                    end
448
                end
449 35
            elseif x isa Module
450 35
                if x === m
451 35
                    cache[s] = VarRef(x)
452 35
                elseif parentmodule(x) === m
453 35
                    symbols(env, x, allnames, visited, get_return_type = get_return_type)
454
                else
455 35
                    cache[s] = VarRef(x)
456
                end
457
            else
458 35
                cache[s] = GenericStore(VarRef(VarRef(m), s), FakeTypeName(typeof(x)), _doc(x), s in getnames(m))
459
            end
460
        end
461
    else
462 35
        for m in Base.loaded_modules_array()
463 35
            in(m, visited) || symbols(env, m, allnames, visited, get_return_type = get_return_type)
464
        end
465
    end
466
end
467

468

469 5
function load_core(; get_return_type = false)
470 25
    c = Pkg.Types.Context()
471 25
    cache = getenvtree([:Core,:Base])
472 25
    symbols(cache, get_return_type = get_return_type)
473 25
    cache[:Main] = ModuleStore(VarRef(nothing, :Main), Dict(), "", true, [], [])
474

475
    # This is wrong. As per the docs the Base.include each module should have it's own
476
    # version.
477 25
    push!(cache[:Base].exportednames, :include)
478

479
    # Add special cases for built-ins
480 25
    let f = cache[:Base][:include]
481 25
        cache[:Base][:include] = FunctionStore(f.name, cache[:Base][:MainInclude][:include].methods, f.doc, f.extends, true)
482
    end
483

484 25
    cache[:Base][Symbol("@.")] = cache[:Base][Symbol("@__dot__")]
485 25
    cache[:Core][:Main] = GenericStore(VarRef(nothing, :Main), FakeTypeName(Module), _doc(Main), true)
486
    # Add built-ins
487 25
    builtins = Symbol[nameof(getfield(Core, n).instance) for n in unsorted_names(Core, all = true) if isdefined(Core, n) && getfield(Core, n) isa DataType && isdefined(getfield(Core, n), :instance) && getfield(Core, n).instance isa Core.Builtin]
488 25
    cnames = unsorted_names(Core)
489 25
    for f in builtins
490 25
        if !haskey(cache[:Core], f)
491 25
            cache[:Core][f] = FunctionStore(getfield(Core, Symbol(f)), Core, Symbol(f) in cnames)
492
        end
493
    end
494 25
    haskey(cache[:Core], :_typevar) && push!(cache[:Core][:_typevar].methods, MethodStore(:_typevar, :Core, "built-in", 0, [:n => FakeTypeName(Symbol), :lb => FakeTypeName(Any), :ub => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
495 25
    push!(cache[:Core][:_apply].methods, MethodStore(:_apply, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
496 25
    haskey(cache[:Core].vals, :_apply_iterate) && push!(cache[:Core][:_apply_iterate].methods, MethodStore(:_apply_iterate, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
497 25
    if isdefined(Core, :_call_latest)
498 0
        push!(cache[:Core][:_call_latest].methods, MethodStore(:_call_latest, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
499 0
        push!(cache[:Core][:_call_in_world].methods, MethodStore(:_call_in_world, :Core, "built-in", 0, [:world => FakeTypeName(UInt), :f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
500
    else
501 25
        if isdefined(Core, :_apply_in_world)
502 0
            push!(cache[:Core][:_apply_in_world].methods, MethodStore(:_apply_in_world, :Core, "built-in", 0, [:world => FakeTypeName(UInt), :f => FakeTypeName(Function), :args => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
503
        end
504 25
        push!(cache[:Core][:_apply_latest].methods, MethodStore(:_apply_latest, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
505
    end
506 25
    push!(cache[:Core][:_apply_pure].methods, MethodStore(:_apply_pure, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
507 25
    push!(cache[:Core][:_expr].methods, MethodStore(:_expr, :Core, "built-in", 0, [:head => FakeTypeName(Symbol), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Expr)))
508 25
    haskey(cache[:Core].vals, :_typevar) && push!(cache[:Core][:_typevar].methods, MethodStore(:_typevar, :Core, "built-in", 0, [:name => FakeTypeName(Symbol), :lb => FakeTypeName(Any), :ub => FakeTypeName(Any)], Symbol[], FakeTypeName(TypeVar)))
509 25
    push!(cache[:Core][:applicable].methods, MethodStore(:applicable, :Core, "built-in", 0, [:f => FakeTypeName(Function), :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Bool)))
510 25
    push!(cache[:Core][:apply_type].methods, MethodStore(:apply_type, :Core, "built-in", 0, [:T => FakeTypeName(UnionAll), :types => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(UnionAll)))
511 25
    push!(cache[:Core][:arrayref].methods, MethodStore(:arrayref, :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any), :c => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
512 25
    push!(cache[:Core][:arrayset].methods, MethodStore(:arrayset, :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any), :c => FakeTypeName(Any), :d => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
513 25
    push!(cache[:Core][:arraysize].methods, MethodStore(:arraysize, :Core, "built-in", 0, [:a => FakeTypeName(Array), :i => FakeTypeName(Int)], Symbol[], FakeTypeName(Int)))
514 25
    haskey(cache[:Core], :const_arrayref) && push!(cache[:Core][:const_arrayref].methods, MethodStore(:const_arrayref, :Core, "built-in", 0, [:args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
515 25
    push!(cache[:Core][:fieldtype].methods, MethodStore(:fieldtype, :Core, "built-in", 0, [:t => FakeTypeName(DataType), :field => FakeTypeName(Symbol)], Symbol[], FakeTypeName(Type{T} where T)))
516 25
    push!(cache[:Core][:getfield].methods, MethodStore(:setfield, :Core, "built-in", 0, [:object => FakeTypeName(Any), :item => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
517 25
    push!(cache[:Core][:ifelse].methods, MethodStore(:ifelse, :Core, "built-in", 0, [:condition => FakeTypeName(Bool), :x => FakeTypeName(Any), :y => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
518 25
    push!(cache[:Core][:invoke].methods, MethodStore(:invoke, :Core, "built-in", 0, [:f => FakeTypeName(Function), :x => FakeTypeName(Any), :argtypes => FakeTypeName(Type{T} where T) , :args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
519 25
    push!(cache[:Core][:isa].methods, MethodStore(:isa, :Core, "built-in", 0, [:a => FakeTypeName(Any), :T => FakeTypeName(Type{T} where T)], Symbol[], FakeTypeName(Bool)))
520 25
    push!(cache[:Core][:isdefined].methods, MethodStore(:getproperty, :Core, "built-in", 0, [:value => FakeTypeName(Any), :field => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
521 25
    push!(cache[:Core][:nfields].methods, MethodStore(:nfields, :Core, "built-in", 0, [:x => FakeTypeName(Any)], Symbol[], FakeTypeName(Int)))
522 25
    push!(cache[:Core][:setfield!].methods, MethodStore(:setfield!, :Core, "built-in", 0, [:value => FakeTypeName(Any), :name => FakeTypeName(Symbol), :x => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
523 25
    push!(cache[:Core][:sizeof].methods, MethodStore(:sizeof, :Core, "built-in", 0, [:obj => FakeTypeName(Any)], Symbol[], FakeTypeName(Int)))
524 25
    push!(cache[:Core][:svec].methods, MethodStore(:svec, :Core, "built-in", 0, [:args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
525 25
    push!(cache[:Core][:throw].methods, MethodStore(:throw, :Core, "built-in", 0, [:e => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
526 25
    push!(cache[:Core][:tuple].methods, MethodStore(:tuple, :Core, "built-in", 0, [:args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
527 25
    push!(cache[:Core][:typeassert].methods, MethodStore(:typeassert, :Core, "built-in", 0, [:x => FakeTypeName(Any), :T => FakeTypeName(Type{T} where T)], Symbol[], FakeTypeName(Any)))
528 25
    push!(cache[:Core][:typeof].methods, MethodStore(:typeof, :Core, "built-in", 0, [:x => FakeTypeName(Any)], Symbol[], FakeTypeName(Type{T} where T)))
529

530 25
    push!(cache[:Core][:getproperty].methods, MethodStore(:getproperty, :Core, "built-in", 0, [:value => FakeTypeName(Any), :name => FakeTypeName(Symbol)], Symbol[], FakeTypeName(Any)))
531 25
    push!(cache[:Core][:setproperty!].methods, MethodStore(:setproperty!, :Core, "built-in", 0, [:value => FakeTypeName(Any), :name => FakeTypeName(Symbol), :x => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
532 25
    push!(cache[:Core][:setproperty!].methods, MethodStore(:setproperty!, :Core, "built-in", 0, [:value => FakeTypeName(Any), :name => FakeTypeName(Symbol), :x => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
533 25
    haskey(cache[:Core], :_abstracttype) && push!(cache[:Core][:_abstracttype].methods, MethodStore(:_abstracttype, :Core, "built-in", 0, [:m => FakeTypeName(Module), :x => FakeTypeName(Symbol), :p => FakeTypeName(Core.SimpleVector)], Symbol[], FakeTypeName(Any)))
534 25
    haskey(cache[:Core], :_primitivetype) && push!(cache[:Core][:_primitivetype].methods, MethodStore(:_primitivetype, :Core, "built-in", 0, [:m => FakeTypeName(Module), :x => FakeTypeName(Symbol), :p => FakeTypeName(Core.SimpleVector), :n => FakeTypeName(Core.Int)], Symbol[], FakeTypeName(Any)))
535 25
    haskey(cache[:Core], :_equiv_typedef) && push!(cache[:Core][:_equiv_typedef].methods, MethodStore(:_equiv_typedef, :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
536 25
    haskey(cache[:Core], :_setsuper!) && push!(cache[:Core][:_setsuper!].methods, MethodStore(:_setsuper!, :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
537 25
    haskey(cache[:Core], :_structtype) && push!(cache[:Core][:_structtype].methods, MethodStore(:_structtype, :Core, "built-in", 0, [:m => FakeTypeName(Module), :x => FakeTypeName(Symbol), :p => FakeTypeName(Core.SimpleVector), :fields => FakeTypeName(Core.SimpleVector), :mut => FakeTypeName(Bool), :z => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
538 25
    haskey(cache[:Core], :_typebody) && push!(cache[:Core][:_typebody!].methods, MethodStore(:_typebody!, :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
539 25
    push!(cache[:Core][:(===)].methods, MethodStore(:(===), :Core, "built-in", 0, [:a => FakeTypeName(Any), :b => FakeTypeName(Any)], Symbol[], FakeTypeName(Any)))
540 25
    push!(cache[:Core][:(<:)].methods, MethodStore(:(<:), :Core, "built-in", 0, [:a => FakeTypeName(Type{T} where T), :b => FakeTypeName(Type{T} where T)], Symbol[], FakeTypeName(Any)))
541
    # Add unspecified methods for Intrinsics, working out the actual methods will need to be done by hand?
542 25
    for n in names(Core.Intrinsics)
543 25
        if getfield(Core.Intrinsics, n) isa Core.IntrinsicFunction
544 25
            push!(cache[:Core][:Intrinsics][n].methods, MethodStore(n, :Intrinsics, "built-in", 0, [:args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
545 25
            :args => FakeTypeName(Vararg{Any})
546
        end
547
    end
548

549 25
    for bi in builtins
550 25
        if haskey(cache[:Core], bi) && isempty(cache[:Core][bi].methods)
551
            # Add at least one arbitrary method for anything left over
552 25
            push!(cache[:Core][bi].methods, MethodStore(bi, :none, "built-in", 0, [:x => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)))
553
        end
554
    end
555

556 25
    cache[:Core][:ccall] = FunctionStore(VarRef(VarRef(Core), :ccall),
557
        MethodStore[
558
            MethodStore(:ccall, :Core, "built-in", 0, [:args => FakeTypeName(Vararg{Any})], Symbol[], FakeTypeName(Any)) # General method - should be fixed
559
        ],
560
        "`ccall((function_name, library), returntype, (argtype1, ...), argvalue1, ...)`\n`ccall(function_name, returntype, (argtype1, ...), argvalue1, ...)`\n`ccall(function_pointer, returntype, (argtype1, ...), argvalue1, ...)`\n\nCall a function in a C-exported shared library, specified by the tuple (`function_name`, `library`), where each component is either a string or symbol. Instead of specifying a library, one\ncan also use a `function_name` symbol or string, which is resolved in the current process. Alternatively, `ccall` may also be used to call a function pointer `function_pointer`, such as one\nreturned by `dlsym`.\n\nNote that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression.\n\nEach `argvalue` to the `ccall` will be converted to the corresponding `argtype`, by automatic insertion of calls to `unsafe_convert(argtype, cconvert(argtype, argvalue))`. (See also the documentation for `unsafe_convert` and `cconvert` for further details.) In most cases, this simply results in a call to `convert(argtype, argvalue)`.",
561
        VarRef(VarRef(Core), :ccall),
562
        true)
563 25
    push!(cache[:Core].exportednames, :ccall)
564 25
    cache[:Core][Symbol("@__doc__")] = FunctionStore(VarRef(VarRef(Core), Symbol("@__doc__")), [], "", VarRef(VarRef(Core), Symbol("@__doc__")), true)
565 25
    cache_methods(getfield(Core, Symbol("@__doc__")), Symbol("@__doc__"), cache, false)
566
    # Accounts for the dd situation where Base.rand only has methods from Random which doesn't appear to be explicitly used.
567
    # append!(cache[:Base][:rand].methods, cache_methods(Base.rand, cache))
568 25
    for m in cache_methods(Base.rand, :rand, cache, get_return_type)
569 25
        push!(cache[:Base][:rand].methods, m[2])
570
    end
571 25
    for m in cache_methods(Base.randn, :randn, cache, get_return_type)
572 25
        push!(cache[:Base][:randn].methods, m[2])
573
    end
574

575
    # Intrinsics
576 25
    cache[:Core][:add_int] = VarRef(VarRef(VarRef(nothing, :Core), :Intrinsics), :add_int)
577 25
    cache[:Core][:sle_int] = VarRef(VarRef(VarRef(nothing, :Core), :Intrinsics), :sle_int)
578 25
    return cache
579
end
580

581

582 0
function collect_extended_methods(depot::EnvStore, extendeds = Dict{VarRef,Vector{VarRef}}())
583 0
    for m in depot
584 0
        collect_extended_methods(m[2], extendeds, m[2].name)
585
    end
586 0
    extendeds
587
end
588

589 0
function collect_extended_methods(mod::ModuleStore, extendeds, mname)
590 0
    for (n, v) in mod.vals
591 0
        if (v isa FunctionStore) && v.extends != v.name
592 0
            haskey(extendeds, v.extends) ? push!(extendeds[v.extends], mname) : (extendeds[v.extends] = VarRef[v.extends.parent, mname])
593 0
        elseif v isa ModuleStore
594 0
            collect_extended_methods(v, extendeds, v.name)
595
        end
596
    end
597
end
598

599 35
getallns() = let allns = Base.IdSet{Symbol}(); oneverything((m, s, x, state) -> push!(allns, s)); allns end
600

601
"""
602
    split_module_names(m::Module, allns)
603

604
Return two lists of names accessible from calling getfield(m, somename)`. The first
605
contains those symbols returned by `Base.names(m, all = true)`. The second contains
606
all others, including imported symbols and those introduced by the `using` of modules.
607
"""
608 0
function split_module_names(m::Module, allns)
609 0
    internal_names = getnames(m)
610 0
    availablenames = Set{Symbol}([s for s in allns if isdefined(m, s)])
611
    # usinged_names = Set{Symbol}()
612

613 0
    for n in availablenames
614 0
        if (n in internal_names)
615 0
            pop!(availablenames, n)
616
        end
617
    end
618 0
    allms = get_all_modules()
619 0
    for u in get_used_modules(m, allms)
620 0
        for n in unsorted_names(u)
621 0
            if n in availablenames
622 0
                pop!(availablenames, n)
623
                # push!(usinged_names, pop!(availablenames, n))
624
            end
625
        end
626
    end
627 0
    internal_names, availablenames
628
end
629

630 0
get_all_modules() = let allms = Base.IdSet{Module}(); apply_to_everything(x -> if x isa Module push!(allms, x) end); allms end
631 0
get_used_modules(M, allms = get_all_modules()) = [m for m in allms if usedby(M, m)]

Read our documentation on viewing source code .

Loading