intellij-elixir

Elixir plugin for JetBrain's IntelliJ Platform (including Rubymine)

OTHER License

Stars
1.8K
Committers
55

Bot releases are hidden (Show)

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025235555

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025233115

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025230421

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025192802

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025025704

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025024310

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025023243

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025022131

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025020337

Published by KronicDeth almost 6 years ago

intellij-elixir - https://github.com/KronicDeth/intellij-elixir/releases/tag/v10.0.0-pre+20181025005945

Published by KronicDeth almost 6 years ago

intellij-elixir - v9.0.0

Published by KronicDeth about 6 years ago

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) 🤦‍♂️

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
    Choose Target.png
  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
    Choose Target.png
  4. You will be taken to the decompiled module
    Decompiled.png
intellij-elixir - v8.1.0

Published by KronicDeth about 6 years ago

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.
intellij-elixir - v8.0.0

Published by KronicDeth about 6 years ago

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. 😉)
        • 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

README Updates

Features

Debugger

Steps

  1. Define a run/debug configuration
  2. Create breakpoints in the *.ex files
  3. Launch a debugging session
  4. During the debugger session, step through the breakpoints, examine suspended program, explore frames, and evaluate code when suspended.

Starting the Debugger Session

It takes awhile, once the debugged process is started to configure the debugger in BEAM. To ensure that breakpoints are setup before allow the debugged code to run, the debugger blocks until setup is complete.

  1. The debugged process will wait for the debugger to attach
    Waiting for debugger to attach.png
  2. Breakpoints will be set
  3. The debugger will mark modules to be interpreted
    1. The code paths will be scanned for .beam files
      • Code paths from the Elixir SDK will be skipped
        Skipped.png
      • .beam files will be interpreted unless they match the Module Filter Pattern
        Completed.png
  4. The debugger attaches (so it can receive breakpoint events) and allows the debugged process to continue.
    Attached.png

Examining Suspended Program

Variables

Binary.png

Binaries show each byte at the byte's offset.

Bitstring.png

Bitstrings show each byte with any partial byte annotated with its bitwidth.

Boolean.png

Boolean variables are rendered as their value.

Charlist.png

Charlists show the integer values because they're treated as lists

Functions.png

Functions don't have literal representation, so the inspect form starting with #Fun<...> is shown

Lists.png

Lists render differently based on whether the list is improper or not. Improper lists show the head and tail while proper lists show their element by offset.

Maps.png

Maps render differently based on the key type. If the map uses all atom keys, the key will equal the value in the nested children while non-atom keys are shown as entries at a specific offset with the key and value. This is done, so that complex keys that have subterms can be expanded or collapsed, which is not possible for the simpler atom rendering.

Numbers.png

Floats and integers are rendered as literals.

Pid.png

