IntelliJ Elixir - Elixir plugin for JetBrain's IntelliJ Platform

Version 6.6.0

Donate

Thanks

  • For reporting that HEAD-<SHA1> format used for brew install --head elixir directory was unparsable and caused a null Version and a NPE when sorting to determine the default directory.
  • For letting me know that templates are compiled to private functions in View modules.
  • For explaining how ERB is implemented in Rubymine and pointing to handlebars as an open-source implementation of a similar language.

Changelog

v6.6.0

Enhancements

  • #923 - @KronicDeth
    • EEx support
      • Lexer for EEx format
      • Parser for EEx format
      • EEx as a Template Language
        • Any file with .eex as the final extension will be treated as EEx. To determine the Template Data Language, the .eex extension will be stripped and any remaining extension will be looked up to get the File Type and its associated Language. For example, *.txt.eex will be EEx with Plain Text (.txt) as the Data Template Language. Likewise, *.html.eex will be EEx with HTML as the Data Template Language. There’s no need to register *.txt.eex or *.html.eex or any other *.DATA_TEMPLATE_LANGUAGE_EXTENSION.eex pattern explicitly: the nested extension will be looked up using the normal extension setup.
    • Update Build Matrix
      • IDEA 2016.2 is dropped because it’s over a year old. It is still supported, but not actively tested.
  • #931 - Decompile LocT chunk for private macros and functions and the derived names of anonymous functions. - @KronicDeth

Bug Fixes

  • #910 - mix hex.local --forcemix local.hex --force in README - @bryanhuntesl-lowpriv
  • #930 - @KronicDeth
    • Parse HEAD-<SHA1> as 0.0.<SHA1> for sorting versions from homebrew homepath. It will almost always be last unless there is an unknown version, which uses 0.0.0.
    • Ensure any unparsable version sorts as 0.0.0 (UKNOWN_VERSION).
  • #932 - @KronicDeth
    • Look at parent of eexTag to resolve fn parameters
    • Ensure functions fn in eex tags don’t error by looking at eex element parent.
    • Search above eexTag and eex to determine if variable.

README updates

Embedded Elixir (EEx) Templates

Any file with .eex as the final extension will be treated as Embedded Elixir (EEx) templates. To determine the Template Data Language, the .eex extension will be stripped and any remaining extension will be looked up to get the File Type and its associated Language. For example, *.txt.eex will be EEx with Plain Text (.txt) as the Data Template Language. Likewise, *.html.eex will be EEx with HTML as the Data Template Language. There’s no need to register *.txt.eex or *.html.eex or any other *.DATA_TEMPLATE_LANGUAGE_EXTENSION.eex pattern explicitly: the nested extension will be looked up using the normal extension setup.

Form Template

Parameter Usage in Form Template

Advanced configuration

If you need more file-by-file configuration of the Template Data Language than can be achieved with a file extension/pattern, IntelliJ IDEA (Community or Ultimate Edition) has support for setting the Template Data Language on a specific path.

  1. Preferences > Languages and Frameworks > Template Data Languages

Call definition macros

It turns out that in the .beam binary format there are no macros. This makes sense since the BEAM format was made for Erlang, which does not have macros, and only has functions. Elixir marks its macros in the compiled .beam by prefixing them with MACRO-.

There are 2 chunks in the BEAM format for function references: ExpT, which is for exports (because in Erlang module they are from -export), which are the public functions and macros; and LocT, which is for locals (anything not exported in Erlang), which are private functions and macros.

BEAM Chunk Atom Prefix Macro
ExpT MACRO- defmacro
ExpT N/A def
LocT MACRO- defmacrop
LocT N/A defp
defp with / in name

Much like there are no macros in BEAM, there are no anonymous functions either. Any anonymous function (using fn in Elixir or fun in Erlang) ends up being a named function in the LocT chunk. Anonymous functions names start with -, then the parent function’s name, a / and a unique number for that scope.

As an example, Kernel has

defp unquote(:"-MACRO-binding/2-fun-0-")(p0, p1, p2, p3) do
  # body not decompiled
end

which is generated from the for in

 defmacro binding(context \\ nil) do
    in_match? = Macro.Env.in_match?(__CALLER__)
    for {v, c} <- __CALLER__.vars, c == context do
      {v, wrap_binding(in_match?, {v, [generated: true], c})}
    end
  end

Kernel.binding/1

[Removal of EEx work-around]

Installation Instructions

3 Likes

v6.7.0

Donate

Thanks

  • For reporting performance issues with nesting anonymous functions
  • For helping with parser change ideas
  • For reporting general performance issues

Changelog

v6.7.0

