GithubHelp home page GithubHelp logo

elixir-lsp / elixir_sense Goto Github PK

View Code? Open in Web Editor NEW
291.0 291.0 41.0 3.1 MB

Provides context-aware information for code completion, documentation, go/jump to definition, signature info and more

License: MIT License

Elixir 84.90% Erlang 15.10%

elixir_sense's People

Contributors

adrianomitre avatar axelson avatar dependabot[bot] avatar dvic avatar e14 avatar edelvalle avatar goose97 avatar gugahoa avatar henrythebuilder avatar j3rn avatar jakebecker avatar lukaszsamson avatar maciej-szlosarczyk avatar moogle19 avatar msaraiva avatar oo6 avatar princemaple avatar rodrigues avatar sarahkw avatar sasa1977 avatar scohen avatar sheldak avatar slashmili avatar smaximov avatar timgent avatar tmepple avatar tuxified avatar untra avatar wojtekmach avatar zachdaniel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elixir_sense's Issues

Error raised on behaviour unquote(__MODULE__) statement

Hi there,

I am using a behaviour statement in a macro like so:

defmacro __using__(opts) do
    quote location: :keep do
      @behaviour unquote(__MODULE__)
      ...
    end
end

Unfortunately, it raises this error:

Message: an exception was raised:
    ** (ArgumentError) argument error
        :erlang.atom_to_binary({:unquote, [line: 37, column: 18], [{:__MODULE__, [line: 37, column: 26], nil}]}, :utf8)
        (elixir_sense) lib/elixir_sense/core/introspection.ex:552: ElixirSense.Core.Introspection.module_to_string/1
        (elixir_sense) lib/elixir_sense/providers/suggestion.ex:336: anonymous fn/2 in ElixirSense.Providers.Suggestion.find_callbacks/2
        (elixir) lib/enum.ex:2994: Enum.flat_map_list/2
        (elixir_sense) lib/elixir_sense/providers/suggestion.ex:335: ElixirSense.Providers.Suggestion.find_callbacks/2

Cheers

License issues

This library is currently licensed under MIT license but it contains code taken from alchemist-server project licensed under GPL v3:

  • lib/alchemist/helpers/complete.ex
  • lib/alchemist/helpers/module_info.ex and test/alchemist/helpers/module_info_test.exs

The status of lib/alchemist/helpers/complete.ex is even more complicated as it is in fact a derrived work basing on elixir lib/iex/lib/iex/autocomplete.ex covered by Apache License v2 and copyrighted by Platformatec and it's not likely that alchemist-server authors had Platformatec's agreement to relicense it under GPL v3. AFAIK modifications to Apache Licensed code can be released under GPL v3, but the not modified part stays under original license.

What needs to be done:

  1. obtain alchemist-server's authors' agreement to relicense under MIT or rewrite GPL covered code or mention that the files are licensed under GPL v3 (I'm not sure if it's doable to release this lib under part MIT part GPL v3 license)
  2. adhere to Apache License requirements with (lib/alchemist/helpers/complete.ex and also test/alchemist/helpers/complete_test.exs), i.e. mention that original parts are copyrighted and licensend under Apache License and include list of modifications and required notices.

@do fails to complete

In ElixirLS typing @do above a function definition fails to return any completions and can result in an exception:

07:36:09.440 [error] Process #PID<0.400.0> raised an exception
** (CaseClauseError) no case clause matching: [{:hi, [line: 10, column: 7], nil}, [do: {:__block__, [], [{{:., [line: 16, column: 7], [{:__aliases__, [line: 16, column: 5], [:IO]}, :puts]}, [line: 16, column: 7], ["hihihibefesffesfasasd"]}, {{:., [line: 17, column: 9], [{:__aliases__, [line: 17, column: 5], [:Enum]}, :chunk_every]}, [line: 17, column: 9], [[], 3]}]}]]
    (elixir_sense 1.0.1) lib/elixir_sense/core/metadata_builder.ex:556: ElixirSense.Core.MetadataBuilder.pre/2
    (elixir 1.10.3) lib/macro.ex:430: anonymous fn/4 in Macro.do_traverse_args/4
    (elixir 1.10.3) lib/enum.ex:1520: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir 1.10.3) lib/enum.ex:1520: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir 1.10.3) lib/macro.ex:396: Macro.do_traverse/4
    (elixir 1.10.3) lib/macro.ex:411: Macro.do_traverse/4
    (elixir 1.10.3) lib/enum.ex:1520: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir 1.10.3) lib/macro.ex:416: Macro.do_traverse/4

