Skip to content

Commit

Permalink
going to work on protocol detections
Browse files Browse the repository at this point in the history
  • Loading branch information
scohen committed Apr 11, 2024
1 parent 85ad8ce commit 4fa75d0
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ defmodule Lexical.RemoteControl.CodeIntelligence.Symbols.Workspace do
defmodule Link do
defstruct [:uri, :range, :detail_range]

@type t :: %__MODULE__{
uri: Lexical.uri(),
range: Lexical.Document.Range.t(),
detail_range: Lexical.Document.Range.t()
}

def new(uri, range, detail_range \\ nil) do
%__MODULE__{uri: uri, range: range, detail_range: detail_range}
end
Expand All @@ -13,6 +19,13 @@ defmodule Lexical.RemoteControl.CodeIntelligence.Symbols.Workspace do

defstruct [:name, :type, :link, container_name: nil]

@type t :: %__MODULE__{
container_name: String.t() | nil,
link: Link.t(),
name: String.t(),
type: atom()
}

def from_entry(%Entry{} = entry) do
link =
entry.path
Expand All @@ -28,17 +41,6 @@ defmodule Lexical.RemoteControl.CodeIntelligence.Symbols.Workspace do
}
end

defp symbol_name(fun, entry)
when fun in [:function, :public_function, :private_function] do
[name_and_arity, local_module] =
entry.subject
|> String.split(".")
|> Enum.reverse()
|> Enum.take(2)

local_module <> "." <> name_and_arity
end

@module_types [
:struct,
:module,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ defmodule Lexical.RemoteControl.Search.Fuzzy do
if map_items? do
items
|> Stream.map(mapper)
|> Stream.filter(filter_fun)
|> Enum.to_list()
|> Enum.filter(filter_fun)
else
Enum.filter(items, filter_fun)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
defmodule Lexical.RemoteControl.Search.Indexer.Entry do
@type entry_type :: :module
@type entry_type ::
:ex_unit_describe
| :ex_unit_test
| :function
| :module
| :module_attribute
| :private_function
| :protocol
| :protocol_implementation
| :public_function
| :struct
| :variable

@type subject :: String.t()
@type entry_subtype :: :reference | :definition
@type version :: String.t()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,10 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.Module do
) do
%Block{} = block = Reducer.current_block(reducer)

with {:ok, aliased_module} <- resolve_alias(reducer, module_name),
with {:ok, protocol_module} <- resolve_alias(reducer, module_name),
{:ok, for_target} <- resolve_for_block(reducer, for_block) do
protocol_module = Module.concat(aliased_module, for_target)

detail_range = defimpl_range(reducer, defimpl_ast)
implemented_module = Module.concat(protocol_module, for_target)

implementation_entry =
Entry.block_definition(
Expand All @@ -81,10 +80,15 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.Module do
:protocol_implementation,
block_range(reducer.analysis.document, defimpl_ast),
detail_range,
Application.get_application(aliased_module)
Application.get_application(protocol_module)
)

module_entry =
Entry.copy(implementation_entry,
subject: Subject.module(implemented_module),
type: :module
)

module_entry = Entry.copy(implementation_entry, type: :module)
{:ok, [implementation_entry, module_entry]}
else
_ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule Lexical.RemoteControl.CodeIntelligence.SymbolsTest do
{symbols, doc}
end

def workspace_symbols(code, query) do
def workspace_symbols(code) do
doc = Document.new("file:///file.ex", code, 1)

{:ok, entries} =
Expand All @@ -31,7 +31,7 @@ defmodule Lexical.RemoteControl.CodeIntelligence.SymbolsTest do

entries = Enum.reject(entries, &(&1.type == :metadata))
patch(Lexical.RemoteControl.Search.Store, :fuzzy, entries)
symbols = Symbols.for_workspace(query)
symbols = Symbols.for_workspace("")
{symbols, doc}
end

Expand Down Expand Up @@ -361,7 +361,7 @@ defmodule Lexical.RemoteControl.CodeIntelligence.SymbolsTest do
defmodule Parent.Child do
end
]
|> workspace_symbols("hello")
|> workspace_symbols()