Enhancements

  • #943 - @KronicDeth
    • Regression test for #580
    • {EOL}|. -> {ANY} in Elixir.flex
    • Convert (some) unimportant newlines from EOL to WHITE_SPACE token, as GrammarKit is smarter about reparsing when only WHITE_SPACE changes in size.
      • After
        • fn
        • do
        • ->
        • block identifier (after, catch, else, and rescue)
        • keyword pair colon
        • (
      • Before
        • Comments

Bug Fixes

  • #943 - @KronicDeth
    • Remove !stabOperationPrefix before expression, since stabOperationPrefix itself starts with expression and instead put a negative look-ahead, !(infixComma | stabInfixOperator) after expression. This now works when it previously didn’t because COMMA was added to expressionRecoverUntil, which means both COMMA and STAB_OPERATOR are now in both not eaten by expression's error recovery.

      This drops Fn1 through Fn8 to ~176ms instead of the previous time of the last optimization of 13 seconds for Fn8. It started at 26 seconds and now it appears that the time no longer grows with the number of fn. It also eliminates the pause when hitting entering inside the fn nesting.

      Data and Chart

Installation Instructions

2 Likes

Version 7.0.0

Donate

Thanks

  • For reporting that mix credo spiking the CPU can make IntelliJ appear sluggish while its using mix credo for annotations.
  • For explaining how to properly switch invalidate the parsed files when the Elixir level changes when the SDK changes

Changelog

v7.0.0

Enhancements

  • #944 - @KronicDeth
    • Eliminate the majority of the eolStar parser rules around operators where they do not matter leaving only the eolStar after COMMA and the the ones that help differentiate unary and binary +/-. This simplifies the parser and under certain conditions should prevent reparsing when only WHITE_SPACE changes in size.
      • Look-ahead in the lexer, where it’s cheaper than the parser to see if the next token does not care if there’s an EOL or normal WHITE_SPACE.
      • After operators that don’t care if they are followed by EOL, try to match all following WHITE_SPACE, ESCAPED_EOL and EOL.
  • #950 - @KronicDeth
    • If you want to limit the performance impact of the credo annotator because mix credo spikes your CPU, you can limit the number of mix credo runs to 1 per open file by disabling the Explanation tooltip

      1. Preferences > Editor > Inspections > Credo
      2. Uncheck “Include Explanation”

      If you don’t want the annotator to run at all on open editors, then you can disable the paired
      inspection

      1. Preferences > Editor > Inspections
      2. Uncheck Elixir > Credo

      If you’ve unchecked the inspection, it disables both the annotation and the pair inspection when Analyze > Inspect Code… is run. You can still run the Credo inspection by name.

      1. Analyze > Run Inspection By Name… (⌥⇧⌘I)
      2. Type “Credo”
      3. Select “Credo” from the shortened list
      4. Hit Enter.

      You’ll be presented with a “Run ‘Credo’” dialog

      1. Change the “Inspection scope” from “Whole project”, which would include the deps to “Custom scope”
      2. Select “Project Production Files” from the “Custom scope” dropdown
      3. Click “OK”
  • #951 - @KronicDeth
    • Setup VirtualFilePointerManager during ParsingTestCase
    • Put LineMarkerInfo on leaf elements for Method (Call Definition) Separators for a performance improvement.
    • Add IntelliJ IDEA 2017.3 to the build matrix

Bug Fixes

  • #947 - When the SDK changes, record what Release of Elixir is used indirectly, using a Level enum that only cares about the major and minor version. Changing the Level, will mark the open files and .beam files as invalidated, so that if the SDK is changed, the stubs and code Level will agree, so there isn’t a stub incompatibility with the PSI. - @KronicDeth
  • #950 - Allow credo section to be empty when processing credo explanations - @KronicDeth
  • #951 - @KronicDeth
    • Prevent negative indent, not supported in 2017.3
    • Cleanup SDKs from MixProjectImportBuilderTest

Incompatible Changes

README Updates

Credo

Annotator

If credo is not installed as a project dependency, nothing will happen, but if it is installed, mix credo PATH will be called on any files after updates have quieted. Any credo check failures will show up as warning annotations

Individual check failures will show the explanation (from mix credo PATH:LINE(:COLUMN)) if you hover over the annotation

You can hover over the explanation and click the embedded links to jump to the line (and column) where the failure occurred.

Inspection

Batch Mode

If you’d like to run the mix credo external annotator when it is disabled, you can run it using the inspection name.

  1. Analyze > Run Inspection By Name… (⌥⇧⌘I)
  2. Type “Credo”
  3. Select “Credo” from the shortened list
  4. Hit Enter.

You’ll be presented with a “Run ‘Credo’” dialog

Run 'Credo'

  1. Change the “Inspection scope” from “Whole project”, which would include the deps to “Custom scope”
  2. Select “Project Production Files” from the “Custom scope” dropdown
  3. Click “OK”

The Inspections Result Tool Pane will open and show results as each file is processed.

  1. Click the :arrow_forward: to expand the Credo section to show all warnings

    Individual Entry

  2. Click an entry for the details of an individual warning with a code highlighting.

    Code Highlighting

    The view will show the parts of the file that aren’t annotated as collapsed with the discontinuous line number indicating the jumps.

    If you click on + collapse markers, you can expand the collapsed sections to see the full context

    Expansion

    Or you can hover over the collapsed section to see a tooltip preview of the expansion

    Expansion Preview

Configuration

Preferences > Editor > Inspections Preferences > Editor > Inspections > Credo Editor Inspections
Elixir > Credo Include Explanation Highlight Message Explanation in tooltip mix credo Runs Highlight Message mix credo Runs Action
Per File Per Issue Working Directory Inspect Code Run Inspection By Name
Yes Yes Yes 1 1 Yes Yes 1 Yes Yes
Yes Yes No 1 0 Yes Yes 1 Yes Yes
ⁿ/ₐ No No No 0 0 Yes Yes 1 No Yes

If you want to limit the performance impact of the credo annotator because mix credo spikes your CPU, you can limit the number of mix credo runs to 1 per open file by disabling the Explanation tooltip

  1. Preferences > Editor > Inspections > Credo
  2. Uncheck “Include Explanation”

If you don’t want the annotator to run at all on open editors, then you can disable the paired inspection

  1. Preferences > Editor > Inspections
  2. Uncheck Elixir > Credo

Once the annotator is disabled, you can still run the inspection in batch mode

Installation Instructions

1 Like

Version 7.1.0

Donate

Changelog

v7.1.0

Enhancements

  • #955 - @KronicDeth
    • Start using Kotlin for new development.
    • Elixir Facet in Small IDEs
      • Preferences > Languages & Frameworks > Elixir can set the Elixir Facet SDK for the Project Module used in Small IDEs as a per-project settings.
      • Preferences > Languages & Frameworks > Elixir> SDKs can add, delete, and configure Elixir SDKs as per-application settings.
      • Preferences > Languages * Frameworks > Elixir > Internal SDKs can add, delete, and configure Erlang SDK for Elixir SDKs as per-application settings.
    • Configure SDK before running mix when importing mix projects, so that the mix path does not need to be configured separately from the SDK path.
      • The mix path no longer needs to be setup independently from the Elixir SDK.
  • #957 - Add Local shared credo inspection, so the the credo inspection works for Code > Code Cleanup. - @KronicDeth
  • #958 - @KronicDeth
    • Show Mix ExUnit in context menu in Elixir Facets, so that

      • Run ‘Mix ExUnit …’
      • Debug ‘Mix ExUnit …’
      • "Create “Mix ExUnit …'”

      appear in Rubymine when you right-click the test directory and it is Marked as a Test Sources Root. It will appear green in Rubymine if already marked. To mark it, do the following:

      1. Right-Click test directory
      2. Select “Mark Directory as > Test Sources Root”

Bug Fixes

  • #955 - @KronicDeth
    • Protect access to JavadocOrderRootType.getInstance() so that it doesn’t cause an error in Small IDEs where its Extension Point is not defined.
    • If the explanation tooltip is empty, fallback to the message for the credo annotator instead.
  • #956 - Check if SdkAdditionalData is null before getting ErlangSDK as it can be null in certain scenarios in Rubymine. - @KronicDeth
  • #958 - @KronicDeth
    Fix isConfigurationFromContext, so that it works on Mix ExUnit Run Configurations generated from directories. Check if the programParameters and workingDirectory match by just
    generating another configuration from the context as this ensures the logic matches and includes support for PsiDirectory.

README Updates

From Existing Sources

Import project from external model

If you’ve already created a mix project, you can load it as an Elixir project into the plugin.

  1. File > New > Project From Existing Sources…
  2. Select the root directory of your project.
  3. Select “Import project from external model”
  4. Select Mix
  5. Click Next
  6. Select a Project SDK directory by clicking Configure.
  7. The plugin will automatically find the newest version of Elixir installed. (NOTE: SDK detection only works for
    Linux, homebrew installs on OSX, and Windows. Open an issue
    with information about Elixir install locations on your operating system and package manager to have SDK detection
    added for it.
    )
  8. If the automatic detection doesn’t find your Elixir SDK or you want to use an older version, manually select select
    the directory above the bin directory containing elixir, elixirc, iex, and mix. (On Windows it is the
    directory containing elixir.bat, elixirc.bat, iex.bat, and mix.bat.)
  9. Click Finish after you select SDK name from the Project SDK list.
  10. The “Mix project root” will be filled in with the selected directory.
  11. (Optional) Uncheck “Fetch dependencies with mix” if you don’t want to run mix deps.get when importing the project
  • If “Fetch dependencies with mix” is checked both mix local.hex --force and mix deps.get will be run.
  1. Click Next
  2. All directories with mix.exs files will be selected as “Mix projects to import”. To import just the main project and not its dependencies, click Unselect All.
  3. Check the box next to the project root to use only its mix.exs. (It will likely be the first checkbox at the top.)
  4. Click Finish

SDK

Because Elixir is built on top of Erlang, Elixir command line commands don’t have OS native binaries, instead the OS native binaries from Erlang are used. In order to reliably find the Erlang OS native binaries, like erl and erl.exe, the path to BOTH the Erlang SDK and the Elixir SDK must be configured. This allows you to install Erlang and Elixir with completely different package managers too: you can install Erlang with kerl and Elixir with kiex and you don’t have to worry about IntelliJ not seeing the environment variables set by kerl when launching IntelliJ from an application launchers instead of a terminal.

Since JetBrains’ OpenAPI only supports one SDK per Project or Module, to support Elixir and Erlang SDK at the same time, the Elixir SDK keeps track of an Internal Erlang SDK. When setting up your first Elixir SDK, you will be prompted to create an Erlang SDK (if you have the intellij-erlang plugin installed) or and Erlang for Elixir SDK (if you don’t have intellij-erlang installed and you need to use the minimal Erlang for Elixir SDK supplied by this plugin).

Rich IDEs

Rich IDEs can use the Project Structure system to configure Elixir and Erlang SDKs and select the Project/Module SDK.

Small IDEs

Because Small IDEs like Rubymine do not have Project Structure, the Elixir SDK, Erlang SDK, and selected SDK must be configured in Preferences.

Elixir Facet SDK

Facets are a feature of JetBrains OpenAPI that allow additional languages and frameworks to be added to a Module. In Small IDEs, each Project has only one Module and its SDK MUST match the Small IDE’s language, such as a Ruby SDK in Rubymine, so to allow an Elixir SDK to be selected, an Elixir Facet is added to the Module in Small IDEs.

To configure the Elixir Facet SDK

  1. Open Preferences > Languages & Frameworks > Elixir
  2. Select a previously created Elixir SDK from the SDK combo box.
  • If there is no Elixir SDK, you can create one first.
  1. Click Apply to save the Preferences changes or OK to save and close.
Elixir SDKs

In Small IDEs, Elixir SDKs are tracked as Application Preferences, so any Elixir SDK you create in one project will be usable in another and you won’t have to create the SDK in each project, just select it.

  1. Open Preferences > Languages & Frameworks > Elixir > SDKs

  2. Click + to add a new Elixir SDK

  3. If you don’t already have an Erlang SDK for Elixir SDK setup, you’ll need to create one first.

  4. You’ll be prompted with the default path for the most recent version of Erlang installed.

    You can change directory to a select a different version. The home directory for “Erlang SDK for Elixir SDK” for Homebrew is NOT /usr/local/Cellar/erlang/VERSION, but /usr/local/Cellar/erlang/VERSION/lib/erlang due to where the OTP app ebin directories are located.

  5. Click OK to create the Erlang SDK for Elixir SDK.

  6. With at least one Erlang SDK for Elixir SDK setup, you’ll be prompted with the default path for the most recent version of Elixir installed.

  7. Click OK to create the Elixir SDK.

  8. Click Apply to save the Preferences changes or OK to save and close.

You can further customize the Elixir SDK by selecting its name from the left list.

  • Change Home Path
  • Change Internal Erlang SDK
  • Change ebin directories on the Classpath tab
Internal Erlang SDK

If you want to change the Internal Erlang SDK, you’ll need to create a new Erlang SDK for Elixir SDK.

  1. Open Preferences > Languages & Frameworks > Elixir > Internal SDKs

  2. Follow the same steps as above to create an SDK

Installation Instructions

2 Likes

Version 7.2.0

Donate

Thanks

  • For reporting that OrderRootType.getOrderRootType now has a @NotNull annotation, which causes newer Small IDE releases to break when trying to access JavaDocRootType.getInstance().
  • For reporting “invokeAndWait from read-action leads to possible deadlock” warning

Changelog

v7.2.0

Enhancements

  • #963 - mix runs will be faster as they will no longer check to see if the SDK is updated. - @KronicDeth

Bug Fixes

  • #963 - Avoid problems with read and write locks when updating Elixir SDK on-demand by instead updating them when any project is open using a project converter. - @KronicDeth
  • #964 - JetBrains/intellij-community@9adbba0 added @NotNull to OrderRootType.getOrderRootType, which JavaDocRootType.getInstance calls, which means any Small IDE using intellij-community since 4 months ago, including the newest CLion cannot have JavadocOrderRootType.getInstance safely called. - @KronicDeth
  • #966 - Path changes were not being written back to disk because the projectSdksModel.apply() was being called before the editor.apply(), which would have copied to the editor's path changes to the projectSdksModel. - @KronicDeth

Installation Instructions

2 Likes

Version 7.2.1

Donate

Thanks

  • For reporting that .bat was no longer needed on WIndows
  • For reporting that Credo annotator broke on Elixir scratch files
  • For reporting that another read action wrapper was needed in the Mix project importer
  • For reporting ExternalLanguageAnnotators.allForFile was being called with a null PsiFile
  • For reporting the Credo annotator, in certain projects, severely slows down the responsiveness of the editor.
  • For pairing with me to demonstrate the responsiveness problems
  • For reporting that configuring Erlang SDK for Elixir SDK failed when more than CLASSES and SOURCES Root Types are installed

Changelog

v7.2.1

Bug Fixes

  • #980 - Use documentionRootType to indirectly get the documentation OrderRootType in the Erlang SDK Type, so that it works in Small IDEs that have more than CLASSES and SOURCES root types installed. - @KronicDeth
  • #981 - @KronicDeth
    • The credo annotator is disabled by default as numerous users find running mix credo in the background has a negative impact on their system performance. If you like to try enabling the annotation, you can turn it on using the configuration.

      1. Preferences > Editor > Inspections > Elixir
      2. Check “Credo”
      3. Click OK to save and close Preferences

      If you notice a degradation the in the responsiveness of the editor, it is recommended you disable the annotator again.

      1. Preferences > Editor > Inspections > Elixir
      2. Uncheck “Credo”
      3. Click OK to save and close Preferences
  • #982 - Protect from PsiFile being null in Local credo inspector - @KronicDeth
  • #983 - Run Qualified#moduleName getText in Read Action. - @KronicDeth
  • #985 - Scratch Files have a Project, but not a Module, so change flow to use Project when Module is null in credo annotator. - @KronicDeth
  • #986 - Don’t add .bat to mix on Windows. mix is never run as an executable. It is either run as a script to elixir.bat OR as an argument to erl.exe when erl.exe is running elixir. - @KronicDeth

README Updates

Credo

Annotator

When enabled, if credo is not installed as a project dependency, nothing will happen, but if it is installed, mix credo PATH will be called on any files after updates have quieted. Any credo check failures will show up as warning annotations

Warning Annotations

Individual check failures will show the explanation (from mix credo PATH:LINE(:COLUMN)) if you hover over the annotation

Explanation

You can hover over the explanation and click the embedded links to jump to the line (and column) where the failure occurred.

Enable

The credo annotator is disabled by default as numerous users find running mix credo in the background has a negative impact on their system performance. If you like to try enabling the annotation, you can turn it on using the configuration.

  1. Preferences > Editor > Inspections > Elixir
  2. Check “Credo”
Disable

If you notice a degradation the in the responsiveness of the editor, it is recommended you disable the annotator again.

  1. Preferences > Editor > Inspections > Elixir
  2. Uncheck “Credo”

Installation Instructions

2 Likes

Version 7.3.0

Donate

Thanks

Changelog

v7.3.0

Enhancements

  • #1015 - @KronicDeth
    • Add supplemental file editor for .beam files: “BEAM Chunks”. The decompiled binary file will continue to be shown on the default “Text” editor tab.
  • #1021 - @KronicDeth
    • Support for Remove incorrect wording regarding test cases · elixir-lang/elixir@23c7542 · GitHub

      Version Struct Started Event Finished Event %ExUnit.Test{} field
      < 1.6.0 %ExUnit.TestCase{} :case_started :case_finished case
      >= 1.6.0 %ExUnit.TestCase{} :module_started :module_finished module

      Because Elixir 1.6.0 could not introduce a breaking change, the < 1.6.0 events are fired, but resources/exunit/1.6.0/team_city_ex_unit_formatting.ex will ignore them and only convert the >= 1.6.0 events to TeamCity event used in the JetBrains Test Runner UI.

  • #1018 - Expose Declarations > Functions and Declarations > Macros in Color Settings - @dimcha

Bug Fixes

  • #1019 - Don’t use StreamEx because support is inconsistent across IDEs - @KronicDeth

README.md Updates

.beam Files

.beam files are the compiled version of modules on the BEAM virtual machine used by Elixir and Erlang. They are the equivalent of .class files in Java.

.beam files are not detected purely by their file extension: the BEAM file format starts with a magic number, FOR1, that is checked for before decompiling.

.beam files have 2 editors registered: decompiled Text and BEAM Chunks

file Editor Tabs

Decompression

If the .beam module was compiled with the compressed compiler directive, which in Erlang looks like

-compile([compressed])

and in Elixir looks like

@compile [:compressed]

then the outer file format is GZip (which is detected by checking for the gzip magic number, 1f 8b, at the start of the file) and the .beam will be (stream) decompressed before the .beam header is checked and the chunks decoded.

BEAM Chunks

.beam files are composed of binary chunks. Each chunk is formatted

Offset +0 +1 +2 +3
0 Name (ASCII Characters)
4 Length (`unsigned-big-integer`)
8+ Chunk-Specific

This format is generically referred to as Type-Length-Value

The BEAM Chunks editor tab is subdivided into further tabs, one for each chunk in the .beam file.

BEAM Chunks editor chunk tabs

The tabs are listed in the order that the chunks occur in the .beam file.

Atom / AtU8

The Atom chunk holds LATIN-1 encoded atoms while AtU8 chunk holds UTF-8 atoms. There will only be one of these atom-related chunks in any given .beam file. AtU8 is used in newer versions of OTP that support UTF-8 atoms. AtU8 was introduced in OTP 20.

Format
Offset +0 +1 +2 +3
0 atom count (`unsigned-big-integer`)
4 length1 (`unsigned-byte`) bytes (for length1)
4+length1+...+lengthn-1 lengthn (`unsigned-byte`) bytes (for lengthn)
Tab

The Atom/AtU8 tab shows a table with the columns

Column Description Source
Index 1-based to match Erlang convention. In the Code chunk, atom(0) is reserved to always translate to nil Derived
Byte Count The byte count for the atom’s bytes Raw
Characters From encoding the bytes as LATIN-1 for Atom chunk or UTF-8 for AtU8 chunk Derived

Attr

The Attr chunk holds the module attributes, but only those that are persisted. Erlang module attributes are persisted by default, but in Elixir module attributes need to be marked as persisted with Module.register_attribute/3

Format

The Attr chunk uses External Term Format (term_to_binary’s output) to encode a proplist, which is similar to, but not quite the same an Elixir Keyword list

All modules will have a :vsn attribute that is either set explicitly or defaults to the MD5 of the module.

Tab

The Attr tab shows a table with the columns

Column Description Source
Key Attribute name Raw
Value Attribute value. Note: The value always appears as a list as read from the binary format. I don’t know why. Raw

Attr Table

CInf

The CInf chunk is the Compilation Information for the Erlang or Erlang Core compiler. Even Elixir modules have it because Elixir code passes through this part of the Erlang Core compiler

Format

The CInf chunk uses External Term Format (term_to_binary’s output) to encode a proplist, which is similar to, but not quite the same an Elixir Keyword list

Tab

The CInf tab shows a table with the columns

Column Description Source
Key Option name Raw
Value Inspected value Raw

CInf Table

Code

The Code chunk contains the byte code for the module.

Format

It is encoded in BEAM Compact Term Encoding, which differs from the binary format produced by term_to_binary.

Tab

The Code tab shows a read-only editor with one byte code operation on each line. For ease of reading, operations are grouped by function and then label block with indentation indicating scope.

By default as many references to other chunks and references to other parts of Code chunk are inlined to ease understanding. If you want to see the raw byte code operations, you can turn off the various inliners.

####### Controls

Control On Off
Inline Atoms atom(0) is inlined as nil atom(N) if "Inline Integers" is Off
atom(n) looks up index `n` in `Atom`/`AtU8` chunk and inlines its `inspect`ed version N if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Functions literal(n) looks up index n in FunT chunk and inlines the name if the argument supports "Inline Functions" literal(n) if "Inline Integers" is Off
n if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Imports literal(n) looks up index n in ImpT and inlines it as a function reference: &module.name/arity if argument supports "Inline Functions" literal(n) if "Inline Integers" Is Off
n if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Integers atom(n) and literal(n) inline as n if argument supports "Inline Integers" atom(n), integer(n), and literal(n)
integer(n) inlines as n
Inline Labels label(n) inlines as n if argument supports "Inline Labels" label(n)
Inline Lines line(literal(n)) looks up index `n` in the "Line Reference" table in the `Lines` chunk. The Line Reference contains a file name index and line. The file name index is looked up in the "File Name" table in the `Lines` chunk. The line from the Line Reference and the File name from the "File Name" table are inlined as `line(file_name: file_name, line: line)`. line operations are left as is
Inline Literals literal(n) looks up index n in LitT chunk and inlines its `inspect`ed version if the argument supports "Inline Literals" literal(n)
Inline Local Calls label(n) finds label(n) in Code chunk, then searches back for the previous func_info operation, then inlines it as a function reference: &module.name/arity if argument supports "Inline Local Calls" label(n)
Inline Strings Looks up bit_length and byte_offset into `StrT` chunk as their CharList value if supported by operation as value to string argument name bit_length and byte_offsetarguments are left as is
Show Argument Names Adds keyword argument names before each argument value Leaves values as positional arguments

If any of the inliners are incorrect or you have an argument name that makes more sense, please open an issue.

Dbgi

The Dbgi chunk contains Debug Info. It was introduced in OTP 20 as a replacement for the Abst chunk. While the Abst chunk was required to contain the Erlang AST, the Dbgi format can contain the debug info for other languages, such as Elixir quoted form AST.

Format

Because the format is language neutral, the format is a set of nested, versioned formats. The outer most layer is

{:debug_info_v1, backend, metadata | :none}

For :debug_info_v1, Elixir’s backend is :elixir_erl. The metadata for :elixir_erl is further versioned: {:elixir_v1, map, specs}.

map contains the bulk of the data.

Key Value
:attributes Attributes similar to the Attr chunk, but at the Elixir, instead of Core Erlang level. Usually they match with the exception that attributes doesn’t contain vsn when Attr contains the MD5 version
:compile_opts Compilation options similar to CInf chunk’s options key, but at for Elixir, instead of Core Erlang level.
:definitions The Elixir quoted AST for reach function clause.
:file The name of the file the module was generated from.
:line The line in :file where the module was defined, such as the line defmodule occurred.
:module The name of the module as an atom
:unreachable Unreachable functions
Tab

The Dbgi tag show the single value map entries: :file, :line, and :module.

Singletons

For the multi-value keys: :attributes, :compile_opts, and :definitions, there are individual tabs.

Multivalue Tabs

####### Attributes

The Attributes tab has the same format as the Attrs chunk.

Dbgi Attributes Table

####### Compile Options

The Compile Options tab is usually empty, much like the CInf options key for Erlang.

Table

####### Definitions

The Definitions tab is split between a tree of Module, Function/Arity and clauses.

Tree

Clicking on a clause will show only that clause, but clicking on a higher level in the tree will show all clauses in the function or the entire Module.



The AST stored in the definitions tab and the process of converting it back to code is not format preserves, so it will not look precisely like the source code as the AST has undergone some macro expansion before its put in the Dbgi chunk. As common idioms are understood, reversals will be add to the renderer.

ExDc

The ExDc chunk stores ExDoc. Not the rendered HTML from the ex_doc package, but the the @doc, @moduledoc, and @typedoc attribute values that work even without ex_doc installed. This chunk is what is consulted when the h helper is used in iex.

Format

The ExDc chunk is the encoded with term_to_binary. The term format is a versioned as {version, versioned_format}. The current version tag is :elixir_docs_v1 and the versioned_format is a Keyword.t with keys matching the Code.get_docs/2 tags :callback_docs, :docs, :moduledoc, and :type_docs keys.

Tab

Like Dbgi, the ExDc tab is split between a tree to navigate and an editor to show the decompiled value.

ExDc Tree

Click on a node in the tree will show all docs at that level and any descendants.

Node Description
Root All docs
Module @moduledoc
Types All @typedocs
Types child A specific @typedoc
Callbacks All @callback @docs
Callbacks child A specific @callback’s @doc
Functions/Macros All @docs for functions/macros
Functions/Macros child A specific function/macro’s @doc
ExpT

The ExpT chunk is the Export Table. The name “Export” derives from the Erlang module attribute -export, which is used to “export” functions from a module. It is the equivalent of making a function or macro public with def and defmacro as opposed to making it private with defp and defmacrop in Elixir.

Format

The BEAM format and the ExpT chunk, being made for Erlang, has no concept of macros. It only understands functions, so Elixir macros, like __using__/1 called by use are compiled to plain Erlang functions with MACRO- prefixed to their name and an extra argument (the __CALLER__ environment) as the first argument, which increases the arity, yielding a full MFA of MACRO-__using__/2 as seen above.

Tab

The ExpT tab shows a table with the columns

Column Description Source
Atom Index Index into the Atom or AtU8 chunk for the function’s name Raw
Name The atom referenced by “Atom Index” Derived
Arity The arity (argument count) of the function Raw
Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

ExpT Table

ImpT

The ImpT chunk is the Import Table. It DOES NOT encode just the Erlang -import attributes or Elixir import macro calls: it tracks any external function or macro called from another module. call_ext_* operations in the Code chunk don’t store the Module and Function (MF) of the function they will call directly in the bytecode, instead, one of the arguments is an index into the ImpT chunk. This way, all external calls are normalized into the ImpT chunk instead of being denormalized to the call site. The arity still appears at the call site to help with checking the argument count.

Format

You may notice that erlang.byte_size/1 is included in the table. This is because even BIFs are referenced by MFA and not a pre-assigned number as would be the case for system calls in operating systems like Linux. BEAM is like an Operation System, but not in all ways.

Tab

The ImpT tab shows a table with the columns

Column Description Source
Index 0-based index used by references in the Code chunk. Derived
Module Atom Index Index into the Atom or AtU8 chunk for the Module’s name Raw
Module Atom The atom referenced by “Module Atom Index”. Derived
Function Atom Index Index into the Atom or AtU8 chunk for the functon’s name Raw
Function Atom The atom referened by “Function Atom Index”. Derived

LitT

The LitT chunk contains literals loaded as arguments in Code chunk.

Format

Confusingly, in the Code chunk sometimes the literal(N) term is used to encode integer N, an index into another chunk, or an actual index into the LitT. How literal terms are handled is completely dependent on the specific operation, so without having outside knowledge about the bytecode operation arguments for BEAM, the best way to figure out if literal terms are an integer or an index is to toggle the various controls in the Code tab to see if literal with no inlining turns into a LitT literal, FunT function reference, ImpT function reference, or integer.

Tab

The LitT tab shows a table with the columns

Column Description Source
# 0-based index used by references in the Code chunk. Derived
Term The equivalent of `raw > binary_to_term()

Line

The Line chunk encodes both the file name and line number for each line(literal(n)) operation in the Code chunk. The n in line(literal(n)) is an index in to the Line References table in the Line chunk. This is used in Phoenix view modules to show where code from templates comes from.

Format

The Line chunk is composed of 2 subsections: (1) Line References and (2) File Names. First there is a header setting up the number of each entry to expect.

Offset +0 +1 +2 +3
0 emulator version (`unsigned-big-integer`)
4 flags (`unsigned-big-integer`)
8 Line Instruction Count (`unsigned-big-integer`)
12 Line Reference Count (`unsigned-big-integer`)
16 File Name Count (`unsigned-big-integer`)

####### Line References

This uses the Compact Term Format used for the Code chunk. The format ends up producing {file_name_index, line} pairs using the following algorithm:

Term Interpretation
atom(n) Change file_name_index to n
integer(n) Add {file_name_index, n} to end of Line References

####### File Names

Offset +0 +1 +2 +3
0 Byte Count (`unsigned-big-integer`) Bytes
Tab

The Line tab has one subtab for each subsection in the tab. Each subsection has its own table.


File Names TableTable

LocT

The LocT chunk is the dual to the ExpT chunk: it contains all private functions and macros.

Format

You’ll notice entries like -__struct__/1-fun-0-, starts with - and have a / suffix with fun in it. This naming scheme is used for anonymous functions such as those defined with fn or the capture operator (&) in Elixir. Much like how macros don’t really exist and use a MACRO- suffix, anonymous functions/lambdas don’t exist, and instead use a distinct naming scheme -<PARENT_FUNCTION>/*fun*. Unlike MACRO-, which is an Elixir invention, anonymous functions/lambdas really being local named functions with derived names is also done in pure Erlang modules. Erlang’s anonymous functions are defined with fun, which is where the fun part of the naming scheme comes from.

Tab

The LocT tab shows a table with the columns

Column Description Source
Atom Index Index into the Atom or AtU8 chunk for the function’s name Raw
Name The atom referenced by “Atom Index” Derived
Arity The arity (argument count) of the function Raw
Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

LocT Table

StrT

The StrT chunk contains all Erlang strings (that is, Elixir charlists) used in the Code chunk.

Format

The StrT chunk contains a single contiguous pool. These strings are used for byte code operations like bs_put_string. Not all strings appear in StrT. Some strings, including most Elixir strings (Erlang binaries) appear in the LitT chunk that holds literals. I’m not sure how the compiler determines whether to use StrT or LitT. I think it all depends on the byte code operation.

Instead of encoding the start and length of each string in the chunk itself, the start and length for any given string is passed as arguments to the byte code operations in the Code chunk. By doing this, shared substrings can be efficiently encoded in StrT.

Tab

StrT Pool

Installation Instructions

3 Likes

Wow, that’s an amazing post and a fantastic update!!

I really need to see if I can get intellij running well so as to use it, the java-built IDE is just sooooo laggy at times (nothing to do with the plugin at all, it just does that anywhere/everywhere). :slight_smile:

2 Likes

The default install of IntelliJ launches the JVM with a max of 750 MB. (Slack and Chrome normally use gigs of memory, so this isn’t a lot really for an IDE) It won’t ask you to increase this memory limit until its been stuck garbage collecting for tens of minutes, so usually, it ends up appearing laggy where it’s stuck GCing a lot when close to the limit.

You can turn on a memory usage display in the bottom right status bar:

  1. Open Preferences > Appearance & Behavior > Appearance.
  2. Scroll down to Window Options
  3. Check Show memory indicator

The docs for IntelliJ explain the status bar in more detail.

You can increase the max allowed memory for the JVM with

  1. Click Help > Edit Custom VM Options
  2. Change the -Xmx argument to change the max memory. m means megabytes, g means gigabytes, so a max memory of 1 gigabyte would be -Xmx1g.
  3. Save the file
  4. Click File > Invalidate Cache / Restart …
  5. Click Just Restart in the dialog

The status bar indicator should show the new max memory in the “C of DM” for C of D megabytes used.

I changed the default allocated memory long ago to 2Gigs just because of those issues in the past. ^.^

A lot of the lag just seems to be in the GUI itself though, like it can take a second to change tabs for one example of many, it’s just lots and lots and lots of little things that combine to make the overall experience feel ‘slow’. Eclipse has the same problems. And it’s the same experience on Windows 10 and multiple linux machines thus far.

1 Like

Version 7.4.0

Donate

Thanks

Changelog

v7.4.0

Enhancements

  • #1036 - @KronicDeth
    • Clean up debugger
      • mix format debugger
      • Restructure debugger.
      • Convert IDE-side to Kotlin
    • Allow files to skip interpreting in the debugger to be configured in Preferences > Build, Execution, Deployment > Debugger > Stepping. It is recommended to customize these settings instead of using INTELLIJ_ELIXIR_DEBUG_BLACKLIST environment variable. INTELLIJ_ELIXIR_DEBUG_BLACKLIST should be reserved to additional modules that need to not be interpreted only for specific runs.
      • Ship a set of patterns that excludes Elixir standard library by default and most mix phx.new dependencies, so that debugger boots faster for most users.
    • Support debugging .eex templates
      • Detect MFAs that refer to template functions in Phoenix view modules derived from .eex template files, to allow stepping through Elixir tags in those templates.
      • Allow setting breakpoints in .eex files when a .beam file using the template’s relative can be found. This means that the Phoenix view module .beam file must exist in _build prior to setting a breakpoint. Run the Run Configuration once, before debugging to complete the build if setting a breakpoint does not work.
        • .beam files are now indexed by their Line chunk filenames subsection to power this feature.
    • Cache .beam Beam Cache on VirtualFile. Cache is invalidated and refreshed on modification of the VirtualFile. Cache is used for both BEAM Chunks read-only editors and Line chunk file name index.
  • #1037 - Each package manager uses a different root path and which directory to pick above the ebins varies by package manager, so document package manager install paths. - @KronicDeth
  • #1041 - @KronicDeth
    • Restructure JPS code to remove prefixes and suffixes in class names that redundant with package names.
    • Show warnings-as-errors checkbox as original blocker has been fixed for awhile and ProcessAdapter turns warning text into errors that IDE understands.
  • #1045 - @KronicDeth
    • When importing Mix projects, don’t exclude compiler output from indexing because it is needed to resolve Elixir Line Breakpoints in EEx files.
      • For pre-existing Elixir modules, they will be converted to not exclude compiler output.
  • #1047 - @KronicDeth
    • Exclude known uninterpretable modules
      • Bcrypt.Base
      • :erocksdb
      • :lz4
      • :re2

Bug Fixes

  • #1036 - @KronicDeth
    • Turn off dbeug flag when starting IntelliJElixir.DebugServer, which removes the *DBG* statements that kept printing in the ExUnit output when using the debugger.
    • Fix conversion of Elixir module names to Erlang module names for INTELLIJ_ELIXIR_DEBUG_BLACKLIST environment variable.
    • Cache null SDK Release, so that when Elixir is configured, but the Erlang path is broken (such as after a brew unlink erlang, the Release calculating using elixir
    • Implement Macro.atomToString
    • Properly render improper lists
      • Show improper list with explicit | for presenation
      • Children of improper lists show head and tail instead of index.
    • Show Elixir indices (0-based) instead of Erlang indices (1-based`) for lists and tuples.
  • #1037 - Loosen check on the path suffix by looking for only lib and not lib/erlang/lib, so that it works for both Homebrew’s ebin paths and ASDF’s ebin paths. - @KronicDeth
  • #1041 - @KronicDeth
    • Remove unused MixBuilder because building with mix is just an option in ElixirBuilder.
    • Harmonize JPS compile server’s invoking of mix to pattern used in Run Configuration runners.
      • Use mix path from SDK
    • No longer say the build succeeded when there are obvious mix errors
      • Parse mix compile output for compilation errors and warnings
        • When “warnings-as-errors” is enabled in “Elixir compiler” settings, IDE also shows warnings as errors.
        • IDE will know build failed if there are errors (or warnings treated as errors) and properly allow rebuild.
  • #1045 - @KronicDeth
    • Group alternatives in erlang_module_name_patterns_to_regex before pinning: I always forget that the | swallows the ^ and $ in regexes.
    • Reject vs filter accumulation got flipped when switching to Enum.reduce to track rejections.
  • #1047 - @KronicDeth
    • Some modules, like NIF modules, can’t be loaded into the debugger. Individual modules not being debuggable shouldn’t kill the debugger task, so rescue the known error and record it for later debugging of the debugger.
    • Add : to start of Erlang module names for included debugger excludes

