Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate symbol server #37

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ authors = ["David Anthoff <anthoff@berkeley.edu>"]
version = "4.6.1-DEV"

[deps]
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"
CancellationTokens = "2e8d271d-f2e2-407b-a864-17eb2156783e"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
JuliaSyntax = "70703baa-626e-46a2-a12c-08ffd08c73b4"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"
Salsa = "1fbf2c77-44e2-4d5d-8131-0fa618a5c278"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
TestItemDetection = "76b0de8b-5c4b-48ef-a724-914b33ca988d"
CancellationTokens = "2e8d271d-f2e2-407b-a864-17eb2156783e"

[extras]
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
JuliaSyntax = "0.4"
julia = "1.6"
AutoHashEquals = "1,2"
CancellationTokens = "1"
InteractiveUtils = "1.11.0"
JuliaSyntax = "0.4"
Salsa = "2.2.0"
TestItemDetection = "1.1"
CancellationTokens = "1"
julia = "1.6"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"

[targets]
test = ["Test", "TestItemRunner"]
4 changes: 4 additions & 0 deletions src/JuliaWorkspaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ using .URIs2: filepath2uri, uri2filepath

using .URIs2: URI, @uri_str

include("SymbolServer/SymbolServer.jl")
import .SymbolServer

include("exception_types.jl")
include("types.jl")
include("sourcetext.jl")
Expand All @@ -27,6 +30,7 @@ include("layer_projects.jl")
include("layer_testitems.jl")
include("layer_diagnostics.jl")
include("fileio.jl")
include("layer_symbols.jl")
include("public.jl")

end
14 changes: 14 additions & 0 deletions src/SymbolServer/SymbolServer.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module SymbolServer

import Pkg, InteractiveUtils, UUIDs

using UUIDs: UUID

include("faketypes.jl")
include("symbols.jl")
include("utils.jl")
include("serialize.jl")

using .CacheStore

end
172 changes: 172 additions & 0 deletions src/SymbolServer/faketypes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
########## Fake type-system


# Used to label all objects
@auto_hash_equals struct VarRef
parent::Union{VarRef,Nothing}
name::Symbol
end
VarRef(m::Module) = VarRef((parentmodule(m) == Main || parentmodule(m) == m) ? nothing : VarRef(parentmodule(m)), nameof(m))

# These mirror Julia types (w/o the Fake prefix)
@auto_hash_equals struct FakeTypeName
name::VarRef
parameters::Vector{Any}
end

function FakeTypeName(@nospecialize(x); justname=false)
@static if !(Vararg isa Type)
x isa typeof(Vararg) && return FakeTypeofVararg(x)
end
if x isa DataType
xname = x.name
xnamename = xname.name # necessary but unclear why.
if justname
FakeTypeName(VarRef(VarRef(x.name.module), x.name.name), [])
else
# FakeTypeName(VarRef(VarRef(x.name.module), x.name.name), _parameter.(x.parameters))
ft = FakeTypeName(VarRef(VarRef(x.name.module), x.name.name), [])
for p in x.parameters
push!(ft.parameters, _parameter(p))
end
ft
end
elseif x isa Union
FakeUnion(x)
elseif x isa UnionAll
FakeUnionAll(x)
elseif x isa TypeVar
FakeTypeVar(x)
elseif x isa Core.TypeofBottom
FakeTypeofBottom()
elseif x isa Module
VarRef(x)
else
error((x, typeof(x)))
end
end

@auto_hash_equals struct FakeTypeofBottom end
@auto_hash_equals struct FakeUnion
a
b
end
FakeUnion(u::Union) = FakeUnion(FakeTypeName(u.a, justname=true), FakeTypeName(u.b, justname=true))
@auto_hash_equals struct FakeTypeVar
name::Symbol
lb
ub
end
FakeTypeVar(tv::TypeVar) = FakeTypeVar(tv.name, FakeTypeName(tv.lb, justname=true), FakeTypeName(tv.ub, justname=true))
@auto_hash_equals struct FakeUnionAll
var::FakeTypeVar
body::Any
end
FakeUnionAll(ua::UnionAll) = FakeUnionAll(FakeTypeVar(ua.var), FakeTypeName(ua.body, justname=true))

