IntelliJ Elixir v4.3.0

Thanks

  • Thanks to @gremlinLee, Huy Hoang (@huyh) , Ratan Paul (@RatanPaul) and @anehing for reporting NoSuchMethod errors on GeneratedParserUtilBase, which motivated me to actually ask JetBrains how to fix the problem, where Yann Cébron (@YannCebron)
  • Thanks to Alexander Merkulov (@merqlove) for opening an issue that Go To Definition didn’t work for aliases as before that the issue was just in my head. Go To Definition (and completion) for Aliased ended up being the primary feature of this release, so thanks Alexander.
  • Thanks to Josué Henrique Ferreira da Silva (@josuehenrique) for reporting that Go To Symbol broke on schema metaprogramming in Ecto, which led to support for looking outside Enum.map functions for enclosing modulars.
  • Thanks to Robin Hilliard (@robinhilliard) for reporting that unquoting of literal variables (unquote({name, [], nil}) in type specs was broken
  • Thanks to Max Baumann (@dudeman) for reproduction case in DBConnection.Connection.sync_stop/4 for variable resolution not working for pinned variable in receive clauses.
  • Thanks to Filip Haglund (@drathier), Gerard de Brieder (@smeevil), Markus Fischer (@mfn) and Alexander Tovstonozhenko (@alextov) for let me know that users wanted to be able to turn off Module directive (alias, import, require, user) folding.
  • Thanks to Halil Özgür (@halilim) excellent reproduction case for revealing the reason for mystery isParameter errors.

Changelog

v4.3.0

Enhancements

  • #387 - Resolve aliased modules to their alias call, from the alias call, you can Go To Declaration for the module itself. - @KronicDeth
    • Code structure
      • Module resolution uses the OpenAPI convention of treeWalkUp now instead of custom code.
      • Resolvable names has been extracted to its own class
    • Resolution use cases
      • Suffix resolves to alias Prefix.Suffix
      • Suffix.Nested resolves to alias Prefix.Suffix
      • As resolves toalias Prefix.Suffix, as: As`
      • NestedSuffix resolves to alias __MODULE__.NestedSuffix
  • #389 - Completion for module aliases - @KronicDeth
    • From in-file aliases
    • __MODULE__
    • In project modules (using index already used for Go To Declaration)
  • #393 - In addition to StubBased#canonicalName, there now also StubBased#canonicalNames, for when a call defines multiple canonical names, as is the case for defimpl <PROTOCOL>, for: [<TYPE>, ...]. - @KronicDeth
  • #397 - When a aliased name is added to the module list for completion, it’s unaliased name is searched for in the AllName index, if any nested modules are found for the unaliased name, then those nested names are aliased and also shown for completion. - @KronicDeth
  • #399 - resolvableName allows nested modules under multiple aliases to be completed. - @KronicDeth
  • #403 - By user request, the folding will be off-by-default now, but can be re-enabled, like the old behavior by checking the checkbox in Preferences > Editor > General > Code Folding > Elixir Module directive (alias, import, require or use) groups. - @KronicDeth
  • #405 - @KronicDeth
    • Resolve as: aliased name to both alias and defmodule
    • Complete modules nested under as: aliased name.
  • #409 - @KronicDeth
    • Completion and reference tests for aliases:
      • alias Prefix.Suffix
      • alias Prefix.Suffix, as: As
      • alias Prefix.{MultipleAliasA, MultipleAliasB}

Bug Fixes

  • #393 - @KronicDeth
    • defimpl <PROTOCOL>, for: [<TYPE>, ...] generates multiple canonical names, which are stored in the stub index.
  • #400 - @KronicDeth
    • Look outside Enum.map for enclosing macro call because Ecto defines the clauses of __schema__(:type, ...) using Enum.map, but enclosingMacroCall only knews to jump over enclosing macros like for, so a special case was added for anonymous function given to Enum.map.
    • Fix if-else-ordering bug where Call appeared before operations (which are usually Calls) like Match.
  • #401 - In @type unquote({name, nil, []}) :: foo, name will be highlighted as a type parameter even though it is not strictly the name that will appear as a type parameter. - @KronicDeth
  • #405 - @KronicDeth
    • Resolve alias nested under aliased modules to both the alias and defmodule, as resolving to only the alias loses the nested name, so it wasn’t possible to jump to the nested name’s defmodule.
    • Resolve aliased name to both the alias and the defmodule, so you can skip jumping to the alias before jumping to the defmodule.
  • #406 - @KronicDeth
    • The generated ElixirParser uses the GeneratedParserUtilBase from com.intellij.lang.parser, but since that version is a synced copy, it is a snapshot of GeneratedParserUtilBase from the version of GrammarKit that was current when the IDE was released. To ensure the generated parser works on all the IDEs, I copy GeneratedParserUtilBase from org.intellij.grammar.parser into org.elixir_lang.grammar.parser and then use that version in ElixirParser. This ensures neither the IDE’s version nor the version in any installed GrammarKit plugin is used.
  • #409 - @KronicDeth
    • Check that index name maps to an actual project element before returning it for completion as the names from StubIndex.getInstance.getAllKeys(...) is a superset of actual keys in the actual project according to Peter Gromov of JetBrains.
    • Don’t index canonicalName if it matches the literal name, as the duplicate name leads to duplicate entries in the completion lookup.
      • canonicalNameCollection was renamed to canonicalNameSet (with type changing from Collection<String> to Set<String> to match) to emphasize that the canonical names should be unique, but canonicalNameSet itself should still include duplicates of name for those places where only canonical names are used.
    • Use resolvableName for the unaliasedName for MultipleAliases Aliases, so that they complete correctly for nested modules.
    • Completion for nested modules will no longer complete with string suffixes (i.e. SSHView) and only complete nested Aliases (i.e. SSH.Key).

README Changes

Completion

Aliases and Modules

When you start typing an Alias, completion will look in three locations:

  1. alias aliased names in the current file
    a. Suffix for alias Prefix.Suffix
    b. MultipleAliasA or MultipleAliasB for alias Prefix.{MultipleAliasA, MultipleAliasB}
    c. As for alias Prefix.Suffix, as: As
  2. Indexed module names (as available from Go To Symbol)
    a. Prefix.Suffix from defmodule Prefix.Suffix
    b. MyProtocol from defprotocol MyProtocol
    c. MyProtocol.MyStruct
    i. defimpl MyProtocol, for: MyStruct
    ii. defimpl MyProtocol nested under defmodule MyStruct
  3. Nested modules under aliased names
    a. Suffix.Nested for alias Prefix.Suffix where Prefix.Suffix.Nested is an indexed module, implementation or protocol name.
    b. MultipleAliasA.Nested for alias Prefix.{MultipleAliasA, MultipleAliasB} where Prefix.MultipleAliasA.Nested alias Prefix.{MultipleAliasA, MultipleAliasB} is an indexed module, implementation or protocol name.
    c. As.Nested for alias Prefix.Suffix, as: As where Prefix.Suffix.Nested is an indexed module, implementation, or protocol name.

Go To Declaration

Go To Declaration is a feature of JetBrains IDEs that allows you to jump from the usage of a symbol, such as a Module
Alias, to its declaration, such as the defmodule call.

Alias

  1. Place the cursor over an Alias with an aliased name setup by alias
    a. Suffix if alias Prefix.Suffix called
    b. MultipleAliasA if alias Prefix.{MultipleAliasA, MultipleAliasB} called
    c. As if alias Prefix.Suffix, as: As
  2. Activate the Go To Declaration action with one of the following:
    a. Cmd+B
    b. Select Navigate > Declaration from the menu.
    c. Cmd+Click
  3. A Go To Declaration lookup menu will appear, allowing you to jump either the alias that setup the aliased name or jumping directly to defmodule of the unaliased name. Select which declaration you want
    a. Use arrow keys to select and hit Enter
    b. Click

Module

  1. Place the cursor over a fully-qualified Alias
    a. A.B in A.B.func()
    b. A.B in alias A.B
    c. B in alias A.{B, C}
  2. Activate the Go To Declaration action with one of the following:
    a. Cmd+B
    b. Select Navigate > Declaration from the menu.
    c. Cmd+Click

If you hold Cmd and hover over the Alias before clicking, the target declaration will be shown.

Installation

Inside IDE using JetBrains repository

  1. Preferences
  2. Plugins
  3. Browse Repositories
  4. Select Elixir
  5. Install plugin
  6. Apply
  7. Restart the IDE

Inside IDE using Github releases

In browser

  1. Go to releases.
  2. Download the lastest zip.

In IDE

  1. Preferences
  2. Plugins
  3. Install plugin from disk…
  4. Select the downloaded zip.
  5. Apply
  6. Restart the IDE.
7 Likes