README updates

Debugger

Basics

Excluding Modules

By default, the debugger will scan all the load paths and build path for .beam files and the corresponding modules will be interpreted which causes the Module’s Erlang abstract code chunk to be interpreted in Erlang instead of the bytecode chunk being executed in the C parts of the BEAM. This interpretation is much slower than execution, so by default all of the Elixir standard library and the common modules installed in Phoenix projects are excluded from being interpreted when the debugger starts. The modules can be still be stepped into or have breakpoints explicitly set.

  1. Preferences > Build, Execution, Deployment > Debugger > Stepping
  2. Scroll to Elixir

Do Not Step Into The Modules

You can customize these module patterns as an application setting.

Disabling Existing Module Patterns
  1. Preferences > Build, Execution, Deployment > Debugger > Stepping
  2. Scroll to Elixir
  3. Click the Checkbox next to the pattern you want to disable
  4. Click Apply to save or OK to save and close Preferences

Disable

Editing Existing Module Patterns
  1. Preferences > Build, Execution, Deployment > Debugger > Stepping
  2. Scroll to Elixir
  3. Click the pattern text box
  4. Click Apply to save or OK to save and close Preferences

Edit

Removing Existing Module Patterns
  1. Preferences > Build, Execution, Deployment > Debugger > Stepping
  2. Scroll to Elixir
  3. Click the row of the pattern you want to remove
  4. Click the “-” Remove button.
  5. Click Apply to save or OK to save and close Preferences

