Skip to content

Commit 38bf6a1

Browse files
authored
Merge pull request #28 from JunoLab/julia-0.7
WIP: Julia 0.7
2 parents 3a898f3 + d4c3129 commit 38bf6a1

File tree

9 files changed

+202
-153
lines changed

9 files changed

+202
-153
lines changed

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
julia 0.6
1+
julia 0.7-beta
22
Lazy 0.6
33
LNR
44
Tokenize 0.1

pkg.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/CodeTools.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ module CodeTools
44

55
using Lazy, LNR
66

7-
const AString = AbstractString
8-
97
include("utils.jl")
108
include("eval.jl")
119
include("module.jl")
1210
include("summaries.jl")
11+
12+
# # Summaries shims
13+
# signature(_) = nothing
14+
# description(_) = nothing
15+
1316
include("completions.jl")
1417
include("doc.jl")
1518

src/completions.jl

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ const builtin_completions =
1919

2020
const identifier_pattern = r"^@?[_\p{L}][\p{Xwd}!]*+$"
2121

22+
_names(mod; all = false, imported = false) = filter!(x -> !Base.isdeprecated(mod, Symbol(x)), names(mod, all=all, imported=imported))
23+
2224
moduleusings(mod) = ccall(:jl_module_usings, Any, (Any,), mod)
2325

24-
filtervalid(names) = @>> names map(string) filter(x->ismatch(identifier_pattern, x))
26+
filtervalid(names) = @>> names map(string) filter(x->occursin(identifier_pattern, x))
2527

2628
accessible(mod::Module) =
27-
[names(mod, true, true);
28-
map(names, moduleusings(mod))...] |> unique |> filtervalid
29+
[_names(mod, all=true, imported=true);
30+
map(_names, moduleusings(mod))...] |> unique |> filtervalid
2931

3032
Base.getindex(b::Binding) = isdefined(b.mod, b.var) ? getfield(b.mod, b.var) : nothing
3133

@@ -37,7 +39,7 @@ completiontype(x) =
3739

3840
const meta_cache = Dict{Any,Any}()
3941

40-
function withmeta(completion::AString, mod::Module)
42+
function withmeta(completion::AbstractString, mod::Module)
4143
isdefined(mod, Symbol(completion)) || return completion
4244
b = Binding(mod, Symbol(completion))
4345
mod = b.mod
@@ -51,7 +53,7 @@ function withmeta(completion::AString, mod::Module)
5153
c
5254
end
5355

54-
for name in map(string, names(Base))
56+
for name in map(string, _names(Base))
5557
meta_cache[(Base, name)] = withmeta(name, Base)
5658
end
5759

@@ -60,9 +62,9 @@ withmeta(completions::Vector, mod::Module) =
6062

6163
function namecompletions_(mod::Module, qualified = false)
6264
if !qualified
63-
[withmeta(filter!(x->!Base.isdeprecated(mod, Symbol(x)), accessible(mod)), mod); builtin_completions]
65+
[withmeta(accessible(mod), mod); builtin_completions]
6466
else
65-
withmeta(filter!(x->!Base.isdeprecated(mod, Symbol(x)), filtervalid(names(mod, true))), mod)
67+
withmeta(filtervalid(_names(mod, all=true)), mod)
6668
end
6769
end
6870

@@ -92,11 +94,11 @@ function pathprefix(line)
9294
end
9395

9496
function stringmeta(cs, prefix)
95-
map(c -> d(:text => c, :_prefix => prefix, :type => :file), cs)
97+
map(c -> Dict(:text => c, :_prefix => prefix, :type => :file), cs)
9698
end
9799

98100
function pathmeta(cs, path, prefix)
99-
stringmeta(map(c -> replace(joinpath(path, c), r"^\./", ""), cs), prefix)
101+
stringmeta(map(c -> replace(joinpath(path, c), r"^\./" => ""), cs), prefix)
100102
end
101103

102104
function children(dir, ext = ""; depth = 0, out = String[], prefix = "")
@@ -140,37 +142,29 @@ function pathcompletions(line)
140142
elseif func == "open"
141143
pathmeta(children(joinpath(pwd(), dir)), dir, path)
142144
end
145+
catch e
146+
[]
143147
end
144148
end
145149

146150
# Package Completions
147151
# –––––––––––––––––––
152+
# not sure why this errors with "ArgumentError: Module Pkg3 not found in current path."
148153

149-
packages(dir = Pkg.dir()) =
150-
@>> dir readdir filter(x->!ismatch(r"^\.|^METADATA$|^REQUIRE$", x))
151-
152-
all_packages() = packages(Pkg.dir("METADATA"))
154+
import Pkg
153155

154-
required_packages() =
155-
@>> Pkg.dir("REQUIRE") readstring lines
156+
pkgmeta(xs) = [Dict(:text => x, :type => "package") for x in xs]
156157