Pids are broken up into their hidden node, id, and serial`.

String.png

Strings show their literal value and unicode is fully supported.

Tuple.png

Tuples show their elements at their offsets.

Rebound.png

While Elixir allows rebinding variable names, Erlang does not, so when viewed in the Variables pane, rebound variables will have an @VERSION after their name indicating which rebinding of a the variable is.

Evaluate

When stopped at a breakpoint, you can use the Evaluate button (it looks like a simple pocket calculator) to open an editor to type code to be executed in the current stack frame.

Evaluate.png

The evaluator supports the full syntax.

Result.png

The result of evaluating the code with be shown as the value of result below the entered "Expression".

Exception.png

Typo.png

Errors in the code will report back as a result tuple with an :EXIT tag. This reflects that the error has crashed the process that was evaluating the code. Thankfully, due to how how the interpreter is written, this does not lose the current stack frame and stepping or other evaluation can continue.

Run/Debug Configurations

Distillery Release CLI Elixir Mix Icon with tapered neck to make a retort as used in distilleries

Distillery's mix release produces a CLI for running the release.

  1. Build the release: mix release
    ==> Release successfully built!
        You can run it in one of the following ways:
          Interactive: _build/ENV/rel/NAME/bin/NAME console
          Foreground: _build/ENV/rel/NAME/bin/NAME foreground
          Daemon: _build/ENV/rel/NAME/bin/NAME start
    
  2. Run > Edit Configurations...
    Edit Run Configurations
  3. Click +
  4. Select "Distillery Release CLI"
    Add New Distillery Release CLI
  5. Fill in the "Release CLI Path" with the full path to the _build/ENV/rel/NAME/bin/NAME path produed by mix release above.
  6. Fill in the "Release CLI arguments".
    • console runs a shell with the release loaded similar to iex -S mix.
    • foreground to runs the release without a shell, like mix or mix run.
      The available commands are controlled by your release config rel/config.exs that Distillery uses.
  7. (Optionally) fill in "erl arguments" with arguments to erl before it runs elixir.
    This is the same as the ERL_OPTS environment variable supported by Distillery.
  8. (Optionally) fill in "elixir -extra arguments" with arguments to pass to elixir before it run the release.
    This is the same as the EXTRA_OPTS environment variable supported by Distillery.
  9. (Optionally) change the Code Loading Mode
    This is the same as the CODE_LOADING_MODE environment variable supported by Distillery.
    • Use Default - use whatever is configured in rel/config.exs. Don't set CODE_LOADING_MODE environment variable.
    • embedded - load all code immediately on boot. Set CODE_LOADING_MODE=embedded.
    • interactive - load code on-demand as it is needed/referenced. Set CODE_LOADING_MODE=interactive.
  10. (Optionally) set the "Log Directory"
    This is the same as the RUNNER_LOG_DIR environment variable supported by Distillery.
  11. (Optionally) change "Replace OS Vars"
    This is the same as the REPLACE_OS_VARS environment variable supported by Distillery.
    • Use Default - use whatever is configured in rel/config.exs. Don't set REPLACE_OS_VARS environment variable.
    • false - don't replace "${A_VAR_NAME}" in the generated configuration with A_VAR environment variable at runtime. Set REPLACE_OS_VARS=false.
    • true - replace "${A_VAR_NAME}" in the generated configuration with A_VAR environment variable at runtime. Set REPLACE_OS_VARS=true.
  12. (Optionally) set "sys.config File"
    This is the same the SYS_CONFIG_PATH environment variable supported by Distillery.
  13. (Optionally) set "Release Config Directory".
    This is the same as the RELEASE_CONFIG_DIR environment variable supported by Distillery.
  14. (Optionally) set "Pipe directory".
    This is the same as the PIPE_DIR environment variable supported by Distillery.
  15. (Optionally) set "Use Pseudo-terminal (PTY).
    If checked use PTY for interactive shells. Automatically on when "Release CLI Arguments" starts with one of the known interactive commands (attach, console, console_boot, console_clean, or remote_console).
  16. Fill in the "Working directory.
    • Type the absolute path to the directory.
    • Select the path using directory picker by clicking the ... button
  17. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  18. Click "OK" to save the Run Configuration and close the dialog
Running
  1. Click the Run Arrow in the Toolbar to run the _build/ENV/rel/NAME/bin/NAME
  2. The Run pane will open
    • If the either "Use Pseduo-terminal (PTY)" is checked of the "Release CLI Arguments" are known to need a PTY, an interactive shell will appear in the Run pane where you can enter iex commands.
    • Otherwise, the output of running the command will be shown.
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. Add the :debugger application to your release
    1. Open rel/config.exs
    2. In the release NAME block, in the set :applications block add :debugger:
      --- a/rel/config.exs
      +++ b/rel/config.exs
      @@ -41,6 +41,8 @@ end
       release :intellij_elixir do
         set version: current_version(:intellij_elixir)
         set applications: [
      +    # needed for IntelliJ Elixir debugger
      +    :debugger,
           :runtime_tools
         ]
       end
      
  3. For how to use the debugger, including how to set breakpoints see the Debugger section.
  4. Click the Debug bug in the Toolbar to debug the mix tests

Elixir Elixir Drop

Although it is exceedingly rare, as most Elixir projects use mix, it is supported to run/debug elixir directly, such as when doing elixir script.exs.

  1. Run > Edit Configuations...
    Edit Run Configurations
  2. Click +
  3. Select "Elixir"
    Add New Elixir
  4. Fill in the "elixir arguments".
  5. (Optionally) fill in "erl arguments" with arguments to erl before it runs elixir.
  6. Fill in the "Working directory"
  • Type the absolute path to the directory.
  • Select the path using directory picker by clicking the ... button
  1. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  2. Click "OK" to save the Run Configuration and close the dialog

With the Run Configuration defined, you can either Run or Debug elixir

Running
  1. Click the Run arrow in the Toolbar to run elixir.
    Run
  2. The Run pane will open, showing the results of elixir.
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. For how to use the debugger, including how to set breakpoints see the Debugger section.
  3. Click the Debug bug in the Toolbar to debug elixir

IEx (Interactive Elixir)

iex run configurations allow you to run iex with IntelliJ Elixir attached. It is most useful when debugging, but it also allows you save customizations in the configuration when it is more complicated than just iex.

  1. Run > Edit Configurations...
    Edit Run Configurations
  2. Click +
  3. Select "IEx"
    Elixir Drop inside round-bottom flask
  4. (Optionally) fill in "iex arguments" with arguments to iex.
  5. (Optionally) full in "erl arguments" with arguments to erl before it runs iex.
  6. Fill in the "Working directory"
  • Type the absolute path to the directory.
  • Select the path using directory picker by clicking the ... button
  1. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  2. Click "OK" to save the Run Configuration and close the dialog

With the Run Configuration defined, you can either Run or Debug the iex configuration.

Running
  1. Click the Run arrow in the Toolbar to run iex
    Run
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. For how to use the debugger, including how to set breakpoints see the Debugger section.
  3. Click the Debug bug in the Toolbar to debug iex.

Mix Tasks Elixir Drop mixed in a round-bottom flask

Much like rake tasks in Rubymine, this plugin can run mix tasks.

  1. Run > Edit Configurations...
    Edit Run Configurations
  2. Click +
  3. Select "Elixir Mix"
    Add New Elixir Mix
  4. Fill in the "mix arguments" starting with the name of the mix task followed by any arguments to that task.
  5. (Optionally) fill in "elixir arguments" with arguments to elixir before it runs mix.
  6. (Optionally) fill in "erl arguments" with arguments to erl before it runs elixir.
  7. Fill in the "Working directory"
  • Type the absolute path to the directory.
  • Select the path using directory picker by clicking the ... button
  1. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  2. Click "OK" to save the Run Configuration and close the dialog

With the Run Configuration defined, you can either Run or Debug the Mix Task

Running
  1. Click the Run arrow in the Toolbar to run the mix task
    Run
  2. The Run pane will open, showing the results of the mix task.
    • If there is an error with a FILE:LINE stack stack_frame, it will be a clickable link that will take you to that location
      Error link
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. For how to use the debugger, including how to set breakpoints see the Debugger section.
  3. Click the Debug bug in the Toolbar to debug the mix task

IEx Mix

If you want to run iex in the context of the project, you need to run iex -S mix, but if you don't want to have to worry about forgetting whether it's -s or -S or if it is mix -S iex or iex -S mix, you can use an IEx Mix configuration.

  1. Run > Edit Configurations...
    Edit Run Configurations
  2. Click +
  3. Select "IEx Mix"
    The Mix Icon with ">" to indicate the IEX prompt
  4. (Optionally) fill in "mix arguments", such as phx.server if you want to launch Phoenix inside of iex.
  5. (Optionally) fill in "iex arguments" with arguments to iex before -S mix.
  6. (Optionally) full in "erl arguments" with arguments to erl before it runs iex.
  7. Fill in the "Working directory"
  • Type the absolute path to the directory.
  • Select the path using directory picker by clicking the ... button
  1. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  2. Click "OK" to save the Run Configuration and close the dialog

Wih the Run Configuration defined, you can either Run or Debug iex -S mix

Running
  1. Click the Run Arrow in the Toolbar to run iex -S mix
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. For how to use the debugger, including how to set breakpoints see the Debugger section.
  3. Click the Debug bug in the Toolbar to debug iex -S mix.

mix test

The mix test task gets a special type of Run Configuration, Elixir Mix ExUnit. Using this Run Configuration type instead, of the basic Elixir Mix Run Configuration will cause the IDE to attach a special formatter to mix test, so that you get the standard graphical tree of Test Results

The Run pane will show Test Results. If there is a compilation error before or during mix test, it will be shown as a test failure. If the compilation failure is in a _test.exs file can it can be inferred from the stacktrace, the compilation error will show up as a test failure in that specific module.

doctest names are rearranged to emphasize the function being tested: "test doc at MODULE.FUNCTION/ARITY (COUNT)" becomes "MODULE.FUNCTION/ARITY doc (COUNT)". If MODULE is the same as the test case without the Test suffix, then MODULE is stripped too and the test name becomes only FUNCTION/ARITY doc (COUNT).

Creating mix test Run Configurations Manually
  1. Run > Edit Configurations...
    Edit Run Configurations
  2. Click +
  3. Select "Elixir Mix ExUnit"
    Add New Elixir Mix ExUnit
  4. Fill in the "mix test arguments" with the argument(s) to pass to mix test. Normally, this will be a directory like test, relative to the "Working directory"
  5. (Optionally) fill in "elixir arguments" with the arguments to elixir before it runs mix test.
  6. (Optionally) fill in "erl arguments"with the arguments toerlbefore it runselixir`.
  7. Fill in the "Working directory"
  • Type the absolute path to the directory.
  • Select the path using directory picker by clicking the ... button
  1. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  2. Click "OK" to save the Run Configuration and close the dialog

