diff --git a/apps/language_server/lib/language_server/ast_utils.ex b/apps/language_server/lib/language_server/ast_utils.ex index d9c0305f3..6cde73ce0 100644 --- a/apps/language_server/lib/language_server/ast_utils.ex +++ b/apps/language_server/lib/language_server/ast_utils.ex @@ -7,6 +7,7 @@ defmodule ElixirLS.LanguageServer.AstUtils do import ElixirLS.LanguageServer.Protocol alias ElixirLS.LanguageServer.SourceFile + alias ElixirSense.Core.Normalized.Code, as: NormalizedCode @binary_operators ~w[| . ** * / + - ++ -- +++ --- .. <> in |> <<< >>> <<~ ~>> <~ ~> <~> < > <= >= == != === !== =~ && &&& and || ||| or = => :: when <- -> \\]a @unary_operators ~w[@ + - ! ^ not &]a @@ -412,4 +413,19 @@ defmodule ElixirLS.LanguageServer.AstUtils do {line + length(lines) - 1, String.length(last_line)} end end + + def surround_context_with_fallback(code, {line, column}, options \\ []) do + case NormalizedCode.Fragment.surround_context(code, {line, column}, options) do + :none -> + {NormalizedCode.Fragment.surround_context(code, {line, max(column - 1, 1)}, options), + column - 1} + + %{context: {:dot, _, _}} -> + {NormalizedCode.Fragment.surround_context(code, {line, max(column - 1, 1)}, options), + column - 1} + + context -> + {context, column} + end + end end diff --git a/apps/language_server/lib/language_server/providers/definition.ex b/apps/language_server/lib/language_server/providers/definition.ex index ddf972c3b..25ea03bf1 100644 --- a/apps/language_server/lib/language_server/providers/definition.ex +++ b/apps/language_server/lib/language_server/providers/definition.ex @@ -16,15 +16,7 @@ defmodule ElixirLS.LanguageServer.Providers.Definition do result = case Locator.definition(source_file.text, line, character, metadata: metadata) do nil -> - case Locator.definition(source_file.text, line, max(character - 1, 1), - metadata: metadata - ) do - nil -> - nil - - %ElixirLS.LanguageServer.Location{} = location -> - Protocol.Location.new(location, uri, source_file.text, project_dir) - end + nil %ElixirLS.LanguageServer.Location{} = location -> Protocol.Location.new(location, uri, source_file.text, project_dir) diff --git a/apps/language_server/lib/language_server/providers/definition/locator.ex b/apps/language_server/lib/language_server/providers/definition/locator.ex index 60cc0e3ce..924fb4378 100644 --- a/apps/language_server/lib/language_server/providers/definition/locator.ex +++ b/apps/language_server/lib/language_server/providers/definition/locator.ex @@ -25,14 +25,14 @@ defmodule ElixirLS.LanguageServer.Providers.Definition.Locator do alias ElixirSense.Core.Parser alias ElixirLS.LanguageServer.Plugins.Phoenix.Scope - alias ElixirSense.Core.Normalized.Code, as: NormalizedCode + alias ElixirLS.LanguageServer.AstUtils def definition(code, line, column, options \\ []) do - case NormalizedCode.Fragment.surround_context(code, {line, column}) do - :none -> + case AstUtils.surround_context_with_fallback(code, {line, column}) do + {:none, _} -> nil - context -> + {context, column} -> metadata = Keyword.get_lazy(options, :metadata, fn -> Parser.parse_string(code, true, true, {line, column}) diff --git a/apps/language_server/lib/language_server/providers/hover/docs.ex b/apps/language_server/lib/language_server/providers/hover/docs.ex index 99b1aa41b..f2f90a652 100644 --- a/apps/language_server/lib/language_server/providers/hover/docs.ex +++ b/apps/language_server/lib/language_server/providers/hover/docs.ex @@ -21,6 +21,8 @@ defmodule ElixirLS.LanguageServer.Providers.Hover.Docs do alias ElixirSense.Core.TypeInfo alias ElixirSense.Core.Parser + alias ElixirLS.LanguageServer.AstUtils + @type markdown :: String.t() @type module_doc :: %{kind: :module, docs: markdown, metadata: map, module: module()} @@ -71,11 +73,11 @@ defmodule ElixirLS.LanguageServer.Providers.Hover.Docs do |> Kernel.--([:exception, :message]) def docs(code, line, column, options \\ []) do - case NormalizedCode.Fragment.surround_context(code, {line, column}) do - :none -> + case AstUtils.surround_context_with_fallback(code, {line, column}) do + {:none, _} -> nil - %{begin: begin_pos, end: end_pos} = context -> + {%{begin: begin_pos, end: end_pos} = context, column} -> metadata = Keyword.get_lazy(options, :metadata, fn -> Parser.parse_string(code, true, true, {line, column}) diff --git a/apps/language_server/lib/language_server/providers/implementation/locator.ex b/apps/language_server/lib/language_server/providers/implementation/locator.ex index 78b28f8bc..ef198d59d 100644 --- a/apps/language_server/lib/language_server/providers/implementation/locator.ex +++ b/apps/language_server/lib/language_server/providers/implementation/locator.ex @@ -19,15 +19,16 @@ defmodule ElixirLS.LanguageServer.Providers.Implementation.Locator do alias ElixirLS.LanguageServer.Location alias ElixirSense.Core.Parser alias ElixirSense.Core.Normalized.Code, as: NormalizedCode + alias ElixirLS.LanguageServer.AstUtils require ElixirSense.Core.Introspection, as: Introspection def implementations(code, line, column, options \\ []) do - case NormalizedCode.Fragment.surround_context(code, {line, column}) do - :none -> + case AstUtils.surround_context_with_fallback(code, {line, column}) do + {:none, _} -> [] - context -> + {context, column} -> metadata = Keyword.get_lazy(options, :metadata, fn -> Parser.parse_string(code, true, true, {line, column}) diff --git a/apps/language_server/lib/language_server/providers/references.ex b/apps/language_server/lib/language_server/providers/references.ex index 830abf48e..e03302128 100644 --- a/apps/language_server/lib/language_server/providers/references.ex +++ b/apps/language_server/lib/language_server/providers/references.ex @@ -25,18 +25,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do Build.with_build_lock(fn -> trace = ElixirLS.LanguageServer.Tracer.get_trace() - references = - case Locator.references(source_file.text, line, character, trace, metadata: metadata) do - [] -> - Locator.references(source_file.text, line, max(character - 1, 1), trace, - metadata: metadata - ) - - references -> - references - end - - references + Locator.references(source_file.text, line, character, trace, metadata: metadata) |> Enum.map(fn elixir_sense_reference -> elixir_sense_reference |> build_reference(uri, source_file.text, project_dir) diff --git a/apps/language_server/lib/language_server/providers/references/locator.ex b/apps/language_server/lib/language_server/providers/references/locator.ex index b96b39e32..7e5038483 100644 --- a/apps/language_server/lib/language_server/providers/references/locator.ex +++ b/apps/language_server/lib/language_server/providers/references/locator.ex @@ -19,26 +19,14 @@ defmodule ElixirLS.LanguageServer.Providers.References.Locator do alias ElixirSense.Core.SurroundContext alias ElixirSense.Core.Parser - def references(code, line, column, trace, options \\ []) do - {context, column} = - case NormalizedCode.Fragment.surround_context(code, {line, column}) do - :none -> - {:none, column} - - %{context: {:dot, _, _}} -> - {NormalizedCode.Fragment.surround_context(code, {line, max(column - 1, 1)}), column - 1} + alias ElixirLS.LanguageServer.AstUtils - context -> - {context, column} - end - - case context do - :none -> + def references(code, line, column, trace, options \\ []) do + case AstUtils.surround_context_with_fallback(code, {line, column}) do + {:none, _} -> [] - %{ - begin: {begin_line, begin_col} - } = context -> + {%{begin: {begin_line, begin_col}} = context, column} -> metadata = Keyword.get_lazy(options, :metadata, fn -> Parser.parse_string(code, true, true, {line, column})