157-
unused_packages() = setdiff(all_packages(), required_packages())
158-
159-
pkgmeta(xs) = map(x -> d(:text=>x, :type=>"package"), xs)
158+
function stdlibs()
159+
srcdir = joinpath(Sys.BINDIR,"..","..","stdlib","v0.7")
160+
releasedir = joinpath(Sys.BINDIR,"..","share","julia","stdlib","v0.7")
161+
return ispath(srcdir) ? readdir(srcdir) :
162+
ispath(releasedir) ? readdir(releasedir) : []
163+
end
160164

161165
function pkgcompletions(line)
162-
if ismatch(r"^using", line)
163-
return pkgmeta(packages())
164-
end
165-
m = funcprefix(line)
166-
m == nothing && return
167-
func, _ = m
168-
if func in ["Pkg.add", "Pkg.clone", "Pkg.build", "Pkg.test"]
169-
pkgmeta(all_packages())
170-
elseif func in ["Pkg.pin", "Pkg.checkout"]
171-
pkgmeta(packages())
172-
elseif func in ["Pkg.rm"]
173-
pkgmeta(required_packages())
166+
if occursin(r"^using|^import", line)
167+
return pkgmeta(sort!(append!(collect(keys(Pkg.API.installed())), stdlibs())))
174168
end
175169
end
176170

@@ -179,7 +173,7 @@ end
179173

180174
const providers = [pkgcompletions, pathcompletions]
181175

182-
function completions(line::AString, mod::Module = Main; default = true)
176+
function completions(line::AbstractString, mod::Module = Main; default = true)
183177
for provider in providers
184178
cs = provider(line)
185179
cs nothing && return cs

src/doc.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ function methodsorwith(code, cursor, mod = Main)
3939
thing = thingorfunc(code, cursor, mod)
4040
thing == nothing && return
4141
return thing == Module ? methodswith(Module) :
42-
(isa(thing, Function) && isgeneric(thing)) || isleaftype(thing) ? methods(thing) :
42+
(isa(thing, Function) && isgeneric(thing)) || isconcretetype(thing) ? methods(thing) :
4343
eval(Main, :(methodswith($(typeof(thing)), true))) # I have no idea why I thought this was necessary
4444
end

src/eval.jl

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,70 @@ end
1616
getthing(mod::Module, name::AbstractString, default = nothing) =
1717
name == "" ?
1818
default :
19-
@as x name split(x, ".", keep=false) map(Symbol, x) getthing(mod, x, default)
19+
@as x name split(x, ".", keepempty=false) map(Symbol, x) getthing(mod, x, default)
2020

21-
getthing(mod::Module, ::Void, default) = default
21+
getthing(mod::Module, ::Nothing, default) = default
2222

2323
getthing(mod::Module, x, default) = error("can't get $x from a module")
2424

2525
getthing(args...) = getthing(Main, args...)
2626

2727
# include_string with line numbers
2828

29-
function Base.include_string(s::AbstractString, fname::AbstractString, line::Integer)
30-
include_string("\n"^(line-1)*s, fname)
29+
function Base.include_string(mod, s::AbstractString, fname::AbstractString, line::Integer)
30+
include_string(mod, "\n"^(line-1)*s, fname)
3131
end
3232

33-
function Base.include_string(mod::Module, args...)
34-
eval(mod, :(include_string($(args...))))
33+
function getmodule(parent::Union{Nothing, Module}, mod::String)
34+
parent nothing && (mod = string(parent, ".", mod))
35+
getmodule(mod)
36+
end
37+
38+
function getmodule(mod::String)
39+
mods = split(mod, '.')
40+
if length(mods) == 1
41+
getpackage(mod)
42+
else
43+
getsubmod(mods)
44+
end
45+
end
46+
47+
function getpackage(mod)
48+
inds = filter(x -> x.name==mod, collect(keys(Base.loaded_modules)))
49+
if length(inds) == 1
50+
return get(Base.loaded_modules, first(inds), Main)
51+
elseif length(inds) == 0
52+
return nothing
53+
else
54+
@warn "no support for multiple packages with the same name yet"
55+
return get(Base.loaded_modules, first(inds), Main)
56+
end
57+
end
58+
59+
function getsubmod(mods)
60+
mod = getpackage(popfirst!(mods))
61+
mod == nothing && (return nothing)
62+
for submod in mods
63+
submod = Symbol(submod)
64+
if isdefined(mod, submod) && !Base.isdeprecated(mod, submod)
65+
s = getfield(mod, submod)
66+
if s isa Module
67+
mod = s
68+
else
69+
return nothing
70+
end
71+
else
72+
return nothing
73+
end
74+
end
75+
mod
3576
end
3677

3778
# Get the current module for a file/pos
3879

39-
function getmodule(code, pos; filemod = nothing)
80+
function getmodule(code::AbstractString, pos; filemod = nothing)
4081
codem = codemodule(code, pos)
4182
modstr = (codem != "" && filemod != nothing) ? "$filemod.$codem" :
4283
codem == "" ? filemod : codem
43-
getthing(modstr, Main)
84+
getmodule(modstr)
4485
end