With the Run Configuration defined you can either Run or Debug the mix tests

Running
  1. Click the Run arrow in the Toolbar to run the mix test task
  2. The Run pane will open showing the Test Results
    Test Results
Debugging
  1. (Optionally) before debugging, customize the modules that will be interpreted.
    1. Run > Edit Configurations...
    2. Click the "Interpreted Modules" tab next to default "Configuration" tab.
    3. Enable/Disable "Inherit Application Module Filters". Will change the Module Filters show in the below "Do not interpreter modules matching patterns" list.
    4. Uncheck any inherited module filters that you would rather be interpreted and therefore debuggable
    5. Click + to add module filters that are specific to this configuration. This can be useful if you know interpreting a specific module in your project's dependencies or project leads to too much slowdown when debugging or causes the debugger to hang/crash.
    6. Click - to remove configuration-specific module filters added with +. Inherited module filters cannot be removed with -, they can only be disabled by unchecking.
  2. For how to use the debugger, including how to set breakpoints see the Debugger section.
  3. Click the Debug bug in the Toolbar to debug the mix tests

While you can create Elixir Mix ExUnit run configurations manually using the Run > Edit Configurations... menu, it is probably more convenient to use the context menu.

Creating mix test Run Configurations from context

The context menu must know that the the directory, file, or line you are right-clicking is a test. It does this by checking if the current directory or an ancestor is marked as a Test Sources Root.

  1. In the Project pane, ensure your OTP application's test directory is marked as a Test Sources Root
  2. Check if the test directory is green. If it is, it is likely a Test Sources Root. This color may differ in different themes, so to be sure you can check the context menu
  3. Right-click the test directory.
  4. Hover over "Mark Directory As >"
    * If "Unmark as Test Sources Root" is shown, then the directory is already configured correctly, and create from context will work.
    Mark Directory As > Unmark as Test Sources Root
    * If "Test Sources Root" is shown, then the directory need to be configured by clicking that entry
    Mark Directory As > Test Sources Root