Remove

Removed

Adding New Module Patterns
  1. Preferences > Build, Execution, Deployment > Debugger > Stepping
  2. Scroll to Elixir
  3. Click the “+” Add button
  4. Click the default “*” pattern to edit it
  5. Click Apply to save or OK to save and close Preferences

Add

Added

Environment Variables

If you want to customize the modules to ignore on a per-Run-Configuration basis, you can set an environment variable in the Run Configuration.

Variable Example Description
INTELLIJ_ELIXIR_DEBUG_BLACKLIST iconv,some Excluding modules from debugger

Notice: If you want non Elixir. module in blacklist, write it with: :. This rule applies only to module atoms.

Breakpoints

Creating Line Breakpoints

A line breakpoint is a breakpoint assigned to a specific line in the source code.

Line breakpoints can be set on executable lines. Comments, declarations and empty lines are not valid locations for the line breakpoints. Line break points can be set in .ex and .eex files.

ex

.eex line breaks will only work on Elixir code that is used in Phoenix view modules.

.eex breakpoints only work if a .beam file using the template’s relative can be found. This means that the Phoenix view module .beam file must exist in _build prior to setting a breakpoint. Run the Run Configuration once, before debugging to complete the build if setting a breakpoint does not work.

  1. Place the caret on the desired line of the source code.
  2. Do one of the following:
    • Click the left gutter area at a line where you want to toggle a breakpoint
    • Run > Toggle Line Breakpoint
    • Cmd+F8