screenshot-elixir-ls-do-fail

Are there currently any tests of completion that involve a file that fails to compile?

Failure with last Elixir upgrade (1.12.0-dev)

Hi,
after upgrading Elixir, probably from df04a2d (also reported on branch 1.11), ElixirLS fail to start (via eglot) due to a missing function/signature in ElixirSense.

I'm using Emacs+eglot+ElixirLS in a Debian system with Erlang 23 and Elixir aligned to master branch (1.12.0-dev)

Back to the code ElixirSense project test fails with the same origin:

** (FunctionClauseError) no function clause matching in ElixirSense.Core.Normalized.Code.extract_docs/1

     The following arguments were given to ElixirSense.Core.Normalized.Code.extract_docs/1:
     
         # 1
         %{}
     
     Attempted function clauses (showing 3 out of 3):
     
         defp extract_docs(%{"en" => docs_en})
         defp extract_docs(:hidden)
         defp extract_docs(:none)

Trying to change ElixirSense.Core.Normalized.Code.extract_docs/1 with:

diff --git a/lib/elixir_sense/core/normalized/code.ex b/lib/elixir_sense/core/normalized/code.ex
index 8659bf5..c9eec83 100644
--- a/lib/elixir_sense/core/normalized/code.ex
+++ b/lib/elixir_sense/core/normalized/code.ex
@@ -68,7 +68,7 @@ defp map_doc_entry({{kind, name, arity}, anno, signatures, docs, metadata}) do
           String.t() | false | nil
   defp extract_docs(%{"en" => docs_en}), do: docs_en
   defp extract_docs(:hidden), do: false
-  defp extract_docs(:none), do: nil
+  defp extract_docs(_), do: nil
 
   defp get_fun_docs(module, docs) do
     docs_from_module =

ElixirLS seam to work fine but two test on ElixirSense still fail:

  • test retrieve function documentation from behaviour if available (ElixirSense.DocsTest)
  • test retrieve macro documentation from behaviour if available (ElixirSense.DocsTest)

My original intention was to offer a complete solution as a pull-request but at the moment, given even the two failed tests, I still wanted to get involved with something useful.

Enrico

defimpl NiceProto, for: __MODULE__ results in exception

Failing test (test/elixir_sense/core/metadata_builder_test.exs):

  # Fix for
  # ** (CaseClauseError) no case clause matching: {:__MODULE__, [line: 34, column: 35], nil}
  #     (elixir_sense) lib/elixir_sense/core/metadata_builder.ex:213: ElixirSense.Core.MetadataBuilder.pre/2
  #     (elixir) lib/macro.ex:290: anonymous fn/4 in Macro.do_traverse_args/4
  #     (elixir) lib/enum.ex:1440: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
  #     (elixir) lib/enum.ex:1440: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
  #     (elixir) lib/macro.ex:256: Macro.do_traverse/4
  #     (elixir) lib/macro.ex:271: Macro.do_traverse/4
  #     (elixir) lib/enum.ex:1440: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
  #     (elixir) lib/macro.ex:276: Macro.do_traverse/4
  test "protocol implementation using __MODULE__" do
    state =
      """
      defprotocol NiceProto do
        def reverse(term)
      end

      defmodule MyStruct do
        defstruct [a: nil]

        defimpl NiceProto, for: __MODULE__ do
          def reverse(term), do: String.reverse(term)
        end
      end
      """
      |> string_to_state

    # protocol implementation module name does not inherit enclosing module, only protocol
    assert get_line_module(state, 8) == NiceProto.MyStruct
    assert get_line_protocol(state, 8) == {NiceProto, [MyStruct]}
  end

I've tried to fix this but I'm not sure how (or where) to replace __MODULE__ with a module name.

[error] Task started from ElixirSense.Server.TCPServer terminating

IDE: VScode
OS: MacOS

The following is an error I see in Developer Tools when I restart VSCode:

[ElixirSense] 13:22:09.105 [error] Task #PID<0.159.0> started from ElixirSense.Server.TCPServer terminating** (stop) exited in: GenServer.call(ElixirSense.Server.TCPServer.ConnectionHandlerSupervisor, {:start_task, [{:nonode@nohost, #PID<0.159.0>, #PID<0.159.0>}, [#PID<0.159.0>, #PID<0.158.0>], {:erlang, :apply, [#Function<1.131136907/0 in ElixirSense.Server.TCPServer.start_connection_handler/2>, []]}], nil, nil}, :infinity)    
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started    (elixir) lib/gen_server.ex:999: GenServer.call/3    
/Users/kj/.vscode-insiders/extensions/mjmcloug.vscode-elixir-1.1.0/elixir_sense/lib/elixir_sense/server/tcp_server.ex:58: ElixirSense.Server.TCPServer.accept/2    (elixir) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3Function: &ElixirSense.Server.TCPServer.listen/3    Args: ["unix", "localhost", "0"]ok:localhost:/tmp/elixir-sense-1581272529106882000.sock (at Socket.<anonymous> (/Users/kj/.vscode-insiders/extensions/mjmcloug.vscode-elixir-1.1.0/out/src/elixirSenseServerProcess.js:35:21))

Mix.Tasks.Xref.calls deprecation

In ElixirSense.Providers.References, Mix.Tasks.Xref.calls/0 is used to find references to functions. However, the Mix.Tasks.Xref.calls/0 function is now deprecated in favour of the new compilation tracers feature of Elixir 1.10.

Naturally, we'll want to be backwards compatible as much as possible, and may not need to change right away.

That said, the new compilation tracers approach represents some challenges. Namely:

  • The tracer has to be specified as a compiler option before the code to be analysed is compiled. I'm not exactly sure how ElixirSense goes about compiling a guest application (supposing that it does at all), so this may either be very difficult or very easy.
  • From that point forward, the information spat out by the compiler will have to be persisted (maybe an Agent or GenServer?) as it cannot be fetched again without a re-compilation.

I'd be happy to help out with this, but I first wanted to get some input from folks who know more about ElixirSense than I do.

Fails to fetch Timex.parse!/2 docs

10:05:05.675 [error] Process #PID<0.16894.1> raised an exception
** (FunctionClauseError) no function clause matching in ElixirSense.Core.Introspection.get_metadata_entry_md/1
    (elixir_sense 1.0.1) lib/elixir_sense/core/introspection.ex:271: ElixirSense.Core.Introspection.get_metadata_entry_md({:delegate_to, {Timex.Parse.DateTime.Parser, :parse!, 2}})
    (elixir 1.10.2) lib/enum.ex:1400: anonymous fn/3 in Enum.map/2
    (stdlib 3.12.1) maps.erl:232: :maps.fold_1/3
    (elixir 1.10.2) lib/enum.ex:2127: Enum.map/2
    (elixir_sense 1.0.1) lib/elixir_sense/core/introspection.ex:261: ElixirSense.Core.Introspection.get_metadata_md/1
    (elixir_sense 1.0.1) lib/elixir_sense/core/introspection.ex:229: anonymous fn/6 in ElixirSense.Core.Introspection.get_func_docs_md/2
    (elixir 1.10.2) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir_sense 1.0.1) lib/elixir_sense/core/introspection.ex:221: ElixirSense.Core.Introspection.get_func_docs_md/2

Code:
https://github.com/bitwalker/timex/blob/3.6.1/lib/timex.ex#L475-L483

  @doc """
  Same as parse/2 and parse/3, except parse! raises on error.
  See parse/2 or parse/3 docs for usage examples.
  """
  @spec parse!(String.t(), String.t()) :: DateTime.t() | NaiveDateTime.t() | no_return
  @spec parse!(String.t(), String.t(), atom) :: DateTime.t() | NaiveDateTime.t() | no_return
  defdelegate parse!(datetime_string, format_string), to: Timex.Parse.DateTime.Parser
  defdelegate parse!(datetime_string, format_string, tokenizer), to: Timex.Parse.DateTime.Parser

[Proposal] Drop server functionality

Let's be frank. I don't know of a single active user of ElixirSense server. All relevant IDEs/editors have long migrated to language server. In the last 3 years there were only 2 issues reported and no contributions. Maintaining it adds an unnecessary burden - run.exs is not covered by tests and needs tweaking on every module addition/refactoring. Server tests are flaky and crash when other tests do IO. It makes debugging more complicated. I know it could be changed into a proper application (vide elixir-lsp apps). I know it could be extracted to a separate library. I just don't see there's a need for it any more. @msaraiva please voice your opinion.

Exception raised in ecto plugin

I'm getting the following exception and similar fairly regularly when writing a ecto query:

Company: backend company-capf error "an exception was raised:
    ** (FunctionClauseError) no function clause matching in :elixir_env.trace/2
        (elixir 1.10.4) src/elixir_env.erl:35: :elixir_env.trace({:alias_reference, [line: 1], User}, #Macro.Env<aliases: [], context: nil, context_modules: [], file: "nofile", function: nil, functions: [], lexical_tracker: nil, line: 0, macro_aliases: [], macros: [], module: nil, requires: [], ...>)
        (elixir 1.10.4) lib/macro.ex:1384: Macro.do_expand_once/2
        (elixir 1.10.4) lib/macro.ex:1369: Macro.expand_once/2
        (elixir_sense 1.0.1) lib/elixir_sense/plugins/ecto/query.ex:192: ElixirSense.Plugins.Ecto.Query.infer_type/4
        (elixir_sense 1.0.1) lib/elixir_sense/plugins/ecto/query.ex:226: anonymous fn/4 in ElixirSense.Plugins.Ecto.Query.extract_bindings/4
        (elixir 1.10.4) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
        (elixir_sense 1.0.1) lib/elixir_sense/plugins/ecto.ex:87: ElixirSense.Plugins.Ecto.suggestions/4
        (elixir_sense 1.0.1) lib/elixir_sense/providers/suggestion/generic_reducer.ex:39: ElixirSense.Providers.Suggestion.GenericReducer.reduce/6" with args (candidates achi)

My project is on:

erlang 22.3.4.3
elixir 1.10.4-otp-22

ArgumentError: expected an Elixir module, got: Elixir

I get this ArgumentError whenever I am editing a config file with the latest elixir_sense (commit e6374a2)

    ** (ArgumentError) expected an Elixir module, got: Elixir
        (elixir) lib/module.ex:1299: Module.split/2
        (elixir_sense) lib/elixir_sense/core/metadata_builder.ex:376: ElixirSense.Core.MetadataBuilder.pre/2
        (elixir) lib/macro.ex:286: anonymous fn/4 in Macro.do_traverse_args/4
        (elixir) lib/enum.ex:1431: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
        (elixir) lib/macro.ex:252: Macro.do_traverse/4
        (elixir_sense) lib/elixir_sense/core/metadata_builder.ex:23: ElixirSense.Core.MetadataBuilder.build/1
        (elixir_sense) lib/elixir_sense/core/parser.ex:21: ElixirSense.Core.Parser.parse_string/4
        (elixir_sense) lib/elixir_sense.ex:43: ElixirSense.docs/3

BUG: problem when aliasing a nested module

Having something like:

alias Components.{Dialog, Dialog.Footer, Button}

when trying to auto-complete:

[Error - 11:25:31 AM] Request textDocument/completion failed.
  Message: an exception was raised:
    ** (MatchError) no match of right hand side value: ["Dialog", "Footer"]
        (elixir_sense) lib/elixir_sense/core/state.ex:525: anonymous fn/2 in ElixirSense.Core.State.expand_alias/2
        (elixir) lib/enum.ex:2956: Enum.find_list/3
        (elixir_sense) lib/elixir_sense/core/state.ex:524: ElixirSense.Core.State.expand_alias/2
        (elixir_sense) lib/elixir_sense/core/state.ex:383: ElixirSense.Core.State.add_alias/2
        (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
        (elixir_sense) lib/elixir_sense/core/metadata_builder.ex:131: ElixirSense.Core.MetadataBuilder.pre_alias/4
        (elixir) lib/macro.ex:290: anonymous fn/4 in Macro.do_traverse_args/4
        (elixir) lib/enum.ex:1440: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3

Get the module for the current line of a file

Is it possible to expose a public API that will return the Module that corresponds to the current line in the file? (i.e. if there are three modules defined in a file, this API will return the module whose body is on the specified line).

This would be a replacement for ElixirLS calling into ElixirSense.Core.Metadata.get_env:

https://github.com/elixir-lsp/elixir-ls/blob/c9b095fc797613b33c7bc39ca72e9b48c69aedac/apps/debugger/lib/debugger/server.ex#L616

Related issue: elixir-lsp/elixir-ls#234

References provider fails to find function arguments

The following test fails

test "find references of variables in arguments" do
    buffer = """
    defmodule MyModule do
      def call(conn) do
        if true do
          conn
        end
      end
    end
    """

    references = ElixirSense.references(buffer, 2, 13)

    assert references == [
      %{range: %{end: %{column: 16, line: 2}, start: %{column: 12, line: 2}}, uri: nil},
      %{range: %{end: %{column: 11, line: 4}, start: %{column: 7, line: 4}}, uri: nil},
    ]
    # returns []
  end

The reason is broken variable tracking in MetadataBuilder.State. new_func_vars_scope works differently from new_vars_scope - it does not increment the scope_id counter and thanks to that conn variable is not in the function scope. The second problem is subscope handling. When leaving a subscope in remove_vars_scope all subscope variable positions are lost.

definition not able to locate elixir sources on some ocasions

Should ElixirSense.definition/3 be able to handle modules that are provided with Elixir, like GenServer? See https://github.com/balduncle/playground/blob/master/test/playground_test.exs for 3 tests that are currently failing due to the paths to the source files for built in modules not existing on my computer and instead being associated with the machine Elixir was built on. Note that the Enum test comes straight from the docs on hex.

Thanks.

Release v2.0.0

I think it's time to publish a new release since we already have some nice new features and a bunch of fixes/improvements. Unless any of you has something else in mind, I'm planning to to this after #20, #25 and #24 are implemented and merged.

/cc @axelson, @@lukaszsamson

Refactor suggestions engine

Currently, the logic we have in ElixirSense.Providers.Suggestion is way too complex and hard to maintain. For instance if we want to restrict the list of suggestions based on the context, we need to write that logic for each different case we need.

I started to refactor the code so we can have a main reducer going through a list of producers. Each producer returns a set of suggestions that will be added to the final list. A producer can also inform if the reducer should continue to collect more suggestions or if the list provided is already the final list.

One problem I've found so far is handling the hint suggestion. Currently, the hint suggestion is generated along with variables, attributes, variable fields, functions, macros and modules, all inside ElixirSense.Providers.Suggestion.Complete.complete/2. If I want to be able to selectively show/hide individual groups of suggestions, I need to have a way to split them into groups. That's possible with the current implementation by naively using Enum.group_by/2. The problem is that the hint item, as far as I understood, is built while retrieving all those suggestions. If I remove any of them, the hint might become invalid.

So I have a question: Is the hint suggestion actually being used by any editor? Can't we just drop it out of the list and get rid of all the complexity involved? I took a look at elixir-ls code and I couldn't find where it's being used. It's just ignored.

@lukaszsamson in case we can't drop the hint suggestion, do you think it would be feasible to extract the related logic so we could apply it only after we have the final list? I've noticed you do something similar using the Hint.combine/2 function, however, I couldn't find a way to use it with the existing suggestions already returned by Complete.complete/2.

Server listens to a new sock after a client joins

I have a strange issue, I don't know if it's only for me or you also have the same problem but haven't noticed it.

Screenshot 2019-10-19 at 00 40 01

  1. I run server using
elixir run.exs unix 0 dev
  1. Start an iex console and copy paste the example in README
{:ok, socket} = 
...
data = :erlang.term_to_binary(request)
:ok = :gen_tcp.send(socket, data)
{:ok, response} = :gen_tcp.recv(socket, 0)
:erlang.binary_to_term(response)
  1. By this time I see in the output of my server that it listens to a new sock file.

  2. I did try to to connect to the old sock but it's not available anymore

Interactive Elixir (1.9.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, socket} = :gen_tcp.connect({:local, '/var/folders/h8/xlzsrqld6rldv_l03dsn60x80000gn/T/elixir-sense-1571438027826601476.sock'}, 0, [:binary, active: false, packet: 4])
** (MatchError) no match of right hand side value: {:error, :econnrefused}
    (stdlib) erl_eval.erl:453: :erl_eval.expr/5
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4

Feature Request: Get the modules defined in a given file

In the ElixirLS debugger it would be very helpful to get the list of modules defined in a file. This would allow the user to only interpret some of the modules in their project instead of all modules of the system. Defining by filename would be a more natural interface than a list of module names.

Related ElixirLS issue: elixir-lsp/elixir-ls#615

Although after thinking about it in #615 I opted to go with a regex based on the module name I still think that this could be a useful feature for ElixirSense to have.

New project under elixir-lsp to support Surface

Hi @axelson, @asummers and anyone interested.

I'm working on a new open-source project called Surface that should become public in the next couple of days. You can see it in action here. The main goal is to provide a standard way to create and reuse components in Phoenix/LiveView with exceptional integration with editors and other tools.

Having that in mind, I created a VS Code extension to add support for syntax highlighting and I believe it would be great if the project could stay under the elixir-lsp umbrella. The extension can be found at https://github.com/msaraiva/vscode-surface.

I also have some ideas listed at the end of the Getting Started to improve developer experience by customizing ElixirSense. @lukaszsamson let me know what you think.

Cheers.

-marlus

More fuzzy matching

Potential candidates

  • lib/elixir_sense/plugins/option.ex
  • lib/elixir_sense/providers/suggestion/reducers/type_specs.ex
  • lib/elixir_sense/providers/suggestion/reducers/callbacks.ex
  • lib/elixir_sense/providers/suggestion/reducers/struct.ex
  • lib/elixir_sense/providers/suggestion/reducers/params.ex
  • lib/elixir_sense/providers/suggestion/reducers/overridable.ex
  • lib/elixir_sense/providers/suggestion/reducers/protocol.ex
  • lib/elixir_sense/providers/suggestion/reducers/docs_snippets.ex
  • lib/elixir_sense/providers/suggestion/complete.ex
  • lib/elixir_sense/plugins/ecto/schema.ex

@lukaszsamson commented in #121 (comment):

Let's do them in follow up PRs. This one is already big. I'm not sure if callbacks, overridable and protocols are good candidates. Apart from those I'd include more suggestions from complete module: elixir/erlang modules, variables, attributes, map/struct keys. Elixir modules would probably work better with some letter downcasing.

Feature request: Hover for variables and attributes

Environment

  • Elixir & Erlang versions (elixir --version): 1.12.1
  • Operating system: Windows 10 64-bit
  • Editor or IDE name (e.g. Emacs/VSCode): VSCode
  • Editor Plugin/LSP Client name:

Description

Consider the example code below:

defmodule Vector do
  @spec magnitude(Vec2.t()) :: number()
  def magnitude(%Vec2{} = v), do: :math.sqrt(:math.pow(v.x, 2) + :math.pow(v.y, 2))

  @spec normalize(Vec2.t()) :: Vec2.t()
  def normalize(%Vec2{} = v) do
    length = magnitude(v)
    %{v | x: v.x / length, y: v.y / length}
  end
end

When I hover mouse on length in function normalize, the hover document will show length built-in document. But since magnitude function has type spec. I expected the hover should show it as a number or not show when hover on length variable.

Support finding references for a function named "fun"

From what I can tell it is possible to find references from a call, but you can't find references from the definition of a function.

So this works:

  test "working example" do
    buffer = """
    defmodule A do
      def a_fun do
        B.Callee.fun()
                  ^
      end
    end
    """

    references = ElixirSense.references(buffer, 3, 14)
    assert references != []
  end

But this does not:

  test "elixir-ls references test" do
    buffer = """
    defmodule B.Callee do
      def fun() do
           ^
        :ok
      end
    end
    """

    references = ElixirSense.references(buffer, 2, 7)
    assert references != []
  end

I'm trying to use ElixirSense.references/3 (elixir-lsp/elixir-ls#39) but need to be able to find the references for a function from it's definition (which I think makes sense from a usability standpoint as well).

Provide first class support for type specs

  • Autocomplete - Suggest available options for function arguments that are kw lists (options)
  • Autocomplete - Suggest types when in a module scope
  • Find documentation of types
  • Go to definition for types

Bump elixir reqirement to 1.7

Main reason: elixir-ls already requires 1.7 and lots of tests are already failing on 1.6

  • Refactor ElixirSense.Core.Normalized.Code to expose EEP-48 doc format
  • Remove 1.6 code from ElixirSense.Core.Normalized.Typespec
  • Remove 1.6 code from ElixirSense.Core.Normalized.Tokenizer

Potential bug in ElixirSense.Core.Introspection.actual_mod_fun/4

I'm looking into a test failure in the https://github.com/elixir-lsp/elixir-ls/ repo. I believe that I've tracked it down to a potential bug that occurs when trying to find the actual_mod_fun of a function named "fun" fails because it is detected as a built-in type, but a function named "my_fun" or pretty much any other name succeeds.

Example module that is not correctly recognized:

    defmodule B.Callee do
      def fun() do
           ^
        :ok
      end
    end

This results in a call to ElixirSense.Core.Introspection.actual_mod_fun/4 with the args:

    mod_fun: {nil, :fun}
    imports: []
    aliases: []
    module: B

In earlier versions of ElixirSense this would return {B, :fun} but on the current master (899db30) it returns {nil, :fun} because that is what is returned by find_builtin_type/1 (which executes before find_function_in_current_module/2).

The change appears to have happened in b5c56c1

Note: I think this was the actual error underlying #41

Infinite loop with increasing memory

Okay, was finally able to capture detailed info about the loop/memory issue mentioned in elixir-lsp/elixir-ls#82

Here are the screenshots that I captured

memory-processinfo

memory-stacktrace

We can see that there is an infinite loop of lines 700, 712, 710 (this is on commit 2dc70af):

https://github.com/elixir-lsp/elixir_sense/blob/2dc70afe9880ab8dc1/lib/elixir_sense/core/introspection.ex#L700

What is happening appears to be that find_metadata_function is currently operating on a nil module and then it recursively calls itself. So a solution would probably involve adding a case to the Enum.find/2 call that handles a nil module non-recursively.

While I ran into this on commit 2dc70af, the same issue appears to still exist on the master branch.

Get Behaviour callback defined spec when showing type def of the implementation

Environment

  • Elixir & Erlang versions (elixir --version): Erlang/OTP 24 - Elixir 1.12.2
  • Operating system: ArchLinux
  • Editor or IDE name (e.g. Emacs/VSCode): NVim
  • Editor Plugin/LSP Client name: nvim-lspconfig

Troubleshooting

  • Restart your editor (which will restart ElixirLS) sometimes fixes issues
  • Stop your editor, remove the entire .elixir_ls directory, then restart your editor
    • NOTE: This will cause you to have to re-run the dialyzer build for your project

When I hover over a function implementation of a callback, it shows me term typespec instead of the defined callback typespec. ie.

defmodule MyBehaviour do
  @callback print(name :: binary()) :: :ok
end

defmodule MyPrinter do
  @behaviour MyBehaviour

  @impl true
  def print(name), do: :ok
end

Hovering to MyPrinter.print displays MyPrinter.print(term) and it should be MyPrinter.print(binary) :: :ok

How can I see the correct function typespec?

Add umbrella support for "Find References"

I noticed that ElixirLS does not use ElixirSense.references/3. That means it will not benefit from the latest changes that provide accurate information on function calls references, including the column range and a bunch of other improvements. Those changes are absolutely necessary for the refactoring feature.

@balduncle, maybe this was the problem you were facing?

@JakeBecker be aware that the current ElixirLS implementation is not compatible with the latest version of ElixirSense. There's at least one breaking change regarding ElixirLS.LanguageServer.Providers.References calling functions from the ElixirSense.Core.Introspection module. Usually, in order to avoid more incompatibilities, clients should try as much as possible to only call functions from the public ElixirSense module API, which is the official API.

As far as I could see, the only thing that was implemented in the ElixirLS version that was not implemented in ElixirSense, is the support for references in umbrella projects here.

So, I believe we should, in ElxirSense:

  • Add umbrella support for "Find references"
  • Document that only functions from the ElixirSense module are part of the public API.

In ElixirLS:

  • Use ElixirSense.references/3 instead of own implementation
  • Search for other modules that are using ElixirSense non-public API and check if they still work.

@axelson and @lukaszsamson I'm not sure if elixir-lsp/elixir-ls is in sync with the upstream version but I believe it would present the same problem.

Fix master

Hi @lukaszsamson!

I can see the last commit is breaking the build so I wonder if there's more work to be merged soon to fix that. Otherwise, I think the commit should be reverted so we can keep the master stable to accept other changes. I don't have much context regarding the last changes but in case you need any help, please let me know. I have some stuff I want to commit but I prefer to wait for the master to be stable before pushing them.

Cheers.

Add ecto plugin

I'm working on a plugin to improve Ecto support for editors. The first two features are:

  1. Improve snippets to provide the list of available types when completing field or add. Example:

image

  1. Context-aware suggestions for from:

image

@lukaszsamson in the example above, how hard would be to identify the variable u as an instance of %User{}?

Unnecessary suggestions inside heredoc

The following test is failing

  test "no completion inside docstring" do
    buffer = """
    defmodule MyModule do
      @moduledoc \"\"\"
      This is a module asd.
      \"\"\"
    end
    """

    assert [] == ElixirSense.suggestions(buffer, 3, 24)
  end

Suggestions are not aware that this is heredoc and are providing results for asd. subject.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.