Creating/Running mix test Run Configurations from directory
  1. Right-click the directory in the Project pane
  2. Click "Run Mix ExUnit", which will both create the Run Configuration and Run it.
    Run Mix ExUnit
  • If you want to only create the Run Configuration, select "Create Mix ExUnit" instead

Alternatively, you can use keyboard shortcuts

  1. Select the directory in the Project pane.
  2. Ctrl+Shift+R will create the Run Configuration and Run it.
Creating/Running mix test Run Configurations from file
  1. Right-click the file in the Project pane
  2. Click "Run Mix ExUnit", which will both create the Run Configuration and Run it.
  • If you want to only create the Run Configuration, select "Create Mix ExUnit" instead

Alternatively, you can use keyboard shortcuts

  1. Select the directory in the Project pane.
  2. Ctrl+Shift+R will create the Run Configuration and Run it.

Finally, you can use the editor tabs

  1. Right-click the editor tab for the test file you want to run
    Run Mix ExUnit
  2. Click "Run Mix ExUnit", which will both create the Run Configuration and Run it.
  • If you want to only create the Run Configuration, select "Create Mix ExUnit" instead
Creating/Running mix test Run Configurations from line

If you want to be able to run a single test, you can create a Run Configuration for a line in that test

  1. Right-click a line in the test file
    Run Mix ExUnit
  2. Click "Run Mix ExUnit", which will both create the Run Configuration and Run it.
  • If you want to only create the Run Configuration, select "Create Mix ExUnit" instead

Alternatively, you can use keyboard shortcuts

  1. Place the cursor on the line you want to test
  2. Ctrl+Shift+R will create the Run Configuration and Run it.
intellij-elixir - v7.5.0

Published by KronicDeth over 6 years ago

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.

Clause
Function
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
Function
Module

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
intellij-elixir - v7.4.0

Published by KronicDeth over 6 years ago

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

.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

Build, Execution, Deployment > Compiler > Elixir Compiler

  • 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.

Errors and Warnings

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.

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).

intellij-elixir - v7.3.0

Published by KronicDeth over 6 years ago

Thanks

Changelog

v7.3.0