function _parameter(@nospecialize(p))
if p isa Union{Int,Symbol,Bool,Char}
p
elseif !(p isa Type) && isbitstype(typeof(p))
0
elseif p isa Tuple
_parameter.(p)
else
FakeTypeName(p, justname=true)
end
end

Base.print(io::IO, vr::VarRef) = vr.parent === nothing ? print(io, vr.name) : print(io, vr.parent, ".", vr.name)
function Base.print(io::IO, tn::FakeTypeName)
print(io, tn.name)
if !isempty(tn.parameters)
print(io, "{")
for i = 1:length(tn.parameters)
print(io, tn.parameters[i])
i != length(tn.parameters) && print(io, ",")
end
print(io, "}")
end
end
Base.print(io::IO, x::FakeUnionAll) = print(io, x.body, " where ", x.var)
function Base.print(io::IO, x::FakeUnion; inunion=false)
!inunion && print(io, "Union{")
print(io, x.a, ",")
if x.b isa FakeUnion
print(io, x.b, inunion=true)
else
print(io, x.b, "}")
end
end
function Base.print(io::IO, x::FakeTypeVar)
if isfakebottom(x.lb)
if isfakeany(x.ub)
print(io, x.name)
else
print(io, x.name, "<:", x.ub)
end
elseif isfakeany(x.ub)
print(io, x.lb, "<:", x.name)
else
print(io, x.lb, "<:", x.name, "<:", x.ub)
end
end

isfakeany(t) = false
isfakeany(t::FakeTypeName) = isfakeany(t.name)
isfakeany(vr::VarRef) = vr.name === :Any && vr.parent isa VarRef && vr.parent.name === :Core && vr.parent.parent === nothing

isfakebottom(t) = false
isfakebottom(t::FakeTypeofBottom) = true

Base.:(==)(a::FakeTypeName, b::FakeTypeName) = a.name == b.name && a.parameters == b.parameters
Base.:(==)(a::VarRef, b::VarRef) = a.parent == b.parent && a.name == b.name
Base.:(==)(a::FakeTypeVar, b::FakeTypeVar) = a.lb == b.lb && a.name == b.name && a.ub == b.ub
Base.:(==)(a::FakeUnionAll, b::FakeUnionAll) = a.var == b.var && a.body == b.body
Base.:(==)(a::FakeUnion, b::FakeUnion) = a.a == b.a && a.b == b.b
Base.:(==)(a::FakeTypeofBottom, b::FakeTypeofBottom) = true

@static if !(Vararg isa Type)
@auto_hash_equals struct FakeTypeofVararg
T
N
FakeTypeofVararg() = new()
FakeTypeofVararg(T) = (new(T))
FakeTypeofVararg(T, N) = new(T, N)
end
function FakeTypeofVararg(va::typeof(Vararg))
if isdefined(va, :N)
vaN = va.N isa TypeVar ? FakeTypeVar(va.N) : va.N
FakeTypeofVararg(FakeTypeName(va.T; justname=true), vaN) # This should be FakeTypeName(va.N) but seems to crash inference.
elseif isdefined(va, :T)
FakeTypeofVararg(FakeTypeName(va.T; justname=true))
else
FakeTypeofVararg()
end
end
function Base.print(io::IO, va::FakeTypeofVararg)
print(io, "Vararg")
if isdefined(va, :T)
print(io, "{", va.T)
if isdefined(va, :N)
print(io, ",", va.N)
end
print(io, "}")
end
end
function Base.:(==)(a::FakeTypeofVararg, b::FakeTypeofVararg)
if isdefined(a, :T)
if isdefined(b, :T) && a.T == b.T
if isdefined(a, :N)
isdefined(b, :N) && a.N == b.N
else
!isdefined(b, :N)
end
else
false
end
else
!isdefined(b, :T)
end
end
end
Loading
Loading