Skip to content
24 changes: 24 additions & 0 deletions src/languageserverinstance.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mutable struct LanguageServerInstance
symbol_store::Dict{Symbol,SymbolServer.ModuleStore}
symbol_extends::Dict{SymbolServer.VarRef,Vector{SymbolServer.VarRef}}
symbol_store_ready::Bool
workspacepackages::Dict{String,Document}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably have UUIDs as the key, right? I think we are generally not identifying packages by their UUID right now, but probably should to get this right.

# ss_task::Union{Nothing,Future}
format_options::DocumentFormat.FormatOptions
lint_options::StaticLint.LintOptions
Expand Down Expand Up @@ -73,6 +74,7 @@ mutable struct LanguageServerInstance
deepcopy(SymbolServer.stdlibs),
SymbolServer.collect_extended_methods(SymbolServer.stdlibs),
false,
Dict{String,Document}(),
DocumentFormat.FormatOptions(),
StaticLint.LintOptions(),
Channel{Any}(Inf),
Expand Down Expand Up @@ -114,9 +116,31 @@ end

function setdocument!(server::LanguageServerInstance, uri::URI2, doc::Document)
server._documents[uri] = doc
# Add possible workspace packages
path = uri2filepath(uri._uri)
for wk_folder in server.workspaceFolders
if startswith(path, wk_folder) && normpath(wk_folder) == normpath(server.env_path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand the logic here. Is the idea that only if one has activated the package as the env, will any of this work?

sub_path = splitpath(path)
first(sub_path) == "/" && popfirst!(sub_path)
length(sub_path) < 3 && continue
fname = splitext(last(sub_path))[1]
if sub_path[end-1] == "src" && sub_path[end-2] == fname
@info "Setting $path as source of 'live' package"
server.workspacepackages[fname] = doc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that we need to look for a Project.toml and then at its content to decide whether something is really a package or not.

end
end
end
return doc
end

function deletedocument!(server::LanguageServerInstance, uri::URI2)
# clear reference to doc from workspacepackages
for (n,d) in server.workspacepackages
if d._uri == uri._uri
delete!(server.workspacepackages, n)
break
end
end
delete!(server._documents, uri)
end

Expand Down
32 changes: 22 additions & 10 deletions src/requests/completions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,33 +227,35 @@ function is_rebinding_of_module(x)
StaticLint.hasref(refof(x).val.args[3]) && refof(refof(x).val.args[3]).type === StaticLint.CoreTypes.Module &&
refof(refof(x).val.args[3]).val isa EXPR && typof(refof(refof(x).val.args[3]).val) === CSTParser.ModuleH# double check the rhs points to a module
end
get_overlapped_binding(b::StaticLint.Binding) = b.val isa StaticLint.Binding ? get_overlapped_binding(b.val) : b

function _get_dot_completion(px, spartial, rng, CIs, server) end
function _get_dot_completion(px::EXPR, spartial, rng, CIs, server)
if px !== nothing
if refof(px) isa StaticLint.Binding
if refof(px).val isa StaticLint.SymbolServer.ModuleStore
collect_completions(refof(px).val, spartial, rng, CIs, server, true)
elseif refof(px).val isa EXPR && typof(refof(px).val) === CSTParser.ModuleH && scopeof(refof(px).val) isa StaticLint.Scope
collect_completions(scopeof(refof(px).val), spartial, rng, CIs, server, true)
binding = get_overlapped_binding(refof(px))
if binding.val isa StaticLint.SymbolServer.ModuleStore
collect_completions(binding.val, spartial, rng, CIs, server, true)
elseif binding.val isa EXPR && typof(binding.val) === CSTParser.ModuleH && scopeof(binding.val) isa StaticLint.Scope
collect_completions(scopeof(binding.val), spartial, rng, CIs, server, true)
elseif is_rebinding_of_module(px)
collect_completions(scopeof(refof(refof(px).val.args[3]).val), spartial, rng, CIs, server, true)
elseif refof(px).type isa SymbolServer.DataTypeStore
for a in refof(px).type.fieldnames
elseif binding.type isa SymbolServer.DataTypeStore
for a in binding.type.fieldnames
a = String(a)
if startswith(a, spartial)
push!(CIs, CompletionItem(a, 2, MarkupContent(a), TextEdit(rng, a[nextind(a,sizeof(spartial)):end]))) # AUDIT: nextind(n,sizeof(n)) equiv to nextind(n, lastindex(n))
end
end
elseif refof(px).type isa StaticLint.Binding && refof(px).type.val isa SymbolServer.DataTypeStore
for a in refof(px).type.val.fieldnames
elseif binding.type isa StaticLint.Binding && binding.type.val isa SymbolServer.DataTypeStore
for a in binding.type.val.fieldnames
a = String(a)
if startswith(a, spartial)
push!(CIs, CompletionItem(a, 2, MarkupContent(a), TextEdit(rng, a[nextind(a,sizeof(spartial)):end]))) # AUDIT: nextind(n,sizeof(n)) equiv to nextind(n, lastindex(n))
end
end
elseif refof(px).type isa StaticLint.Binding && refof(px).type.val isa EXPR && CSTParser.defines_struct(refof(px).type.val) && scopeof(refof(px).type.val) isa StaticLint.Scope
collect_completions(scopeof(refof(px).type.val), spartial, rng, CIs, server, true)
elseif binding.type isa StaticLint.Binding && binding.type.val isa EXPR && CSTParser.defines_struct(binding.type.val) && scopeof(binding.type.val) isa StaticLint.Scope
collect_completions(scopeof(binding.type.val), spartial, rng, CIs, server, true)
end
elseif refof(px) isa StaticLint.SymbolServer.ModuleStore
collect_completions(refof(px), spartial, rng, CIs, server, true)
Expand Down Expand Up @@ -382,6 +384,11 @@ function import_completions(doc, offset, rng, ppt, pt, t, is_at_end ,x, CIs, ser
end
end
else
for (n,doc1) in server.workspacepackages
if StaticLint.has_workspace_package(server, n)
push!(CIs, CompletionItem(n, 9, MarkupContent("Workspace package: $n"), TextEdit(rng, n)))
end
end
for (n,m) in StaticLint.getsymbolserver(server)
n = String(n)
startswith(n, ".") && continue
Expand Down Expand Up @@ -414,6 +421,11 @@ function import_completions(doc, offset, rng, ppt, pt, t, is_at_end ,x, CIs, ser
end
end
else
for (n,doc1) in server.workspacepackages
if startswith(n, t.val) && StaticLint.has_workspace_package(server, n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is where we need to go via the env info: Say the code has using Foo, then we need to look in the env what UUID Foo corresponds to, then we look in the server.workspacepackages that is indexed by UUID whether there is a package with that UUID. But we probably shouldn't match by name, because the names don't have to be the same if the package is loaded via an env (and not LOAD_PATH).

push!(CIs, CompletionItem(n, 9, MarkupContent("Workspace package: $n"), TextEdit(rng, n[nextind(n,sizeof(t.val)):end]))) # AUDIT: nextind(n,sizeof(n)) equiv to nextind(n, lastindex(n))
end
end
for (n,m) in StaticLint.getsymbolserver(server)
n = String(n)
if startswith(n, t.val)
Expand Down