Skip to content

Commit b6cd941

Browse files
committed
complete moving over of provider code
1 parent 3e71900 commit b6cd941

File tree

19 files changed

+2642
-14
lines changed

19 files changed

+2642
-14
lines changed

apps/language_server/lib/language_server/parser.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ defmodule ElixirLS.LanguageServer.Parser do
217217
nil ->
218218
# file got closed, no need to do anything
219219
state
220+
220221
file ->
221222
version = file.source_file.version
222223

apps/language_server/lib/language_server/providers/completion/generic_reducer.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.GenericReducer do
1212

1313
require Logger
1414
# TODO change/move this
15-
alias ElixirSense.Plugins.Util
15+
alias ElixirLS.LanguageServer.Plugins.Util
1616

1717
@type func_call :: {module, fun :: atom, arg :: non_neg_integer, any}
1818
@type suggestion :: ElixirLS.LanguageServer.Providers.Completion.Suggestion.generic()

apps/language_server/lib/language_server/providers/completion/reducers/docs_snippets.ex

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
defmodule ElixirLS.LanguageServer.Providers.Completion.Reducers.DocsSnippets do
88
@moduledoc false
99

10-
# TODO change/move this
11-
alias ElixirSense.Plugins.Util
10+
alias ElixirLS.LanguageServer.Plugins.Util
1211
alias ElixirLS.Utils.Matcher
1312

1413
# Format:

