Skip to content
24 changes: 24 additions & 0 deletions src/languageserverinstance.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ mutable struct LanguageServerInstance
global_env::StaticLint.ExternalEnv
roots_env_map::Dict{Document,StaticLint.ExternalEnv}
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.


runlinter::Bool
lint_options::StaticLint.LintOptions
Expand Down Expand Up @@ -75,6 +76,7 @@ mutable struct LanguageServerInstance
StaticLint.ExternalEnv(deepcopy(SymbolServer.stdlibs), SymbolServer.collect_extended_methods(SymbolServer.stdlibs), collect(keys(SymbolServer.stdlibs))),
Dict(),
false,
Dict{String,Document}(),
true,
StaticLint.LintOptions(),
:all,
Expand Down Expand Up @@ -123,9 +125,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
doc = getdocument(server, uri)
StaticLint.clear_meta(getcst(doc))
delete!(server._documents, uri)
Expand Down
18 changes: 16 additions & 2 deletions src/requests/completions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ function is_rebinding_of_module(x)
StaticLint.hasref(refof(x).val.args[2]) && refof(refof(x).val.args[2]).type === StaticLint.CoreTypes.Module &&
refof(refof(x).val.args[2]).val isa EXPR && CSTParser.defines_module(refof(refof(x).val.args[2]).val)# 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, state::CompletionState) end
function _get_dot_completion(px::EXPR, spartial, state::CompletionState)
Expand All @@ -303,8 +304,8 @@ function _get_dot_completion(px::EXPR, spartial, state::CompletionState)
add_completion_item(state, CompletionItem(a, CompletionItemKinds.Method, get_typed_definition(a), MarkupContent(a), texteditfor(state, spartial, a)))
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 is_completion_match(a, spartial)
add_completion_item(state, CompletionItem(a, CompletionItemKinds.Method, get_typed_definition(a), MarkupContent(a), texteditfor(state, spartial, a)))
Expand Down Expand Up @@ -456,7 +457,14 @@ function import_completions(ppt, pt, t, is_at_end, x, state::CompletionState)
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.getsymbols(getenv(state))

n = String(n)
(startswith(n, ".") || startswith(n, "#")) && continue
add_completion_item(state, CompletionItem(n, CompletionItemKinds.Module, get_typed_definition(m), MarkupContent(sanitize_docstring(m.doc)), TextEdit(state.range, n)))
Expand Down Expand Up @@ -488,6 +496,12 @@ function import_completions(ppt, pt, t, is_at_end, x, state::CompletionState)
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.getsymbols(getenv(state))
n = String(n)
if is_completion_match(n, t.val)
Expand Down