src/module.jl

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ function jl_files(set)
3131
return files
3232
end
3333

34+
# Recursion + Mutable State = Job Security
3435
"""
3536
Takes a start directory and returns a set of nearby directories.
3637
"""
37-
# Recursion + Mutable State = Job Security
3838
function dirsnearby(dir; descend = 1, ascend = 1, set = Set{String}())
3939
push!(set, dir)
4040
if descend > 0
@@ -125,20 +125,32 @@ Takes a given Julia source file and another (absolute) path, gives the
125125
line on which the path is included in the file or 0.
126126
"""
127127
function includeline(file::AbstractString, included_file::AbstractString)
128-
# check for self-includes
128+
# check for erroneous self includes, doesn't detect more complex cycles though
129129
file == included_file && return 0
130130

131-
i = 0
132-
open(file) do io
133-
for (index, line) in enumerate(eachline(io))
134-
m = match(r"^[^#]*\binclude\(\"([a-zA-Z_\.\\/]*)\"\)", line)
135-
if m != nothing && normpath(joinpath(dirname(file), m.captures[1])) == included_file
136-
i = index
137-
break
131+
line = 1
132+
tokens = Tokenize.tokenize(read(file, String))
133+
134+
t, state = iterate(tokens)
135+
while true
136+
if Tokens.kind(t) == Tokens.WHITESPACE
137+
line += count(x -> x == '\n', t.val)
138+
elseif Tokens.kind(t) == Tokens.IDENTIFIER && t.val == "include"
139+
t, state = iterate(tokens, state)
140+
if Tokens.kind(t) == Tokens.LPAREN
141+
t, state = iterate(tokens, state)
142+
if Tokens.kind(t) == Tokens.STRING
143+
if normpath(joinpath(dirname(file), chop(t.val, head=1, tail=1))) == included_file
144+
return line
145+
end
146+
end
138147
end
148+
elseif Tokens.kind(t) == Tokens.ENDMARKER
149+
break
139150
end
151+
t, state = iterate(tokens, state)
140152
end
141-
return i
153+
return 0
142154
end
143155

144156
"""
@@ -160,7 +172,7 @@ function filemodule_(path::AbstractString)
160172
loc = find_include(path)
161173
if loc != nothing
162174
file, line = loc
163-
mod = codemodule(readstring(file), line)
175+
mod = codemodule(read(file, String), line)
164176
super = filemodule(file)
165177
if super != "" && mod != ""
166178
return "$super.$mod"
@@ -174,9 +186,9 @@ end
174186
const filemodule = memoize(filemodule_)
175187

176188
# Get all modules
177-
178-
children(m::Module) =
179-
@>> names(m, true) map(x->getthing(m, [x])) filter(x->isa(x, Module) && x m)
189+
function children(m::Module)
190+
return @>> [moduleusings(m); getmodule.(Ref(m), string.(_names(m, all=true, imported=true)))] filter(x->isa(x, Module) && x m) unique
191+
end
180192

181193
function allchildren(m::Module, cs = Set{Module}())
182194
for c in children(m)

src/summaries.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Base.Docs: Binding, @var
2-
import Base.Markdown: MD, Code, Paragraph
2+
using Markdown: MD, Code, Paragraph, plain
33

44
# flat_content(md) = md
55
# flat_content(xs::Vector) = reduce((xs, x) -> vcat(xs,flat_content(x)), [], xs)
@@ -31,6 +31,8 @@ function hasdoc(b::Binding)
3131
false
3232
end
3333

34+
hasdoc(b) = hasdoc(Docs.aliasof(b, typeof(b)))
35+
3436
function trygetdoc(b)
3537
docs = try
3638
Docs.doc(b)
@@ -39,8 +41,6 @@ function trygetdoc(b)
3941
end
4042
end
4143

42-
hasdoc(b) = hasdoc(Docs.aliasof(b, typeof(b)))
43-
4444
function fullsignature(b::Binding)
4545
hasdoc(b) || return
4646
docs = trygetdoc(b)
@@ -60,14 +60,14 @@ end
6060
function signature(b::Binding)
6161
sig = fullsignature(b)
6262
sig == nothing && return
63-
replace(sig, r" -> .*$", "")
63+
replace(sig, r" -> .*$" => "")
6464
end
6565

6666
function returns(b::Binding)
6767
r = r" -> (.*)"
6868
sig = fullsignature(b)
6969
sig == nothing && return
70-
if ismatch(r, sig)
70+
if occursin(r, sig)
7171
ret = match(r, sig).captures[1]
7272
if length(ret) < 10
7373
ret
@@ -87,9 +87,9 @@ function description(b::Binding)
8787
first = md[2]
8888
end
8989
if isa(first, Paragraph)
90-
desc = Markdown.plain(first)
90+
desc = plain(first)
9191
return length(desc) > 100 ?
92-
desc[1:100]*"..." :
92+
desc[1:nextind(desc, 0, 99)]*"..." :
9393
desc
9494
end
9595
end

0 commit comments

Comments
 (0)