Building/Compiling

Settings

  • Compile project with mix (use mix compile instead of elixirc directly)
  • Attach docs (don’t use --no-docs elixirc flag)
  • Attach debug info (don’t use --no-debug-info elixirc flag)
  • Warnings as errors (use --warnings-as-errors elixirc flag)
  • Ignore module conflict (use --ignore-module-conflict elixirc flag)

Build Messages

Source

If a file has errors and warnings, they are group together in Build Messages under that file.

Jump To Source

You can jump to errors and warnings in the Build Messages

  1. Highlight the error or warning you want to jump to source

  2. Do one of the following

    1. Right-Click the error or warning

    2. Select Jump to Source from the context menu

      Jump to Source

    OR

    1. Click the error or warning
    2. Press Cmd+Down

You can also turn on Autoscroll to Source, which will Jump To Source whenever you Click or select an error or warning.

Autoscroll to Source

Warnings as Errors

Setting

If you enable Warnings as Errors in the settings, then the Warnings will be treated as Errors by elixirc and mix and the Build Messages will show the Warnings as Errors.

Messages

If only warnings remain in the source.

Source

With Warnings as Errors On, all the Warnings will appear as Errors and still fail the build

Errors

With Warnings as Errors Off, the Warnings will appear as Warnings and the build will succeed

Warnings

SDK

Package Manager Install Locations

When configuring an SDK, if you don’t want to use the suggested SDK home path, you’ll need to know where each package manager puts Elixir and Erlang.

Package Manager SDK Type Directory
ASDF Elixir SDK ~/.asdf/installs/elixir/VERSION
Erlang SDK ~/.asdf/installs/erlang/VERSION
Erlang for Elixir SDK
Homebrew Elixir SDK /usr/local/Cellar/elixir/VERSION
Erlang SDK /usr/local/Cellar/erlang/VERSION/lib/erlang
Erlang for Elixir SDK
Nix Elixir SDK /nix/store/SHA256-elixir-VERSION/lib/elixir
Erlang SDK /nix/store/SHA256-erlang-VERSION/lib/erlang
Erlang for Elixir SDK

If you can can’t see hidden files, such as .asdf in your home directory (~), or system directories, such as /usr, you will need to enable Show Hidden Files in the Home Path dialog.

If your dialog looks like this, click the Show Hidden Files button

IntelliJ

If you’re using the macOS native File Picker, use the keyboard shortcut ⌘⇧. (Command+Shift+Period).

Installation Instructions

3 Likes

Version 7.5.0

Donate

Thanks

  • For reporting that true: and false: did not work as keyword keys
  • For reporting that creating the editor panel for the BEAM Chunks Code editor at boot raised an “Access is allowed from event dispatch thread only.” error.
  • For reporting that creating the editor panel for the BEAM Chunks Documentation editor at boot raised an “Access is allowed from event dispatch thread only.” error.
  • For requesting that #{ auto-close with }
  • For reporting a potential race-condition that led to pre-maturely decompiling an incomplete .beam file when it is being rebuilt.
  • For reporting that the bad .beam files that are test cases in Erlang’s :kernel test code were correctly caught by the bug reporter, but they should be ignored since they’re a known failure.
  • For reporting the null argument being passed for startingReference in ElixirPsiImplUtil.aliasToModular.

Changelog

v7.5.0

Enhancements

  • #1055 - Refactor ElixirPsiImplUtil into separate files tied to specific classes or interfaces to shrink its size. - @KronicDeth
  • #1073 - Complete #{ with }. - @KronicDeth
  • #1109 - @KronicDeth
    • Read Write Accessor Detector
      • Variable/Parameter declarations/rebindings are highlighted as writes while other usages are highlighted as reads.
    • Improved Find & Show Usages
      • Added Find & Show Usages for Functions at declaration and usage site
        • Multi-clause functions use all clauses as targets and find usages of all clauses.
      • Improved Find & Show Usages for Modules/Aliases
    • Improved Element Descriptions
      • It is easier to distinguish aliases and the defmodule that is being aliased because element description now include alias or defmodule before the Alias name based on how the Alias is defined in the scope.
      • Call definitions use the same presentation for Structure View and Find Usages, so that Compile/Runtime time icons, and visibility are the same in both.
  • #1111 - Regression test for #1091 - @KronicDeth
  • #1120 - Add regression tests for #1116 that test that parameter and variables can be renamed. - @KronicDeth
  • #1124 - Update IntelliJ versions in build matrix to include 2018.1 and latest patch version of other versions. - @KronicDeth
  • #1126 - @KronicDeth
    • Add Elixir 1.6.X to build matrix
    • Update grammar and quoter to match native 1.6 behavior when SDK is >= 1.6.
    • New default SDK level is 1.7 to handle builds from master.
  • #1127 - Regression test for #1105 - @KronicDeth

Bug Fixes

  • #1056 - Certain .beam files in the OTP source are purposely invalid, so ignore them when trying to parse and don’t log the expected error. - @KronicDeth
  • #1060 - Log available bytes and total size when header is not FOR1. - @KronicDeth
  • #1071 - erl_abstract_code format Dbgi chunks can now be navigated similar to how elixir_erl format Dbgi chunks can be navigated. Instead of converting the Erlang Abstract Code back to Erlang, which would not be highlighted if intellij-erlang and requires the user to know Erlang, the Erlang Abstract Code is translated back to Elixir source, so you can use the Dbgi chunk view to translate Erlang to Elixir. - @KronicDeth
  • #1111 - Allow zero or more new lines after the struct name before the opening curly brace ({). - @KronicDeth
  • #1112 - @KronicDeth
    • In order to prevent Access is allowed from event dispatch thread only errors when creating read-only code editor in subtabs of the BEAM Chunks editor, only create those editors when their parent tab is selected.

      Affected tabs:

      • Code (Elixir & Erlang)
      • ExDc
      • Dbgi (Elixir & Erlang)
  • #1114 - Check for suffix instead of full match to detect predefined macros when annotating. Location strings have become more complex, such as including the file path for root level modules, so the old exact matching on the module name no longer works. - @KronicDeth
  • #1120 - Restore parameter and variable rename. It broke because the changes to make Find Usages work and have Go To Declaration default to Find Usage when there is only one target disabled the default selected element code that the VariableInplaceRenameHandler used. - @KronicDeth
  • #1121 - @KronicDeth
    • Allow module attribute declaration to resolve to itself, so that unused module attributes don’t say they can’t find the declaration.
    • Restore rename module attributes.
  • #1127 - Allow true and false to be keyword keys. - @KronicDeth

README Updates

Features

.beam Files

BEAM Chunks

Dbgi
Tab

The Dbgi tab appearance varies based on whether it was created with Erlang or Elixir, reflecting the fact that the Dbgi format is dependent on the backend that wrote it.

####### Elixir (:elixir_erl backend)

The Dbgi tab show the single value map entries: :file, :line, and :module.