Enhancements

  • #988 - @KronicDeth
    • Update build matrix
      • Update IntelliJ IDEA version 2017.3 to 2017.3.2
      • Update Elixir version 1.5.2 to 1.5.3
  • #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.
      screen shot 2018-02-01 at 6 38 07 pm
      The BEAM Chunks editor is subdivided into further tabs, one for each chunk in the .beam file.
      screen shot 2018-02-01 at 6 45 23 pm
      The tabs are listed in the order that the chunks occur in the .beam file.
      • The Atom chunk holds LATIN-1 atoms while AtU8 holds UTF8 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 UTF8 atoms.

        The Atom/AtU8 tab shows a table with the columns

        Column Description Source
        Index Which is 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

        screen shot 2018-02-01 at 7 01 43 pm

        Index 1 is always the module name for the .beam file. Since .beam is originally an Erlang format, for Elixir modules, you'll see the full atom name of with the Elixir. prefix instead of the Alias name used in Elixir source.

      • The Attr chunk holds the module attributes, but only those that are persisted.

        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

        screen shot 2018-02-02 at 2 34 22 pm

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

      • 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.

        The CInf tab shows a table with the columns

        Column Description Source
        Key Option name Raw
        Value Inspected value Raw

        screen shot 2018-02-02 at 3 19 50 pm

      • The Code chunk contains the byte code for the module. It is encoded in BEAM Compact Term Encoding, which differs from the binary format produced by term_to_binary.

        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.

        screen shot 2018-02-02 at 9 35 59 pm

        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.

      • 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.

        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

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

        screen shot 2018-02-02 at 5 26 04 pm

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

        screen shot 2018-02-02 at 5 27 29 pm

        The Attributes tab has the same format as the Attrs chunk

        screen shot 2018-02-02 at 6 47 49 pm

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

        screen shot 2018-02-02 at 6 48 34 pm

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

        screen shot 2018-02-02 at 6 50 14 pm

        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.

        screen shot 2018-02-02 at 6 53 17 pm

        screen shot 2018-02-02 at 8 47 05 pm

        screen shot 2018-02-02 at 8 47 20 pm

        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.

      • 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.

        The ExDc binary format is from term_to_binary, so it can be reversed with binary_to_term. 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 :callback_docs, :docs, :moduledoc, and :type_docs keys.

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

        screen shot 2018-02-02 at 8 58 38 pm

        screen shot 2018-02-02 at 9 07 03 pm

        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
      • 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.

        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

        screen shot 2018-02-01 at 8 21 13 pm

        You'll notice the first entry starts with MACRO-. This is because the BEAM, 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.

      • 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.

        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

        screen shot 2018-02-01 at 8 07 15 pm

        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.

      • The LitT chunk contains literals loaded as arguments in Code chunk. 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.

        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()

        screen shot 2018-02-01 at 9 25 07 pm

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

        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

        screen shot 2018-02-01 at 9 27 49 pm

        You'll notice the first entry -__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.

      • The StrT chunk contains a single contiguous pool of all Erlang strings (that is, Elixir charlists) used in the Code chunk. 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.

        screen shot 2018-02-01 at 7 56 15 pm

        The StrT is contiguous with no separation of strings. 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.

  • #1021 - @KronicDeth
    • Support for https://github.com/elixir-lang/elixir/commit/23c7542d95683a497a7b93071b9ccbbeb9e45d2f

      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
  • #999 - @ronanboiteau
    • Jetbrains' Gogland is now named GoLand, updated README accordingly
    • In donors list, Garrett Hart had his GitHub URL (@https://github.com/thirdshift) shown instead of his GitHub username (@thirdshift)

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

.beam 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

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
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

AtU8 Table

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.

Code Chunk Read-Only Editor

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

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.

Clause
Function
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
Function selected in 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

ImpT Table

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()

LitT Table

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.

####### 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

Tab

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

Line References 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

intellij-elixir - v7.2.1

Published by KronicDeth almost 7 years ago

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"
intellij-elixir - v7.2.0

Published by KronicDeth almost 7 years ago

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
intellij-elixir - v7.1.0

Published by KronicDeth almost 7 years ago

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
    File > New Project > From Existing Sources > Import project from external model > 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

    Add SDK

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

    Cannot Create SDK

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

    Select Home Directory for Erlang SDK for Elixir SDK

    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.

    Select Home Directory for Elixir SDK

  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.

SDK

  • 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

    Internal Erlang SDK

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

intellij-elixir - v7.0.0

Published by KronicDeth almost 7 years ago

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

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.

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 ▶ 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

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