apps/language_server/lib/language_server/providers/completion/suggestion.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.Suggestion do
4848
"""
4949

5050
alias ElixirSense.Core.Metadata
51-
alias ElixirSense.Core.ModuleStore
51+
alias ElixirLS.LanguageServer.Plugins.ModuleStore
5252
alias ElixirSense.Core.State
5353
alias ElixirSense.Core.Parser
5454
alias ElixirSense.Core.Source

apps/language_server/lib/language_server/providers/definition/locator.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ defmodule ElixirLS.LanguageServer.Providers.Definition.Locator do
2323
alias ElixirSense.Core.SurroundContext
2424
alias ElixirLS.LanguageServer.Location
2525
alias ElixirSense.Core.Parser
26-
# TODO change/move this
27-
alias ElixirSense.Plugins.Phoenix.Scope
26+
27+
alias ElixirLS.LanguageServer.Plugins.Phoenix.Scope
2828
alias ElixirSense.Core.Normalized.Code, as: NormalizedCode
2929

3030
def definition(code, line, column, options \\ []) do
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
defmodule ElixirLS.LanguageServer.Plugins.Ecto do
2+
@moduledoc false
3+
4+
alias ElixirLS.LanguageServer.Plugins.ModuleStore
5+
alias ElixirSense.Core.Source
6+
alias ElixirLS.LanguageServer.Plugins.Ecto.Query
7+
alias ElixirLS.LanguageServer.Plugins.Ecto.Schema
8+
alias ElixirLS.LanguageServer.Plugins.Ecto.Types
9+
10+
@behaviour ElixirLS.LanguageServer.Plugin
11+
use ElixirLS.LanguageServer.Providers.Completion.GenericReducer
12+
13+
@schema_funcs [:field, :belongs_to, :has_one, :has_many, :many_to_many]
14+
15+
@impl true
16+
def setup(context) do
17+
ModuleStore.ensure_compiled(context, Ecto.UUID)
18+
end
19+
20+
@impl true
21+
def suggestions(hint, {Ecto.Migration, :add, 1, _info}, _chain, opts) do
22+
builtin_types = Types.find_builtin_types(hint, opts.cursor_context)
23+
builtin_types = Enum.reject(builtin_types, &String.starts_with?(&1.label, "{"))
24+
25+
{:override, builtin_types}
26+
end
27+
28+
def suggestions(hint, {Ecto.Schema, :field, 1, _info}, _chain, opts) do
29+
builtin_types = Types.find_builtin_types(hint, opts.cursor_context)
30+
custom_types = Types.find_custom_types(hint, opts.module_store)
31+
32+
{:override, builtin_types ++ custom_types}
33+
end
34+
35+
def suggestions(hint, {Ecto.Schema, func, 1, _info}, _chain, opts)
36+
when func in @schema_funcs do
37+
{:override, Schema.find_schemas(hint, opts.module_store)}
38+
end
39+
40+
def suggestions(hint, {Ecto.Schema, func, 2, %{option: option}}, _, _)
41+
when func in @schema_funcs and option != nil do
42+
{:override, Schema.find_option_values(hint, option, func)}
43+
end
44+
45+
def suggestions(_hint, {Ecto.Schema, func, 2, %{cursor_at_option: false}}, _, _)
46+
when func in @schema_funcs do
47+
:ignore
48+
end
49+
50+
def suggestions(hint, {Ecto.Schema, func, 2, _info}, _, _)
51+
when func in @schema_funcs do
52+
{:override, Schema.find_options(hint, func)}
53+
end
54+
55+
def suggestions(hint, {Ecto.Query, :from, 0, _info}, _, opts) do
56+
text_before = opts.cursor_context.text_before
57+
58+
if after_in?(hint, text_before) do
59+
{:add, Schema.find_schemas(hint, opts.module_store)}
60+
else
61+
:ignore
62+
end
63+
end
64+
65+
def suggestions(
66+
hint,
67+
_,
68+
[{nil, :assoc, 1, assoc_info} | rest],
69+
opts
70+
) do
71+
text_before = opts.cursor_context.text_before
72+
env = opts.env
73+
meta = opts.buffer_metadata
74+
75+
with %{pos: {{line, col}, _}} <- assoc_info,
76+
from_info when not is_nil(from_info) <-
77+
Enum.find_value(rest, fn
78+
{Ecto.Query, :from, 1, from_info} -> from_info
79+
_ -> nil
80+
end),
81+
assoc_code <- Source.text_after(text_before, line, col),
82+
[_, var] <-
83+
Regex.run(~r/^assoc\(\s*([_\p{Ll}\p{Lo}][\p{L}\p{N}_]*[?!]?)\s*,/u, assoc_code),
84+
%{^var => %{type: type}} <- Query.extract_bindings(text_before, from_info, env, meta),
85+
true <- function_exported?(type, :__schema__, 1) do
86+
{:override, Query.find_assoc_suggestions(type, hint)}
87+
else
88+
_ ->
89+
:ignore
90+
end
91+
end
92+
93+
def suggestions(hint, _func_call, chain, opts) do
94+
case Enum.find(chain, &match?({Ecto.Query, :from, 1, _}, &1)) do
95+
{_, _, _, %{cursor_at_option: false} = info} ->
96+
text_before = opts.cursor_context.text_before
97+
env = opts.env
98+
buffer_metadata = opts.buffer_metadata
99+
100+
schemas =
101+
if after_in?(hint, text_before),
102+
do: Schema.find_schemas(hint, opts.module_store),
103+
else: []
104+
105+
bindings = Query.extract_bindings(text_before, info, env, buffer_metadata)
106+
{:add, schemas ++ Query.bindings_suggestions(hint, bindings)}
107+
108+
{_, _, _, _} ->
109+
{:override, Query.find_options(hint)}
110+
111+
_ ->
112+
:ignore
113+
end
114+
end
115+
116+
# Adds customized snippet for `Ecto.Schema.schema/2`
117+
@impl true
118+
def decorate(%{origin: "Ecto.Schema", name: "schema", arity: 2} = item) do
119+
snippet = """
120+
schema "$1" do
121+
$0
122+
end
123+
"""
124+
125+
Map.put(item, :snippet, snippet)
126+
end
127+
128+
# Fallback
129+
def decorate(item) do
130+
item
131+
end
132+
133+
defp after_in?(hint, text_before) do
134+
Regex.match?(~r/\s+in\s+#{Regex.escape(hint)}$/u, text_before)
135+
end
136+
end

0 commit comments

Comments
 (0)