Singletons

For the multi-value keys: :attributes, :compile_opts, and :definitions, there are individual tabs.

Multivalue Tabs

######## Attributes

The Attributes tab has the same format as the Attrs chunk.

Dbgi Attributes Table

######## Compile Options

The Compile Options tab is usually empty, much like the CInf options key for Erlang.

Table

######## Definitions

The Definitions tab is split between a tree of Module, Function/Arity and clauses.

Tree

Clicking on a clause will show only that clause, but clicking on a higher level in the tree will show all clauses in the function or the entire Module.



The AST stored in the definitions tab and the process of converting it back to code is not format preserves, so it will not look precisely like the source code as the AST has undergone some macro expansion before its put in the Dbgi chunk. As common idioms are understood, reversals will be add to the renderer.

####### Erlang (:erlang_abstract_code backend)

The Dbgi tab has Abstract Code and Compile Options tabs.

Dbgi Tabs

######## Abstract Code

The Abstract Code tab is split between a tree of Attributes, Functions, Function/Arity, and clauses.

Tree

Clicking on a clause will show only that clause, but clicking on a higher level in the tree will show all clauses in the function or the entire Module.

Clause


The abstract code stored in the :erlang_abstract_code backend format is the Erlang Abstract Format. Instead of converting the Erlang Abstract Format back to Erlang, which would require IntelliJ Erlang to highlight and annotate and for you to be used to reading Erlang, the Erlang Abstract Format is translated back to Elixir. Using the BEAM Chunk Dbgi viewer can be a way to convert compiled Erlang code to Elixir source automatically.

Find Usages and Show Usages

Find Usages is a feature of JetBrains IDEs. It is the dual of Go To Declaration. While Go To Declaration jumps from a usage to the declaration, Find Usages finds all usages that could jump to a declaration. When used on a usage, Find Usage first finds the declaration(s) and then finds usages of those declaration(s).

Find Usages will open all the found usages in the Find Tool Window (unless you have it configured to not open and jump direct if only one usage is found). If you want to jump to usages quickly, Show Usages, which opens a lookup dialog at the cursor and allows you to select a usage to jump to in the lookup dialog with the arrow keys may be more useful.

Function

  1. Place the cursor over the name of a function, such as hd in the definition def hd([h | t]]) do or hd in a usage hd(list).
  2. Active the Find Usages action with one of the following:
    • Alt+F7
    • Select Edit > Find > Find Usages from the menu.
  3. A Find Usages dialog will appear in the Find Tool Window.

If a function has multiple clauses, all clauses for the function will be resolved and used as targets.

Multiple Clauses.png

You can be sure that all clauses were correctly identified as targets because of the multiple entries in the top “Functions” target grouping.

Multiple Functions.png

If instead of bringing up the Find Tool Window, you’d like a lookup dialog above the cursor, you can use Show Usages.

  1. Place the cursor over the name of a function, such as hd in def hd([h | t]]) do
  2. Active the Show Usages action with one of the following:
    • Alt+Cmd+F7
    • Select Edit > Find > Show Usages from the menu.
  3. A Usages lookup will appear above the cursor.
  4. Select an element from the lookup to jump to that usage

Installation Instructions

2 Likes

Version 8.0.0

Donate

Thanks

  • For reporting NPE in the improved version of the getPresentation
  • For reporting that the safe cast for quote bound variables wasn’t so safe
  • For reporting the disassembler did not support all OTP 21 opcodes
  • For requesting spellchecking
  • For reporting that Phoenix’s use of quote inside a literal [head | tail] list code not be parsed to find the parent modular.
  • For reporting that the missing Erlang SDK message wasn’t clear clicking OK would take you through the setup and cancel would stop Elixir+Erlang SDK confirmation.
  • For reporting that variables use scope could not be calculated in EEx tags.
  • For reporting that @ was allowed in atoms, but not atom keyword keys.
  • For reporting that eachEbinPath did not restrict itself to directories and blow up on files.
  • For reporting that Module.aliasedName still contained assert even though it uses Normalized to protect from PsiErrors.
  • For reporting that Unaliased.down did not have a useful error message

Changelog

v8.0.0

Enhancements

  • #1175 - @KronicDeth
    • New and improved Run/Debug Configurations
      • Distillery Release CLIs for running console, foreground, etc
        Options for configuring each part of the command line
        • Path to Release CLI
        • Release CLI arguments (like a command console)
        • Settings that are normally hidden in environment variables
          • erl arguments (ERL_OPTS)
          • elixir -extra arguments (EXTRA_OPTS)
          • Code Loading Mode (CODE_LOADING_MODE)
          • Log Directory (RUNNER_LOG_DIR)
          • Replace OS Vars (REPLACE_OS_VARS)
          • sys.config file (SYS_CONFIG_PATH)
          • Release Config Directory (RELEASE_CONFIG_DIR)
          • Pipe directory (PIPE_DIR)
        • Use Pseudo-Terminal (PTY) to allow overriding console type when it can’t be inferred from the Release CLI arguments, such as using PTY for console because it uses an iex-like shell.
        • Working Directory
        • Environment Variables
      • iex console with proper PTY support (colors, tab completion, history)
        Options for configuring each part of the command line
        • iex arguments
        • erl arguments
        • Working Directory
        • Environment Variables
      • elixir with colors
        Options for configuring each part of the command line
        • elixir arguments
        • erl arguments
        • Working Directory
        • Environment Variables
      • mix tasks getting expanded options to match the new configurations
        • mix arguments, which used to be called “Program Arguments” (I figured out how to customize that name. :wink:)
        • elixir arguments
        • erl arguments
        • Working Directory
        • Environment Variables
      • iex -S mix
        Options for configuring each part of the command line
        • mix arguments
        • iex arguments
        • erl arguments
        • Working Directory
        • Environment Variables
      • mix test
        • mix test arguments, which used to be called “Program Arguments”
        • elixir arguments
        • erl arguments
        • Working Directory
        • Environment Variables
    • Debugger enhancements
      • All the above configurations can be debugged using the debugger. It is no longer restricted to only working with mix-based configurations.
      • Filter more common dependency modules from being interpreted by default.
        • credo
        • inch_ex
        • earmark
        • ex_doc
      • More ways to filter interpreted modules
        • Run Configurations now have an Interpreted Modules tab, next to Configuration, which by default imports the Application-wide settings, but allows
          • Disabling inherited filters
          • Adding configuration-specific filters
          • Remove configuration-specific filters
        • Allow interpreted modules to be uninterpreted when the debugger is running, using the “Interpreted Modules” tab.
      • Improved Variables pane by showing the Elixir name of variables instead of Erlang names
      • Evaluate can evaluate an Elixir expression in any stack frame.
  • #1192 - @KronicDeth
    • Add all OTP 21 opcodes to disassembler. Previous opcode set was
      frozen prior to OTP 21 release and missed some later additions.

      number name Added
      160 build_stacktrace Before OTP 21 release
      161 raw_raise Now
      162 get_hd Now
      163 get_tl Now
  • #1196 - @KronicDeth
    • Spell checking for identifiers, aliases, comments, and literals (charlists, strings, and sigils).
      • Dictionaries for common dependencies
        • Elixir
        • Ecto
  • #1203 - @KronicDeth
    • Elixir 1.7 debugger Variables and Evaluate compatibility
      • Elixir 1.7 names Erlang variables like _<elixirVariableName>@<counter> while Elixir 1.6 used V<elixirVariableName>@<counter>
      • Elixir 1.7 changed elixir_erl record and %Macro.Env{}, which changed how :elixir.quoted_to_erl needed to be called.
  • #1208 - Update 2018.2 to 2018.2.1 in build matrix. - @KronicDeth
  • #1210 - Regression test for #1141 - @KronicDeth
  • #1212 - Improve Cannot Create SDK error message (additions in bold): “You need to configure an Erlang SDK for Elixir SDK. Click OK to be take through the Erlang SDK configuration. Click Cancel to stop configuring this SDK AND the Erlang SDK.” - @KronicDeth
  • #1223 - Convert mix and mix test run configurations to new format. - @KronicDeth

Bug Fixes

  • #1188 - Show ... for module name when Dbgi has no module name as happens for instrumented modules from IEx.break/4. - @KronicDeth
  • #1189 - Don’t assume callDefinitionClause is non-null. - @KronicDeth
  • #1190 - Don’t assume parent of list access expression is QuotableKeywordPair- @KronicDeth
  • #1191 - Don’t assume parent of keywords is a list. - @KronicDeth
  • #1208 - TerminalExecutionConsole itself echos input in 2018.2 and 2018.2.1, which was introduced in https://github.com/JetBrains/intellij-community/commit/fd7bbd0cb7f3c2a5add8872e0e6c5172be5f074a#diff-5acc2eb2e78fe52d7458d4a48b0eac9f, but it was reverted in JetBrains/intellij-community@5f4465b, so this uses that version to maintain compatibility across supported versions. - @KronicDeth
  • #1210 - In Phoenix.Router.Helpers, a quote block appears as the head of [head | tail] list, so add support for search for enclosing macro call above |. - @KronicDeth
  • #1213 - Treat EEx tag the same as StabBody for use scope. - @KronicDeth
  • #1214 - Use ATOM for keyword keys instead of IDENTIFIER_TOKEN as ATOM allows for @, which is needed for correctness. - @KronicDeth
  • #1215 - In eachEbinPath, the ebin directories were found by iterating <SDK_HOME_PATH>/lib and then iterating grandchild of that, so that all paths matching <SDK_HOME_PATH>/lib/<APP>/ebin would be added, but for some installs from source, like SDK, there are non-OTP-app files in <SDK_HOME_PATH>/lib, so filter <SDK_HOME_PATH>/lib/<APP> to only directories. - @KronicDeth
  • #1216 - org.elixir.lang.psi.scope.Module.aliasedName(QualifiedAlias) was already converted to use org.elixir_lang.psi.operation.Normalized and org.elixir_lang.psi.infix.Normalized, which makes it work with errors in the PSI tree, so there’s no need protect with an assert and that assert would be wrong in times of errors handled by Normalized. - @KronicDeth
  • #1217 - org.elixir_lang.reference.module.UnaliasedName.down(PsiElement) only expects ElixirAccessExpression or QualifiableAlias, but for unexpected classes of elements, it was a simple Kotlin TODO(), which didn’t log anything useful for enhancements. Replace the TODO() with an org.elixir_lang.errorreport.Logger.error, so that the element’s class and content can be reported when this happens again. - @KronicDeth
  • #1164 - Use / in paths passed to Erlang, even on Windows - @notriddle