assert module.type == :module
assert module.name == "Parent.Child"
Expand All @@ -383,7 +383,7 @@ defmodule Lexical.RemoteControl.CodeIntelligence.SymbolsTest do
end
end
]
|> workspace_symbols("hello")
|> workspace_symbols()

assert public_function.type == :public_function
assert String.ends_with?(public_function.name, ".my_fn/0")
Expand All @@ -394,12 +394,56 @@ defmodule Lexical.RemoteControl.CodeIntelligence.SymbolsTest do
assert decorate(doc, public_function.link.detail_range) =~ " def «my_fn» do"

assert private_function.type == :private_function
assert private_function.name == "Child.private_fun/2"
assert private_function.name == "Parent.Child.private_fun/2"
assert private_function.link.uri == "file:///file.ex"
refute private_function.container_name

assert decorate(doc, private_function.link.range) =~ " «defp private_fun(a, b) do\n end»"
assert decorate(doc, private_function.link.detail_range) =~ " defp «private_fun(a, b)» do"
end

test "converts protocol implementations" do
{symbols, _doc} =
~q[
defimpl SomeProtocol, for: Atom do
def do_stuff(atom, opts) do
end
end
]
|> workspace_symbols()

[proto_impl, defined_module, protocol_module, proto_target, function] = symbols

assert proto_impl.type == :protocol_implementation
assert proto_impl.name == "SomeProtocol"

assert defined_module.type == :module
assert defined_module.name == "SomeProtocol.Atom"

assert protocol_module.type == :module
assert protocol_module.name == "SomeProtocol"

assert proto_target.type == :module
assert proto_target.name == "Atom"

assert function.type == :public_function
assert function.name == "SomeProtocol.Atom.do_stuff/2"
end

test "converts protocol definitions" do
{[protocol, function], _doc} =
~q[
defprotocol MyProto do
def do_stuff(something, other)
end
]
|> workspace_symbols()

assert protocol.type == :protocol
assert protocol.name == "MyProto"

assert function.type == :function
assert function.name == "MyProto.do_stuff/2"
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,23 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.FunctionDefinitionTest
assert expected == extract(code, multi_line.range)
end

test "finds functions defined in protocol implementations" do
{:ok, [function], doc} =
~q[
defimpl MyProtocol, for: Structs.Mystruct do
def do_proto(a, b) do
a + b
end
end
]
|> index_functions()

assert function.type == :public_function
assert function.subject == "MyProtocol.Structs.Mystruct.do_proto/2"
assert decorate(doc, function.range) =~ "def «do_proto(a, b)» do"
assert decorate(doc, function.block_range) =~ "«def do_proto(a, b) do\n a + b\n end»"
end

test "skips public functions defined in quote blocks" do
code =
~q[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.ProtocolTest do

assert protocol.type == :protocol_implementation
assert protocol.subtype == :definition
assert protocol.subject == Something.Atom
assert protocol.subject == Something

expected_block =
~q[
Expand Down Expand Up @@ -74,7 +74,7 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.ProtocolTest do

assert protocol.type == :protocol_implementation
assert protocol.subtype == :definition
assert protocol.subject == Something.Atom
assert protocol.subject == Something

expected_block = ~q[
«defimpl Something, for: Atom do
Expand Down Expand Up @@ -118,7 +118,7 @@ defmodule Lexical.RemoteControl.Search.Indexer.Extractors.ProtocolTest do

assert protocol_impl_def.type == :protocol_implementation
assert protocol_impl_def.subtype == :definition
assert protocol_impl_def.subject == Protocol.Target
assert protocol_impl_def.subject == Protocol
assert decorate(doc, protocol_impl_def.range) =~ "«defimpl Protocol, for: Target do»"
assert decorate(doc, protocol_impl_def.block_range) =~ expected_block

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ defmodule Lexical.Server.Provider.Handlers.WorkspaceSymbol do
defp to_kind(:struct), do: :struct
defp to_kind(:module), do: :module
defp to_kind(:protocol_implementation), do: :module
defp to_kind(:protocol), do: :module
defp to_kind(:protocol), do: :interface
defp to_kind(:lx_protocol), do: :module
defp to_kind(:variable), do: :variable
defp to_kind(:function), do: :function
Expand Down

0 comments on commit 4fa75d0

Please sign in to comment.