Incompatible Changes

  • #1175 - Drop support for IntelliJ IDEA before 2017.3 as they lack the TerminalExecutionConsole used to run iex in a PTY. - @KronicDeth

Installation Instructions

6 Likes

Version 8.1.0

Donate

Thanks

  • For consulting on the design of the new flat icons to match IntelliJ IDEA 2018.2’s design guidelines and showing me how to use Figma.
    • Narek Khachatryan (@nk8)
  • For reporting that Decimal.base10? could not resolve its enclosing modular
  • For reporting that completion of SDK files was broken in Small IDEs, which led to discovering the External Libraries were needed in Small IDEs for SDK indexing to occur. (Indexing of SDKs is automatic in IntelliJ IDEA.)
  • For explaining IntelliJ IDEA 2018.2’s design guidlines
    • Alina Mishna
  • For providing the SVG version of the Elixir icon
    • Alina Mishna
  • For providing the Elixir icon made by Alina Mishna

Changelog

v8.1.0

Enhancements

Bug Fixes

  • #1233 - Look above Enum.reduce for enclosing macro call. - @KronicDeth
  • #1234 - @KronicDeth
    • Add Facet SDK as External Library to re-enable indexing. When the External Library was removed in 4297287 in favor of a real SDK, completion for SDK .beam modules was lost because Small IDEs don’t index SDKs, but only External Libraries, so add Application-wide External Libraries for SDKs when they are created (and update, remove on edit or delete), which are then added as a Dependency for the facet’s module when the SDK is set for the Small IDE project.
      • Convert old modules with Elixir facets to also have External Library, so that users don’t need to remove and add the SDKs to get the External Library.
  • #1237 - @KronicDeth
    • Use #AEB9C0 for JetBrains Default/Light Gray. Use #87939A for JetBrains Darcula Gray. Colors based on IntelliJ’s color picker picking its own colors.

      Icon matching testing done under both themes in 2018.2.1. Weirdly, the colors are different in the SVGs in my intellij-community@master. Hopefully, this doesn’t mean the colors change again in 2018.3.

  • #1244 - @KronicDeth
    • Run createLibrary inside runWriteAction.
    • Remove test that leaks threads and so causes builds to fail.

Installation Instructions

2 Likes

Version 9.0.0

Donate

Thanks

  • For reporting that renaming variables didn’t work on bracket operations, which reminded me I still had the feature open to resolve bracket operation identifiers from 2016(!).
  • For reporting that they wanted Go To Source and Go To Decompiled to be separated
  • For let me know that some users were like me and liked being able to jump to decompiled code, which was the impetus for Go To Related support after Go To Declaration switched to preferring source.
    • Kimberly Milner (at ElixirConf 2018)
  • For reporting that I broke completion through imports when I did the Kotlin conversion back in v7.5.0 (released June 5th 2018) :man_facepalming:

v9.0.0

Enhancements

  • #1255 - @KronicDeth
    • Resolve calls through use AnAlias calls
      1. AnAlias will be resolved to its modular (module, implementation, or protocol)
      2. The __using__ macro in the modular is found
      3. The last call in __using__ is checked
      • If it is a quote block, check for call definitions recursively inside the block

      • If it is an apply/3 call

        1. Resolve the first argument as a modular
        2. Scan for each function in modular
        3. In each function Goto Step 3 above

        This handling is what specifically makes use MyAppWeb, :controller in Phoenix apps now work.

      • If it is a general call

        1. Resolve the call to its definition
        2. Goto Step 3 above
  • #1259 - @KronicDeth
    • Go To Related (Ctrl+Cmd+Up) can be used to Go To the decompiled Module or call definitions when on a source modular (defimpl, defmodule, or defprotocol) or callable (def, defp, defmacro, defmacrop). This somewhat restores the ability to go to both source and decompiled module and calls before 9.0.0, but now the source is preferred for Go To Declaration and the decompiled will only be available if there is no source and if you definitely want decompiled, you’ll need to use Go To Related.

Bug Fixes

  • #1245 - Specify that Kotlin Plugin is needed in CONTRIBUTING.md, so IntelliJ plays nice. - @sfat
  • #1246 - @KronicDeth
    • Resolve unqualified bracket operation identifiers (var in var[key]) to variables or 0-arity calls.
      • Fixes renames of variables not renaming usage of variables for Access lookups (i.e. var[key]).
  • #1248 - @KronicDeth
    • Go To Symbol will no longer show redundant entries
      • Call Definitions (name/arity) is no longer shown if the Call Definition Clause is also included. This isn’t a large loss because the /arity was not searchable and only part of the presentation.
      • If there is a decompiled and a source version of a symbol, only the source version will be shown.
        • The source Implementation will be shown and not the decompiled Module with the same fully-qualified name (<protocol>.<for>).
      • Items will be deduped if they point to the same element, such as function clauses with default arguments because when presented they look the same even if internally one is representing /1 and /2, for example.
  • #1249 - Ensure that Go To Declaration for qualified calls such as Module.function(...) where Module is an alias does not return the decompiled version of Module when the source is available. - @KronicDeth
  • #1256 - @KronicDeth
    • Fix completion not working for unqualified functions from imports.
      • When I switched to using ?.let I accidentally hid the if from running when there was no ENTRANCE_CALL_DEFINITION_CLAUSE, so the correct form is add if there is no entrance or if there is a non-equivalent entrance.
      • I just straight up forgot an ! on a contains check. I moved to computeIfAbsent, so it is more obvious what the intent is.

Incompatible Changs

  • #1248 Go To Symbol and Go To Declaration will no longer suggest decompiled modules or functions if source modules or functions of the same name or module/name/arity exists. - @KronicDeth

README updates

Features

Go To Related

Go To Related is like Go To Declaration, but more general, for anything that is related to an element, but not its declaration.

In IntelliJ Elixir, Go To Related can be used to go to the decompiled version of a modular (defimpl, defprotocol, or defmodule) or a callable (def, defp, defmacro, defmacrop) definition.

Decompiled Module

  1. Place the cursor on the name of the modular, such as EExTest.Accounts in defmodule EExTest.Accounts do
  2. Go To Related
    • Navigate > Related Symbol
    • Ctrl+Cmd+Up
  3. Select a “Decompiled BEAM” target from the “Choose Target” context menu
  4. You will be taken to the decompiled module
    Decompiled.png

Decompiled Call Definition

  1. Place the cursor on the name of the call, such as get_user! in def get_user!(id)
  2. Go To Related
    • Navigate > Related Symbol
    • Ctrl+Cmd+Up
  3. Select a “Decompiled BEAM” target from the “Choose Target” context menu
  4. You will be taken to the decompiled module
    Decompiled.png

Installation Instructions

3 Likes

Version 10.0.0

Donate

Thanks

  • For reporting the new for a runWriteAction when adding new JDKs in Small IDES
  • For reporting that a modular element could become invalid during completion and not have a valid containing file.
  • For reporting that :crypto wasn’t in the default module filters even though its NIFs can’t be interpreted.
  • For reporting that the redefinition of defmodule in distillery broke the GoTo Symbol contributor.
  • For reporting “Test framework quit unexpectedly” being reported instead of showing the compilation errors during tests, which turned out to be a deprecation in OpenAPI and a change in ExUnit output in Elixir 1.7 I missed.
  • For reporting that Elixir was bigger than Erlang, or at least the icons in IntelliJ 2018.3 EAP :trollface:.
  • For reporting poor error message when removing module filters
  • For reporting that I can’t make the fact that there is no use call a cache dependency
  • For reporting that completion with nested modules was broken
  • For reporting that alias __MODULE__, as: Mod did not work for resolving references through Mod.

Changelog

v10.0.0

Enhancements

  • #1272 - @KronicDeth
    • Go To Symbol and completion will only resolve in project source unless non-project sources are turned on.
      • deps are properly marked as Libraries and no longer count as being in the project scope for the Go To tools.
      • In umbrella projects, when in_umbrella is used, the Project Module for each apps/#{APP_NAME} will be marked a dependency,
      • Library and Modules are properly connected as dependencies, so that only declared dependencies will resolve, lessening false completions and declarations when different OTP app share common Module or function names.
    • deps and the _build/#{MIX_ENV}/lib/#{DEP_NAME} will be marked as Excluded, so that Libraries appear in External Libraries at the bottom of the Project Pane.
  • #1275 - @KronicDeth
    • Go To Class action (Cmd+O) to go to modules separately from all functions as would happen with Go To Symbols (Alt+Cmd+O).
      • New ModuleName index keeps track of only the names of modulars:

        • defmodule
        • defimpl
        • defprotocol

        It is used to power gotoClassContributor for Go To Class action.

  • #1280 - Handle commit and override for Mix.Dep. - @KronicDeth
  • #1283 - Add .eex to .ex and .exs for accepted file extensions used to hyperlink files in stacktraces. - @KronicDeth
  • #1285 - @KronicDeth
    • Resolve unaliased name when using alias __MODULE__, as: Mod
    • Resolve usage of Mod in alias __MODULE__, as Mod
      1. Mod
      2. __MODULE__ in alias __MODULE__
      3. defmodule MyModule that is enclosing __MODULE__.
    • Disable ProcessCanceledException for runIde gradle task, to allow for easier manual testing of completion and Go To actions during development.
    • Completion of functions in current module when using Mod. after alias __MODULE__, as: Mod.
    • Show more context for alias calls in presentations, like “Choose Declaration” pop up for Go To Declaration.
      • Show resolved __MODULE__ name (alias MyModule) when using alias __MODULE__.
      • Show full alias MyModule, as: Mod when listing Mod in alias __MODULE__, as Mod.
  • #1293 - @KronicDeth
    • Exclude common directories when importing projects
      • cover for test coverage
      • doc for ex_doc
      • logs for log files
      • assets/node_modules/phoenix for phoenix
      • assets/node_modules/phoenix_html for phoenix_html
    • Setup Libraries and Module dependencies when importing projects from Mix.
  • #1299 - Regression test for #1270. - @KronicDeth
  • #1313 - @KronicDeth
    • Update gradle wrapper to 3.5 to allow for environment variable overrides
    • Setup datetime based pre-release versioning to ensure that correct version of pre-release plugin is used when testing Install Plugin From Disk.
  • #1318 - @KronicDeth

Bug Fixes

  • #1277 - Don’t include null useCall as __MODULE__ dependency. - @KronicDeth
  • #1279 - @KronicDeth
    • Wrap LibraryTable#removeLibrary in write action.
    • Wrap Library#modifiableModule#commit in write action.
  • #1282 - Check if Mix.Dep has already been seen to prevent recursive loops. - @KronicDeth
  • #1287 - @KronicDeth
    • More closely match ExUnit.CliFormatter output in Test Runner.
      • Don’t inspect ExUnit failure reason as ##teamcity message.
      • Add captured logs to failure
      • Colorize test failures - including diff colorization
    • .formatter.exs input globs would not match file paths because it was default that needed lib on top and not version-dependent paths used in resources/exunit.
  • #1291 - @KronicDeth
    • Ignore branch and hex options when finding path of Mix.Dep
    • Map Elixir 1.7 :excluded and :skipped (added in elixir-lang/elixir#7245) to testIgnored teamcity message, thereby restoring ignored test counts and markers from Elixir 1.6.
  • #1293 - @KronicDeth
    • When the entire deps directory has updated sync the children deps directories and then sync all modules instead of syncing them after each dep.
    • For an unknown reason, when sync occurs at initComponent time in DepsWatcher or mix.Watcher, the child directories of the project basedDir aren’t shown in the Project Pane until a change is applied in Project Structure.
    • Use invokeAndWait instead of invokeLater to ensure order of syncs.
  • #1299 - When finding a defmodule, check that it is an ancestor of the entrance of the ResolveState, so that nested sibling modules are not scanned for potential call definition clauses, but only the outer module of the entrance. - @KronicDeth
  • #1300 - Improve error message for org.elixir_lang.debugger.settings.stepping.module_filter.editor.table.Model.getValueAt, so we can detect if there is an off-by-1 error. - @KronicDeth
  • #1304 - Remove @2x and @3x SVG icons that render wrong size in 2018.3 EAP. - @KronicDeth
  • #1305 - @KronicDeth
    • Fix unused variables in TeamCityExUnitFormatting
      • reason was completely unused.
      • details should have been used.
  • #1306 - @KronicDeth
    • flushBufferBeforeTerminating was deprecated and in newer IntelliJ the call to processStatuses does not occur unless flushBufferOnProcessTermination is also overridden.
    • Treat == Compilation error in STDOUT as ERROR for ExUnit reporter
    • Convert (CompileError) of a test file to test failure. The “Test framework quit unexpectedly” is converted to a failed run with a single test with the compilation error as the failure message.
  • #1308 - @KronicDeth
    • Don’t treat redefinition of defmodule macro as module definition (as occurs in @bitwalker’s distillery’s Mix.Tasks.Release.Init.MixMock
      • Bump AllName VERSION to re-index and drop bad call definition head from #1301.
  • #1310 - Don’t log compilation errors as test failures unless a test has started. Test name being called mix test does not work, so log those compilation errors as normal build messages instead. - @KronicDeth
  • #1311 - Don’t interpret :crypto by default: :crypto includes NIFs that can’t be reloaded and so kills the debugger. - @KronicDeth
  • #1312 - Protect from null containingFile for modular names during completion. - @KronicDeth
  • #1313 - Wrap syncPublisher(JDK_TABLE_TOPIC) in invokeLater runWriteAction. - @KronicDeth

Incompatible Changes

  • #1272 - @KronicDeth
    • Dependencies are now counted as external to the project, so the Go To tools, like Go To Symbol will no longer include matches for both project sources and dependencies sources together, instead they will follow the more JetBrains native behavior
      • Project sources will be shown by default
      • If there are no project matches, dependencies will be shown instead.
      • If you want to include dependency (non-project) matches, you can check the box or hit Cmd+O.
  • #1293 - Modules and Libraries won’t be automatically setup when a project or module is opened, but instead only when apps or deps directories or subdirectories change. - @KronicDeth

README Updates

Installation

Canary releases

Builds on master will produce pre-release builds of format NEXT_VERSION-pre+YYYYMMDDHHMMSS.

Inside IDE using JetBrains repository

You will need to add the canary repository once to your IDE:

  1. Preferences
  2. Plugins
  3. Browse Repositories
  4. Manage Repositories
  5. Click +
  6. Enter the IntelliJ Elixir canary URL: https://plugins.jetbrains.com/plugins/list?channel=canary&pluginId=7522
  7. Click OK
  8. Click OK to close the Custom Plugin Repositories dialog.

With the canary repository setup:

  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 latest pre-release zip.
In IDE
  1. Preferences
  2. Plugins
  3. Install plugin from disk…
  4. Select the downloaded zip.
  5. Apply
  6. Restart the IDE.

Installation Instructions

2 Likes

Version 10.0.1

Donate

Thanks

  • For reporting that real-world code may produce 10 names for one element.

Changelog

v10.0.1

Bug Fixes

  • #1322 - @KronicDeth
    • Eliminate freezes when calculating Module and Library dependencies during project import and dependency updates.
      • Run library syncing in tasks: When importing projects, run sync as a modal task while when VirtualFileSystem events occur, run sync as background tasks. Either style of task is cancellable and importantly, it allows to show what is happening during the syncing. This converts the unresponsive UI beachball on macOS during import to an updating progress bar.
      • Calculate dep sets iteratively with a work queue instead of recursively to limit the calculation of dep set for a root to 1 time. Then use normal transitive walk to get complete dep set for module. Vastly speeds up project import.
      • Cache dep set on package PsiFile to allow faster refreshes when indirect dependencies don’t change.
  • #1323 - @KronicDeth
    • Log nameSet when it reaches suspect size (10) to allow triaging if it is a real bug or just something with a lot of valid names.
    • Fix inverted condition around when to warn and when to error and use readAheadLength.

Installation Instructions

1 Like

Version v10.1.0

Donate

Thanks

  • For reporting that packgePsiFileToDepSet needed to be wrapped in a read action
  • For requesting ExUnit Test New File template
  • For reporting that defmodule one-liner in IEx autocomplete test was being treated as a call definition head in the GoToSymbolContributor.
  • For opening a PR to fix deadlinks in the README that led me to auditing all the links in the README and fixing image links that were stale.

Changelog

v10.1.0

Enhancements

  • #1330 - @KronicDeth
    • Add IntelliJ Elixir Help to Help menu that opens link in browser using plugin version to link to README.md on GitHub.

      screen shot 2018-11-02 at 12 06 52 pm

      The link will work on released versions that have a tag.

  • #1334 - @KronicDeth
    • Allow creating ExUnit.Case modules from template. Template contains
      • use ExUnit.Case
      • alias of the source module
      • @moduletag :capture_log
      • doctest
      • test that checks that the source module exists.
    • Convert CreateElixirModuleAction to Kotlin.
    • Drop “Elixir” prefix from templates name in Elixir File dialog since you already know you’re creating an Elixir File.

Bug Fixes

  • #1327 - Fix deadlinks to Run Configurations, which broke when section was renamed Run/Debug Configurations and auto-anchor changed name. - @KronicDeth
  • #1328 - Fix image links in README. - @KronicDeth
  • #1331 - Ensure defmodule one-liner isn’t mistaken for call definition head in Go To Symbol. - @KronicDeth

README Updates

Fixed image layout and stale links.

Installation Instructions

1 Like

Version 10.2.0

Donate

Thanks

Changelog

v10.2.0

Enhancements

  • #1353 - @KronicDeth
    • Improve support for umbrella projects in Small IDEs like Rubymine by creating a separate module for each mix.exs when opening a directory (DirectoryConfigurator). This matches the pre-existing support in Rich IDEs (IntelliJ Community & Ultimate Edition) when using Import From External Model and Quick Import when opening a directory.
    • Ignore assets directory when looking for mix.exs files for Import From External Model, Quick Import and Directory Configurator.
  • #1355 - @KronicDeth
    • Update Build Matrix
      • Add 2018.3.
        • Update gradlew to 5.0.
        • Update org.jetbrains.intellij to 0.3.12.
        • Update org.jetbrains.kotlin.kvm to 1.3.10.
          • Update Kotlin apiVerision to 1.3.
        • Update de.undercouch.download to 3.4.3.
        • Don’t configure Kotlin in projects that don’t use it.
      • Remove 2017.3 to keep version count at 3.

Bug Fixes

  • #1355 - Prevent ConcurrentModificationExceptions when updating gradle by using allprojects less. - @KronicDeth
  • #1359 - @KronicDeth
    • Remove unused variables in Elixir debugger server.
    • Protect from AssertionError when VirtualFileCache is disposed.
  • #1360 - Protect from AssertionError when VirtualFilePointerContainer is disposed. - @KronicDeth
  • #1364 - Use :path for deps for paths external to project. Unfortunately, even though they show up in the Project Structure, only ebin directories are shown as it is restricted to those marked as CLASSES and the :path lib is a SOURCES. - @KronicDeth
  • #1367 - Ignore :tag when finding path to dep. - @KronicDeth
  • #1368 - No longer use the forked version of TerminalExecutionConsole as 2018.3's version doesn’t have the text echoing behavior that was being bypassed before. - @KronicDeth
  • #1372 - Ignore :ref when finding path to dep. - @KronicDeth

Installation Instructions

2 Likes

Version 10.3.0

Donate

Thanks

  • For reporting that they expect types to show up.
  • For reporting performance issues
  • For including thread dumps when reporting performance issues

Changelog

v10.3.0

Enhancements

Bug Fixes

  • #1408 - @KronicDeth
    • Cache all computed Elixir levels at the file, module, project, and SDK levels. The computed Elixir level is used to determine how to emulate the various grammar changes made for the different Elixir versions. This bug was potentially introduced as earlier asv7.0.0 (2017-12-15) and as late as v7.5.0 (2018-06-03) as that’s the history for LevelPropertyPusher.java and has affected all later versions. If you ever experienced the 6.X series as faster than the 7.X series and later, this bug may be why and you should upgrade/reinstall immediately.

README Changes

Features

.beam Files

BEAM Chunks

Dbgi
Tab

####### Elixir (:elixir_erl backend)
######## Type Specifications

The Type Specifications tab is split between a tree of the Module, Module Attribute, and type specifications.

Tree.png

Clicking on a type specification will show only that type specification, but clicking on a higher in the tree will show all type specifications for the same module attribute or the entire Module.



Optional Callback.png
Optional Callbacks.png


Type.png

Installation Instructions

4 Likes