Bot releases are hidden (Show)
Published by KronicDeth almost 7 years ago
{EOL}|.
-> {ANY}
in Elixir.flex
EOL
to WHITE_SPACE
token, as GrammarKit is smarter about reparsing when only WHITE_SPACE
changes in size.
fn
do
->
after
, catch
, else
, and rescue
)(
Remove !stabOperationPrefix
before expression
, since stabOperationPrefix
itself starts with expression
and instead put a negative look-ahead, !(infixComma | stabInfixOperator)
after expression
. This now works when it previously didn't because COMMA
was added to expressionRecoverUntil
, which means both COMMA
and STAB_OPERATOR
are now in both not eaten by expression
's error recovery.
This drops Fn1 through Fn8 to ~176ms instead of the previous time of the last optimization of 13 seconds for Fn8. It started at 26 seconds and now it appears that the time no longer grows with the number of fn
. It also eliminates the pause when hitting entering inside the fn
nesting.
Published by KronicDeth almost 7 years ago
HEAD-<SHA1>
format used for brew install --head elixir
directory was unparsable and caused a null
Version
and a NPE when sorting to determine the default directory.
handlebars
as an open-source implementation of a similar language.
.eex
as the final extension will be treated as EEx. To determine the Template Data Language, the .eex
extension will be stripped and any remaining extension will be looked up to get the File Type and its associated Language. For example, *.txt.eex
will be EEx with Plain Text (.txt
) as the Data Template Language. Likewise, *.html.eex
will be EEx with HTML as the Data Template Language. There's no need to register *.txt.eex
or *.html.eex
or any other *.DATA_TEMPLATE_LANGUAGE_EXTENSION.eex
pattern explicitly: the nested extension will be looked up using the normal extension setup.2016.2
is dropped because it's over a year old. It is still supported, but not actively tested.LocT
chunk for private macros and functions and the derived names of anonymous functions. - @KronicDeth
mix hex.local --force
-> mix local.hex --force
in README
- @bryanhuntesl-lowpriv
HEAD-<SHA1>
as 0.0.<SHA1>
for sorting versions from homebrew homepath. It will almost always be last unless there is an unknown version, which uses 0.0.0
.0.0.0
(UKNOWN_VERSION
).eexTag
to resolve fn
parametersfn
in eex
tags don't error by looking at eex
element parent.eexTag
and eex
to determine if variable.Any file with .eex
as the final extension will be treated as Embedded Elixir (EEx) templates. To determine the Template Data Language, the .eex
extension will be stripped and any remaining extension will be looked up to get the File Type and its associated Language. For example, *.txt.eex
will be EEx with Plain Text (.txt
) as the Data Template Language. Likewise, *.html.eex
will be EEx with HTML as the Data Template Language. There's no need to register *.txt.eex
or *.html.eex
or any other *.DATA_TEMPLATE_LANGUAGE_EXTENSION.eex
pattern explicitly: the nested extension will be looked up using the normal extension setup.
If you need more file-by-file configuration of the Template Data Language than can be achieved with a file extension/pattern, IntelliJ IDEA (Community or Ultimate Edition) has support for setting the Template Data Language on a specific path.
It turns out that in the .beam
binary format there are no macros. This makes sense since the BEAM format was made for Erlang, which does not have macros, and only has functions. Elixir marks its macros in the compiled .beam
by prefixing them with MACRO-
.
There are 2 chunks in the BEAM format for function references: ExpT
, which is for exports (because in Erlang module they are from -export
), which are the public functions and macros; and LocT
, which is for locals (anything not exported in Erlang), which are private functions and macros.
BEAM Chunk | Atom Prefix | Macro |
---|---|---|
ExpT |
MACRO- |
defmacro |
ExpT |
N/A | def |
LocT |
MACRO- |
defmacrop |
LocT |
N/A | defp |
defp
with /
in nameMuch like there are no macros in BEAM, there are no anonymous functions either. Any anonymous function (using fn
in Elixir or fun
in Erlang) ends up being a named function in the LocT
chunk. Anonymous functions names start with -
, then the parent function's name, a /
and a unique number for that scope.
As an example, Kernel
has
defp unquote(:"-MACRO-binding/2-fun-0-")(p0, p1, p2, p3) do
# body not decompiled
end
which is generated from the for
in
defmacro binding(context \\ nil) do
in_match? = Macro.Env.in_match?(__CALLER__)
for {v, c} <- __CALLER__.vars, c == context do
{v, wrap_binding(in_match?, {v, [generated: true], c})}
end
end
[Removal of EEx work-around]
Published by KronicDeth almost 7 years ago
MockProjectEx
and my test checks probably broke the the plugin for all non-IDEA IDEs 🤦♂️ .
project instanceOf MockProjectEx
because not all IDEs, such as Rider, ship with MockProjectEx
; instead, do a Class#getCanonicalName()
check. - @KronicDeth
Published by KronicDeth almost 7 years ago
not in
credo
edge detection errors were due to UTF-8 charset not being set.
GeneralCommandLine#withCharset
existed to set the charset to UTF-8 always.
2017.2
2016.1.4
1.5.2
1.3.4
20.1
18.3
not in
grammar added by elixir-lang/elixir#5620 shipped with Elixir 1.5.@
and unary operators as separate operations from non-numeric operands to port elixir-lang/elixir@9747e58db773c716c01c210642ec1d91475e0c83 that shipped with Elixir 1.5.0. This only kicks in if the Elixir SDK is version >= 1.5.0 or not set. With an earlier SDK, you'll get the earlier behavior.+
/-
handling more robust to support one(two, - three)
used in Elixir 1.5 enum.ex
. - @KronicDeth
withCharSet(Charsets.UTF_8)
on all GeneralCommandLines
to prevent encoding errors on Windows. - @KronicDeth
Published by KronicDeth almost 7 years ago
Credo#stripEdge
end
wasn't being decompiled with Unquoted
in wx-1.8.2/ebin/gl.beam
$code_change
wasn't being decompiled with Unquoted
in tools-2.11/ebin/fprof.beam
BeamFileImpl
needed StubbedSpine getStubbedSpine()
in IntelliJ IDEA 2017.3 EAP/Public Preview
StubbedSpine getStubbedSpine()
could be copied from ClsFileImpl
, but then fixing it, so that getStubbedSpine()
had a default implementation on the interface, so I didn't need to use reflection to support > 2017.3 and earlier versions. ❤️
Credo
annotator violated "Write access is allowed from event dispatch thread only" when Type. putDefaultErlangSdk
was triggered for upgraders that didn't upgrade their SDK manually or with a mix
Run Configuration before the Credo annotator started running.
com.intellij.execution.process.ColoredProcessHandler
for ANSI escape code colors. ❤️
mix
Run and Debug output - @KronicDeth
-
in addition to #
in Unquoted
MacroNameArity
decompiler.-
in decompiled module names.nil
as unquote(:nil)
in the decompiler. - @KronicDeth
Application#runWriteAction
MUST be run from EventDispatch thread. This is true when run from a Run Configuration runner, but when the Credo annotator runs runWriteAction
, it's not in an EventDispatch thread, so followed IntelliJ Platform SDK DevGuide - General Threading Rules and wrapped the runWriteAction
in Application#invokeAndWait
. - @KronicDeth
sdkModificator::commitChanges
in invokeAndWait
runWriteAction
in MixRunningStateUtil#updateRoots
. - @KronicDeth
Generalize what needs to be double quoted for Unquoted
decompiler
Normal identifiers and prefix operators then fall through to the Default
decompiler.
end
to Unquoted
decompiler bare atoms. - @KronicDeth
assert
s in Credo
external annotator with extended log messages that record the unexpected line. - @KronicDeth
Published by KronicDeth about 7 years ago
mix test
runner for Small IDEs
credo
external annotator
mix credo
will be run on any modified file.
mix credo
will be turned into a warning annotation (yellow highlight) of the line or line and column credo identified.mix credo PATH:LINE(:COLUMN)
explanation will be shown. Links in the tooltip are clickable and allow you to jump to the specific line or line and column of the failure.org.elixir_lang.annonator
-> org.elixir_lang.annotator
. - @KronicDeth
MixRunningStateUtil#setElixir
to support calling erl
directly in IntelliJ IDEA added a check that sdk type was the Elixir SDK Type, but there was no else
clauses to handle that there IS an SDK, but its NOT Elixir, which is the common case on all Small IDEs (like Rubymine). To fill this gap, if the SDK is not Elixir and a Small IDE is detected, then the SDK Home from Preferences > Other Settings > Elixir External Tools > Elixir SDK > Path will be used to get the absolute path to the elixir
(or elixir.bat
executable and set it in the GeneralCommandLine
.**
for bold.mix test
runner for Small IDEs
credo
external annotator
mix credo
will be run on any modified file.
mix credo
will be turned into a warning annotation (yellow highlight) of the line or line and column credo identified.mix credo PATH:LINE(:COLUMN)
explanation will be shown. Links in the tooltip are clickable and allow you to jump to the specific line or line and column of the failure.org.elixir_lang.annonator
-> org.elixir_lang.annotator
. - @KronicDeth
MixRunningStateUtil#setElixir
to support calling erl
directly in IntelliJ IDEA added a check that sdk type was the Elixir SDK Type, but there was no else
clauses to handle that there IS an SDK, but its NOT Elixir, which is the common case on all Small IDEs (like Rubymine). To fill this gap, if the SDK is not Elixir and a Small IDE is detected, then the SDK Home from Preferences > Other Settings > Elixir External Tools > Elixir SDK > Path will be used to get the absolute path to the elixir
(or elixir.bat
executable and set it in the GeneralCommandLine
.**
for bold.This is a plugin that adds support for Elixir to JetBrains IDEs.
The plugin works both in the rich IDEs that allow alternative language SDK selection and small IDEs that are language specific. The rich IDEs work best for IntelliJ Elixir because only in the rich IDEs can have an Elixir SDK set as the Project SDK. In all small IDEs, the native language SDK is always there, which makes anything that uses the SDK, such as running elixir
, erl
, or mix
more complicated both internally and externally in the configuration you have to setup.
The plugin is free to use in all JetBrains IDEs. The Cost column in the below table is what JetBrains charges for the IDE itself. IntelliJ Elixir is maintained by @KronicDeth who does not get any of the subscription money. If you want to support the plugin itself, make a donation.
IDE | Rich/Small | Languages | Cost | Trial | License | Source |
---|---|---|---|---|---|---|
IntelliJ IDEA Community Edition | Rich | Java | Free | N/A | Apache 2.0 | JetBrains/intellij-community |
IntelliJ IDEA Ultimate Edition | Rich | Java | Subscription | 30-days | Commercial | N/A |
AppCode | Small | Objective-C | Subscription | 30-days | Commercial | N/A |
CLion | Small | C/C++ | Subscription | 30-days | Commercial | N/A |
DataGrip | Small | SQL | Subscription | 30-days | Commercial | N/A |
Gogland | Small | Go | Free | N/A | Early Access Preview | N/A |
PHPStorm | Small | PHP | Subscription | 30-days | Commercial | N/A |
PyCharm Community Edition | Small | Python | Free | N/A | Apache 2.0 | JetBrains/intellij-community subdirectory |
PyCharm Professional Edition | Small | Python | Subscription | N/A | Commercial | N/A |
Rider | Small | .NET | Subcription | N/A | Commercial | N/A |
RubyMine | Small | Ruby | Subscription | 30-days (90-day for whole team) | Commercial | N/A |
WebStorm | Small | JavaScript | Subscription | 30-days | Commercial | N/A |
Once you have your IDE of choice installed, you can install this plugin
Feature | Rich | Small | Alternative |
---|---|---|---|
Project | Yes | No | 1. Open directory2. Elixir SDK Path in External Elixir Tools |
Project Structure | Automatic | Manual | |
Project Settings | Yes | No | |
Module Settings | Yes | No | |
New Elixir File | Yes | Yes | |
Syntax Highlighting and Semantic Annotation | Yes | Yes | |
Grammar Parsing | Yes | Yes | |
Inspections | Yes | Yes | |
Quick Fixes | Yes | Yes | |
Code Folding | Yes | Yes | |
Commenter | Yes | Yes | |
Debugger | Yes | Yes | |
Delimiters | Yes | Yes | |
Building/Compiling | Yes | No | Build/compile as part mix run configurations only |
Live Templates | Yes | Yes | |
Run Configurations | Yes | Yes | |
Completion | Yes | Yes | |
Decompilation | Yes | Yes | |
Go To Declaration | Yes | Yes | |
Formatting | Yes | Yes | |
Go To Symbol | Yes | Yes | |
Go To Test | Yes | Yes | |
Go To Test Subject | Yes | Yes | |
Find Usage | Yes | Yes | |
Refactor | Yes | Yes | |
SDK | Yes | No | Elixir SDK Path in External Elixir Tools |
Structure | Yes | Yes |
If you've already created a mix
project, you can load it as an Elixir project into the plugin.
mix deps.get
when importing the project
mix hex.local --force
and mix deps.get
will be run.mix.bat
, such asC:\Program Files (x86)\Elixir\bin\mix.bat
should be used instead of the mix
file without the extension.mix.exs
files will be selected as "Mix projects to import". To import just the main project and not its dependencies, click Unselect All.mix.exs
. (It will likely be the first checkbox at the top.)bin
directory containing elixir
, elixirc
, iex
, and mix
. (On Windows it is theelixir.bat
, elixirc.bat
, iex.bat
, and mix.bat
.)If you've already created a (non-mix
) project, you can load it as an Elixir project into the plugin.
mix.exs
. Uncheck any project roots that you don't want added.bin
directory containing elixir
, elixirc
, iex
, and mix
.If you want to create a basic (non-mix
) Elixir project with a lib
directory, perform the following steps.
/usr/local/Cellar/elixir
)/nix/store
)/usr/local/lib/elixir
/nix/store
)C:\Program Files\Elixir
)C:\Program Files (x86)\Elixir
)bin
directory containing elixir
, elixirc
, iex
, and mix
. If the bin
, lib,
or src
directory is incorrectly selected, it will be corrected to the parent directory.Project name
to the name your want for the projectProject location
if the directory does not match what you wantMore Settings
to change the Module name
, Content root
, Module file location
, and/or Project format
. The defaults derived from the Project name
and Project location
should work for most projects.In addition to the built-in syntax highlighting and annotations above, various mix
tasks will be run to gather annotations from Elixir status analysis tools.
If credo
is not installed as a project dependency, nothing will happen, but if it is installed, mix credo PATH
will be called on any files after updates have quieted. Any credo
check failures will show up as warning annotations
Individual check failures will show the explanation (from mix credo PATH:LINE(:COLUMN)
) if you hover over the annotation
You can hover over the explanation and click the embedded links to jump to the line (and column) where the failure occurred.
NOTE: These instructions only apply to Rich IDEs, for a Small IDE use Elixir SDK Path
In a Rich IDE, like IntelliJ IDEA, only the path to mix
is configured as an external tool. This mix
path is only used when creating new projects, so when opening a pre-existing project with Import project from external model, this doesn't even need to be set.
NOTE: To setup the SDK in a Rich IDE use Import project from external model or SDK
In a Small IDE, like Rubymine, the Project SDK is always a Ruby SDK, so to support a pseudo-Elixir-SDK in a Small IDE, the Elixir SDK Path can be set.
...
to select the directoryThe pattern for the Elixir SDK Path varies based on the OS and package manager you used to install Elixir
OS | Package Manager | Elixir SDK Path |
---|---|---|
OSX/macOS | Homebrew | /usr/local/Cellar/elixir/VERSION |
OSX/macOS/Linux | Nix | /nix/store/HASH-elixir-VERSION |
Windows 32-bit | Erlang Solutions | C:\Program Files\Elixir |
Windows 64-bit | Erlang Solutions | C:\Program Files (x86)\Elixir |
Linux | Default | /usr/local/lib/elixir |
Published by KronicDeth about 7 years ago
lib/certifi/ebin/certifi_cacerts.beam
end
wasn't an allowed keyword key
:
- @merqlove
Elixir SDK will now have an Internal Erlang SDK, which can be supplied one of two ways:
intellij-erlang
is installed: its Erlang SDK can be usedEither Internal Erlang SDK's home path is used to locate the erl
(or erl.exe
on Windows) executable and it is used to run Elixir; bypassing the elixir
(or elixir.bat
on Windows) script. Instead, as was done in #789, the ebin directories for the Elixir SDK are passed as -pa
options to erl
.
The Elixir SDK's configuration becomes more important: the classpath entries are now the list of ebin
directories to pass to erl
using -pa
instead of scanning for ebins in the homepath, so additional code paths can be added to the Classpaths configuration and they will be used when running mix
and mix test
. The classpaths will be initialized to the ebin directories under the home path.
intellij-erlang
is installed, intellij-elixir
's Erlang version suggestion is still used because intellij-elixir
favors the latest version while intellij-erlang
favors the first found, which is usually the oldest version.HOMEPATH/lib
is replaced with HOMEPATH/lib/APP/ebin
.HOMEPATH/lib
is replaced with HOMEPATH/lib/APP/lib
IF it exists (so only for source SDKs)http://elixir-lang.org/docs/stable/elixir/
will be replaced with https://hexdoc.pm/APP/VERSION
for every APP
in HOMEPATH/lib
.ebin
paths in the Internal Erlang SDK will be copied to the Elixir SDK, so that they are indexed, which makes the Internal Erlang SDK modules show up in Symbol search..
.
.beams
from the Internal Erlang SDK) will be used for completing atoms as soon the atom is parseable: either after the first letter :
or inside the quotes when making a quoted atom..*
and look for regex matches to this derived potential atom name..
will now work at the end of file. Previously, completions only worked in the middle of a file, where the .
could parse the next work an existing call, now if that parse doesn't work and the only thing after is a new line, it will still complete.A-Z
as sigil modifiers in addition to a-z
to support U
ungreedy modifier that replaced r
ungreedy modifier for regexes. - @KronicDeth
Elixir.
- @merqlove
:
) andElixir.
and plain Aliases for debugger blacklist. - @merqlove
END
to allowed keywordKey
tokens - @KronicDeth
.beam
files if macro
is defmacro
. "Macros" header was being printed when there was only functions because the check when there was no lastMacroNameArity
didn't care what the current macroNameArity.macro
was..erl
file has -compile([compressed])
, it will be compiled normally, and then gzipped, so that the .beam
will not contain the BEAM magic number FOR1
, but instead the gzip magic number 0x1f
0x8b
. So, to properly handle normal and compressed, the decompiler needs to look-ahead 2-bytes and check the gzip magic number. If the gzip magic number is detected, the InputStream will be passed through GZIPInputStream
before the the normal decoding process.#
and they would be interpreted as comments. Accepting those names in Unquoted
wouldn't escape the #
from being treated as a comment, so in addition to unquote
ing the name, surround it in double quotes. - @KronicDeth
AdditionalDataConfigurable
only copied the the Internal Erlang SDK Code Paths when the selection in the ComboBox
was changed, which meant if the there was only one Erlang SDK or the user never changed the selection, the Code Paths were never copied. To get the Code Paths copied when the Elixir SDK is first created and setupSdkPaths
interface method is called
SdkAdditionalaData
ebin
directories for its Class Paths, then the Class Paths is expanded to Code Paths.mix test
runs, which meant that the Elixir SDK would not upgrade correctly from 6.1.1 to 6.2.0 without the user deleting the Elixir SDK and recreating it. - @KronicDeth
.beam
files, such as those in the Elixir SDK, the Elixir SDK's Internal Erlang SDK, and in your project's build
directory will be decompiled to equivalent def
and defmacro
calls. The bodies will not be decompiled, only the call definition head and placeholder parameters. These decompiled call definition heads are enough to allow Go To Declaration, the Structure pane, and Completion to work with the decompiled .beam
files.
.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.
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.
Functions and macros can have names that aren't valid identifier names, so the decompiler has special handlers to detect these invalid identifiers and escape them to make decompiled code that is parsable as valid Elixir.
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).
With the Elixir SDK setup with an Internal Erlang SDK, you can see the Elixir SDK name and the home path, but unlike other SDKs, there's a dropdown for changing the Internal Erlang SDK.
You'll notice there is a mix of two different parent paths in Class Paths:
Those from the Elixir SDK Home Directory, which are the lib/APP/ebin
for the APP
s that ships with Elixir: eex
, elixir
, ex_unit
, iex
, logger
, and mix
.
Those from the Internal Erlang SDK Home Directory, which are the lib/APP-VERSION/ebin
for the APP
s that ship with OTP.
The Class Paths are combined from the two SDKs because OpenAPI doesn't allow to dynamically delegate to the Internal Erlang SDK when checking for Class Paths to scan for completion and running. If you change the Internal Erlang SDK in the dropdown, the Class Paths will be updated to remove the old Internal Erlang SDK Class Paths and add the new Internal Erlang SDK Class Paths.
These Class Paths are not just for code completion and search anymore, all paths listed as passed with -pa
flag to erl
or erl.exe
when running mix
, so that you can mix different versions of OTP applications shipped with different version of OTP, so you can take advantage of the independently updatable OTP apps in the release notes for OTP.
The default SDK for new projects can we set from the Configure menu on Welcome Screen
Hover over "Project Defaults" to see its submenu
Select "Project Structure" from the submenu
IntelliJ will start out with no default SDK. To make the default SDK, an Elixir SDK, Click New
Select "Elixir SDK"
You'll get "Cannot Create SDK" message because there are no Erlang SDKs for the Elixir SDK to use as an Internal Erlang SDK. Click OK to create the Erlang SDK first.
You'll be actually prompted to Select Home Directory for the Erlang SDK
If you have the intellij-erlang
plugin installed, you'll create an Erlang SDK from it.
NOTE: Erlang SDK's default Home Directory favors the oldest version of Erlang installed. You probably want the newest version. To manually select the Home Directory, it is the directory that contains the bin
, erts-VERSION
, and lib
subdirectories. For Homebrew, the path looks like /usr/local/Cellar/erlang/VERSION/lib/erlang
. It is important to select the lib/erlang
directory and not the VERSION
directory for intellij-erlang
to accept it as a Home Directory.
If you don't have intellij-erlang
installed, then you'll create and Erlang for Elixir SDK, which is supplied by this plugin.
With an Erlang SDK available to use as the Internal Erlang SDK, you'll be prompted for the Home Directory for the Elixir SDK.
Published by KronicDeth about 7 years ago
do ... end
block
intellij-erlang
a soft-dependency, it broke the debugger's icons that referenced ErlangIcons
, but it turns out all the icon constants were aliases to AllIcons.Debugger
constants, so by using the AllIcons.Debugger
icons directly, the dependency on ErlangIcons
can be removed without the need to copy the image files into intellij-elixir
. - @KronicDeth
do ... end
template is inserted, it did not have a previous child whose attributes to use, so it used the default, which left the cursor unindented. To get the cursor indented by default, When the ElementType
is DO
, apply the stabChildrenIndent
rules: indent normal and determine whether to indent relative to direct parent using code style setting. - @KronicDeth
VirtualFile
path in Beam read errors - @KronicDeth
Published by KronicDeth about 7 years ago
org.elixir_lang.ElixirModules
has static methods for copying resources out to a temporary directory and adding the -r <temporary_path>
for one or more resource files to a new or existing ParametersList. These are now shared for the Mix ExUnit and Debugger code paths.ElixirXDebugProcess
MixExUnitRunningState
MIxRunningState
.beam
files were removed in 58e7d4a, which was before v5.1.0, but not all users had problems with using the debugger. #739 persisted (as reported by @erikreedstrom) when 6.0.0 was released; I retried reproducing on a clean VM and I got it. I'm not sure why it worked for some people in prior releases since the .beam
don't exist that were being copied, but now the debugger uses the same system of copying .ex
files and requiring them with -r
instead of copying .beam
and using -pa
to add the ebin
directory. Fix was verified local under macOS and in Windows VM that reproduced #739. - @KronicDeth
Published by KronicDeth about 7 years ago
SmartHashSet
null
errors
6.0.0
and reporting pre-release bugs
Kernel.SpecialForms
colors were wrong after merging the Kernel
and Callable
annotator
do
block body)
AtU8
instead of Atom
chunk
UnmatchedAtUnqualifiedBracketOperation
could not be checked to be a parameter
""
being sent when ExUnit run configuration had no parametersElixirMatchedUnqualifiedNoParenthesesCallImpl
parameter name set could not be determined
ModuleAttribute.typeTypeParameterNameSet
should assume Aliases are incorrectly capitalized parameter names
defmodule
"'"
was being parsed as a heredoc promoter instead of a single quote inside double quotes
rebar3_hex_config.beam
ElixirVariable
to trigger isVariable
bug
mix deps.get
can hang prompting for if the user wants to mix local.hex --force
bin
is selected as the SDK home instead of the parent of bin
and lib
def
s
do
block lines are indenteddo
blocks end
as the last argument of a no parentheses call unindents to the start of the callelse
.
and
in
or
when
=
<-
and \\
!=
, ==
, =~
, !==
, and ===
<
, <=
, >=
, and >
+
and -
*
and /
+
, -
, !
, ^
, and ~~~
->
::
|
||
and |||
&&
and &&&
<~
, |>
, ~>
, <<<
, <<~
, <|>
, <~>
, >>>
, and ~>>
..
^^^
++
, --
, ..
, <>
=>
,
@
not
fn
after
catch
rescue
key:
&
,
{ }
<< >>
[ ]
( )
/
in &NAME/ARITY
and &QUALIFIER.NAME/ARITY
when
wraps when its right operand wraps, so that guards start with when
on a newline when they are too long.|>
at start of indented line for pipelinesend
with start of call instead of start of line for do
blocks in pipelines::
when
when guards span multiple lines++
, --
, ..
, <>
) operands, so that <>
binaries are multiple lines align their starts instead of using continuation indent and being indented relative to first operand.|
operands, so that alternates in types and specs are aligned instead of continuation indented relative to the first operand.spec
(that is above operands to |
align with the operands|>
is the start of a successive line.<< >>
) elements when wrapped2017.1.1
-> 2017.1.5
2016.3.5
-> 2016.3.7
1.4.2
-> 1.4.5
TeamCityExUnitFormatting.put_event
%__MODULE__{}
for state in clauses to prevent state update errors:suite_finished
and :suite_started
events, so that only events added to the interface will be unknown and IO.warn
can be used tell anyone spotting the new event to file an issue.1
for lines or 3
for heredocs), pin
*_PROMOTER
token, so it's more obvious the pattern is that the promoter is pinned. - @KronicDeth
/nix/store
on Mac if homebrew path does not exist - @KronicDeth
DecompilerTest
lengthorg.jetbrains.intellij
0.2.15
- @KronicDeth
Elixir.LDAPEx.ELDAPv3.beam
as regression test for #703 - @KronicDeth
quote
s in list in macros in Structure View - @KronicDeth
Callable#multiResolve
, CallDefinitionClause#multiResolve
, Module#multiResolve
, and ModuleAttribute#multiResolve
, which are all the extant references, can be cached and invalidated correctly. - @KronicDeth
ParameterLists
to support Path Variables in program parameters. - @KronicDeth
bin
, lib,
or src
to parent directory.ElixirSdkType
.Include specific message for each decompilation error reason.
Regression test for #772
AtU8
UTF8 atoms chunk decompilation to support OTP 20 compiled .beam
files.
Regression test for Elixir 1.5.0 announcement to ensure that unicode from AtU8
chunk can be read from beam file produced by following Elixir code:
```elixir
defmodule AtU8Test do
def こんにちは世界 do
:こんにちは世界
saudação = "Bom dia!"
saudação
end
end
```
IdeaVIM
in the gradle sandbox because it got annoying having to reinstall it when the sandbox reset. - @KronicDeth
MixRunningStateUtil
and fix warnings. - @KronicDeth
::
the same as :
in key:
after when
in type specifications as it's a realistic error..
to #
when referring to constants in javadocs@param
without descriptionsatNonNumericOperation
reference is non-null
before resolvingelse
.Type
leftOperand
is null
before using it.highlightTypesAndTypeParameterUsages(When...)
highlightTypesAndSpecificationTypeParameterDeclarations
equals
to eliminate need for null
check<...>
)Collections.EMPTY_SET
to Collections.emptySet()
to prevent uncheck cast warnings.when
rightOperand
is non-null
before scanning it for parameter names.mix test
, it will be turned into a test failure.
stderr
that end in (elixir) lib/kernel/parallel_require.ex:
.mix test
or the inferred module name of test file.
test/.*_test.exs:\d+: \(module\)
test/
and .exs
will be stripped from the file and it will be camelized to produce the derived test module name of the failuremix test
is used"test doc at MODULE.FUNCTION/ARITY (COUNT)"
becomes "MODULE.FUNCTION/ARITY doc (COUNT)"
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)
##teamCity
testSuiteStarted
messages automatically nest, so switched to using nodeId
and parentNodeId
system, so that nesting is explicit. This will allow multiple parallel tests to show up in GUI too.Elixir.
prefix is stripped from test case names.Callable
and Kernel
annotatorsPsiElementVisitor
instead of PsiRecursiveElementVisitor
, so that macros in defmodule
block don't get double annotated.TextAttributeKey
, erase as before, but then merge the TextAttributeKey
's TextAttributes
and apply as single setEnforcedTextAttributes
. For some reason, this fixes the inconsistency of whether PREDEFINED_CALL
or MACRO_CALL
is applied first.resolved
s, make those that need PREDEFINED_CALL
to win.TeamCityExUnitFormatting.new
should return struct only because none of the formatters expects an :ok
tuple.TeamCityExUnitFormatting.put_Event
catchall parameters.FileReferenceFilter
.exs
to pattern for stacktrace linking.stringLine
and charListLine
.unquote
, include argument in name of call definition clausequote
for enclosingMacroCall
, which allows going to Phoenix.Template.compile's quote's defp
Module.create
as `ModularOr
interface to unify Matched
and Unmatched
Or
s.Or
operation for nested child calls for Structure view.unquote(ARG1)
name for getName
and indexingElementDescription
for ElixirVariable
UnqualifiedParenthesesCall
s as call
instead of variable
.mix local.hex --force
before mix deps.get
during project import to prevent prompt for hex update when local hex is earlier than that required by mix
.MixProjectRootStep
ElixirDecimalFloat
as error in types.
jps-*/out
directories.isParameter
for AtUnqualifiedBracketOperation
.AtUnqualifiedBracketOperation
the same as UnqualifiedBracketOperation
for isVariable
.buildFileStub
- @KronicDeth
do
as a function name, but it's a keyword in Elixir, so wrap it as unquote(:do)
. The SpecialForm
decompiler already did this unquote(...)
wrapping, but do
is a keyword and not a special form, so rename the decompiler to Unquoted
. - @KronicDeth
Move {3} inside |
for SIGIL
PROMOTER
and TERMINATOR
:
SIGIL_HEREDOC_PROMOTER = ({SIGIL_DOUBLE_QUOTES_PROMOTER}|> {SIGIL_SINGLE_QUOTES_PROMOTER}){3} SIGIL_HEREDOC_TERMINATOR = ({SIGIL_DOUBLE_QUOTES_TERMINATOR}|> {SIGIL_SINGLE_QUOTES_TERMINATOR}){3}
The |
is inside group that is then {3}
'd, so it allows either '
or "
in groups of three. This is only applies to the sigils. It's correct for normal string and charlist heredocs:
CHAR_LIST_HEREDOC_PROMOTER = {CHAR_LIST_PROMOTER}{3} CHAR_LIST_HEREDOC_TERMINATOR = {CHAR_LIST_TERMINATOR}{3} STRING_HEREDOC_PROMOTER = {STRING_PROMOTER}{3} STRING_HEREDOC_TERMINATOR = {STRING_TERMINATOR}{3} QUOTE_HEREDOC_PROMOTER = {CHAR_LIST_HEREDOC_PROMOTER} | {STRING_HEREDOC_PROMOTER} QUOTE_HEREDOC_TERMINATOR = {CHAR_LIST_HEREDOC_TERMINATOR} | {STRING_HEREDOC_TERMINATOR}
JPS
type
for jps-*
projects because their deps become incompatible with other projects.break
s to case
statement in processDeclarations(Match, ...)
that caused the logic of whether to check left, right, or both operand based on the whether the treeWalkUp came from always fell through to the RIGHT
case, so it was only, always checking the right operand of the match and never the left operand. - @KronicDeth
processDeclarationsInPreviousSibling
when lastParent
is ElixirFile
- @KronicDeth
Alias
as miscapitalized type parameter. @KronicDeth
when
in type specifications as it is a common occurrence when typing a specification above a pre-existing call definition clause. - @KronicDeth
THashSet
instead of the more specific SmartHashSet
because THashSet
allows null
keys, which are expected for the canonicalNameSet
. - @KronicDeth
List
for enclosing modular macro.ElixirNoParenthesesManyStrictNoParenthesesExpression
for enclosing modular macro.ParametersList
to properly parse quote program parameters.Quoter
into test
directory, so it and its dependency on JUnit
is only used for test compilation and runtime and not the shipped runtime.Quoter
warnings and format.ElixirSdkType
.CallDefinitionClause
InsertHandler
always assumed there was a character after the insert location, but when inserting at the very end of the file, there isn't, which caused an IndexOutOfBoundsException
. Only check if the following character is not a space, (
, or [
when the document is longer than the tail offset to prevent the IndexOutOfBoundsException
. If the insertion is at the end of the file, then the ()
will always be inserted. - @KronicDeth
Decompilated
-> Decompilation
- @KronicDeth
Data(Output|IntputStream
(write|read)Int
don't work correctly with sizes, so use the JetBrains (write|read)VarInt
ones instead. - @KronicDeth
ChildAttributes
to previous child when available: Block.getChildAttributes
is used when Enter is pressed to determine the indentation and alignment. Using the default implementation, newlines in stabs look overly indented, but there is a constant, DELEGATE_TO_PREV_CHILD
that can be used to just use the last child's indent as long as there is one, which appears to work well for stabs (do block bodies, etc). - @KronicDeth
nameSetSize
from 4
to 10
because a Poison.Encoder
has an impl
module for 4 types, and so has 4 canonical names.Kernel.SpecialFroms
arity intervals
alias
overridden from 2
to 1-2
to support without :as
option.import
overridden from 2
to 1-2
to support without :except
or :only
options.quote
overridden from 2
to 1-2
to support block without options.require
overridden from 2
to 1-2
to support without :as
option.super
overridden from 1
to 0-
to support calling any super method.elixir.bat
in at least Elixir 1.5.1, will not properly parse a mix path with spaces in it on Windows even when the path has outer quotes (see elixir-lang/elixir#6455). It is not possible to use inner quotes, as you can do in cmd.exe, using the JetBrains and Java libraries hat auto-matically quote, so instead bypass the bad quoting in elixir.bat
by doing what elixir.bat
does: call erl.exe
with all the SDK ebin paths added with -pa
, then -noshell -s elixir start_cli
to run Elixir and-extra
to run requires (-r
), mix and its tasks. - @KronicDeth
14.1.X
support because it does not have support for nodeId test output, so it's not possible to handle the ExUnit test output in a safe manner while still allowing concurrent output for asynchronous tests.IntelliJ Elixir can reformat code to follow a consistent style.
do
block lines are indenteddo
blocks end
as the last argument of a no parentheses call unindents to the start of the callelse
.
and
in
or
when
=
<-
and \\
!=
, ==
, =~
, !==
, and ===
<
, <=
, >=
, and >
+
and -
*
and /
+
, -
, !
, ^
, and ~~~
->
::
|
||
and |||
&&
and &&&
<~
, |>
, ~>
, <<<
, <<~
, <|>
, <~>
, >>>
, and ~>>
..
^^^
++
, --
, ..
, <>
=>
,
@
not
fn
after
catch
rescue
key:
&
,
{ }
<< >>
[ ]
( )
/
in &NAME/ARITY
and &QUALIFIER.NAME/ARITY
when
wraps when its right operand wraps, so that guards start with when
on a newline when they are too long.|>
at start of indented line for pipelinesend
with start of call instead of start of line for do
blocks in pipelines::
when
when guards span multiple lines++
, --
, ..
, <>
) operands, so that <>
binaries are multiple lines align their starts instead of using continuation indent and being indented relative to first operand.|
operands, so that alternates in types and specs are aligned instead of continuation indented relative to the first operand.spec
(that is above operands to |
align with the operands|>
is the start of a successive line.<< >>
) elements when wrappedAll files in a directory can be reformatted.
Using context menu:
Using keyboard shortcuts:
Alt+Cmd+L
All lines in a file can be reformatted.
Using context menu:
Using keyboard shortcuts:
Alt+Cmd+L
All the lines in the current editor tab file can be reformatted with the
current settings.
Alt+Cmd+L
Alt+Shift+Cmd+L
to get the Reformat Code dialog.A subset of a file can be reformatted.
Alt+Shift+Cmd+L
Published by KronicDeth over 7 years ago
scope.isEquivalentTo(lastParent.getParent())
is false
in processDeclarationsInPreviousSibling
assert scope.isEquivalentTo(lastParent.getParent())
with an if
and log what lastParent
was when condition is false
, so root cause can be traced. - @KronicDeth
IntelliJ Elixir allows for graphical debugging of *.ex
files using line breakpoints.
*.ex
filesAfter you have configured a run configuration for your project, you can launch it in debug mode by pressing Ctrl+D
.
Action | Keyword Shortcut |
---|---|
Toggle Breakpoint | Cmd+F8 |
Resume Program | Alt+Cmd+R |
Step Over | F8 |
Step Into | F7 |
View breakpoint details/all breakpoints | Shift+Cmd+F8 |
When a breakpoint is set, the editor displays a breakpoint icon in the gutter area to the left of the affected source code. A breakpoint icon denotes status of a breakpoint, and provides useful information about its type, location, and action.
The icons serve as convenient shortcuts for managing breakpoints. Clicking an icon removes the breakpoint. Successive use of Alt - click on an icon toggles its state between enabled and disabled. The settings of a breakpoint are shown in a tooltip when a mouse pointer hovers over a breakpoint icon in the gutter area of the editor.
Status | Icon | Description |
---|---|---|
Enabled | Indicates the debugger will stop at this line when the breakpoint is hit. | |
Disabled | Indicates that nothing happens when the breakpoint is hit. | |
Conditionally Disabled | This state is assigned to breakpoints when they depend on another breakpoint to be activated. |
When the button is pressed in the toolbar of the Debug tool window, all the breakpoints in a project are muted, and their icons become grey: .
To view the list of all breakpoints and their properties, do one of the following:
Shift+Cmd+F8
To view properties of a single breakpoint
To configure actions, suspend policy and dependencies of a breakpoint
Shift+Cmd+F8
*DBG* 'Elixir.IntellijElixir.DebugServer' got cast {breakpoint_reached, PID}
will appear in the console.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.
Cmd+F8
Cmd+Down
. The caret will be placed at the line marked with the breakpoint in question.When you temporarily disable or enable a breakpoint, its icon changes from to and vice versa.
Do one of he following:
Cmd+F8
.Ctrl+D
OR
Debug quick menu
Ctrl+Alt+D
Enter
Up
or Down
to change framesWhen changing frames or jumping to definitions, you can lose track of where the debugger is paused. To get back to the current execution point, do one of the following:
Alt+F10
While Elixir allows rebinding variable names, Erlang does not, so when viewed in the Variables pane, variables will have an @VERSION
after their name indicating which rebinding of a the variable is. Even if there is no variable reuse, the first variable will still have @1
in its name.
Action | Icon | Shortcut | Description |
---|---|---|---|
Show Execution Point | Alt+F10 |
Click this button to highlight the current execution point in the editor and show the corresponding stack frame in the Frames pane. | |
Step Over | F8 |
Click this button to execute the program until the next line in the current function or file, skipping the function referenced at the current execution point (if any). If the current line is the last one in the function, execution steps to the line executed right after this function. | |
Step Into | F7 |
Click this button to have the debugger step into the function called at the current execution point. | |
Step Out | Shift+F8 |
Click this button to have the debugger step out of the current function, to the line executed right after it. |
Published by KronicDeth over 7 years ago
With both the contribution of ExUnit Mix Tasks in 4.7.0
and the conversion of the build to Gradle for 5.0.0
, I've added Jake Becker (@JakeBecker) as a Collaborator to the repo.
AssertionError
in org.elixir_lang.code_insight.lookup.element_renderer.CallDefinitionClause.renderElement
ElixirVariable
could not be determined if it was a variable.
ElixirMultipleAliases
could not resolve variable in match.
MatchedUnqualifiedParenthesesCall
could not be type highlighted
.beam
-only Module, which is what inspired me to attempt decompilation
.beam
files
.beam
files.beam
files.beam
files (both SDK and deps)
:idna
)Enum
).beam
files (both SDK and deps)
Enum
).beam
files.beam
files
ELIXIR_VERSION
for 1.2.*
from 1.2.3
to 1.2.6
ELIXIR_VERSION
1.3.4
ELIXIR_VERSION
1.4.0
IDEA
for 2016.*
to 2016.3.1
OtpErlangBitStr
(and therefore OtpErlangBinary
contents when tests failto_charlist
instead of to_char_list
for Elixir >= 1.3
. Depends on Elixir version of project SDK.elixir
instead of java
VM, so now Erlang and Elixir don't need to be built on travis-ci, but ant
and the jdk
need to be installed, but unlike Erlang and Elixir, there are tarballs for that, so this way is faster than the old method without depending on travis-ci cache.multiResolve
causes a StackOverflow
for org.elixir_lang.annotator.Callable.visitCall
, then catch
it and use errorreport
logger to log the element.errorreport
excerptStackOverflow
related to import
sLookupElement#getObject
when LookupElement#getPsiElement
is null
to track down how it was null
in #563../gradlew runIde
(or the runIde (VERSION)
Run Configurations) will run IDEA in a sandbox with the development version of the plugin../gradlew test
(or the test (VERSION)
Run Configurations) will run the main plugin and jps-builder tests../gradlew publishPlugin
, BUT you'll need to fill in publish*
properties in gradle.properties
. This will eventually allow for automated "nightlies" from successful Travis-CI builds on master
.Callable
annotator is meant for variables, parameters, and macro and function calls and declarations. The ModuleAttribute
annotator handles module attribute declaration and usage, so we can save reference resolution time by skipping module attributes in Callable
. - @KronicDeth
defmodule
.Callable.callDefinitionClauseDefiner(Call)
: in addition to the current CallDefinitionClause
, make it work for Implementation
, Module
, and Protocol
.MatchOperatorInsteadOfTypeOperator
- @KronicDeth
.beam
file when decompiling to defmacro
calls because the Erlang function for Elixir macros has one addition argument: the first argument is the Caller
of the macro.BeamFileImpl
VirtualFile
argument to BeamFileImpl#buildFileStub
.++
, =~
, and in
to INFIX_OPERATOR_SET
.2
.+
and -
are both binary and unary operators. When a unary operator they need to be wrapped in parentheses, so that the call definition clause is parsed correctly.JFLex
jarelixir-lang/elixr
files remove in 1.3
nil
as a keyword key. nil
was being lexed as a potential keyword key, but NIL was missing from the token list in the keywordKey grammar rule.unquote
. - @KronicDeth
MultipleAliases
for variable declarations.MultipleAliases
as invalid.import Kernel
in kernel.ex
to prevent stack overflow due to recursive import
(+value)
can be see as +
operator type spec.IndexNotReadyException
documentation and check DumbService.isDumb(Project)
before calling StubIndex.getElements
in Module
and module.MultiResolve.indexNameElements
.assert
that LookupElement#getPsiElement
is not null
in CallDefinitionCluase.renderElement
ant
1.10.1
because 1.10.0
is no longer hosted.ElixirVariable
isn't necessarily a variable if it doesn't occur in a declaration context. It could just be a no-parentheses function call in the wrong spot, so check the parent PsiElement
to determine if ElixirVariable
is a variable. - @KronicDeth
maybe(t)
in @type maybe(t)
) the same as a full type definition (maybe(t)
in @type maybe(t) :: t | nil
) - @KronicDeth
do:
as atom in demo text - @KronicDeth
referrer
Callable
. The resolved
may be outside the file if it is a cross-file function or macro usage, in which case it's TextRange
should not be highlighted because it is referring to offsets in a different file. - @KronicDeth
Variable
scope for QualifiedMultipleAliases
, which occurs when qualified call occurs over a line with assignment to a tuple, such as Qualifier.\n{:ok, value} = call()
ESC
was hit to cancel the completion, which became excessive once the index of call definition clauses was expanded by the decompilation of the Elixir standard library .beam
s, so disable it. If bare-words completion is restored. It will either (1) need to not use the Reference#getVariants()
API because it generates too many objects that need to be thrown away or (2) need to only complete call definition clauses that are provably in-scope from imports or other macros.LICENSE.md
CODE_OF_CONDUCT.md
when
operation in case it's a guarded function head in org.elixir_lang.annonator.Parameter.putParameterized(Parameter, PsiElement)
def*
call is encountered.ModuleImpl#getProject()
to prevent StackOverflowError
. Without overriding #getProject()
, IdentifierHighlighterPass
gets stuck in a loop between getManager
and getProject
on the target (the ModuleImpl
) when clicking on the space between def
s or defmacro
s in the decompiled .beam
files.CallDefinitionClause
completion provider is unexpectedly invoked both when .
is typed, but continues to be invoked after a letter is typed after the .
; however, once the letter is typed, the letter becomes the default prefix instead, so the prefix should only be reset to ""
when it ends in .
.Callable#getVariants
unless Unqualified
to prevents local functions and macros being shown as completions for qualified names.Alias
now has underscored
effectBrackets
are now greenish instead of brownishCallbacks
are now a lighter blue and has underscored
effectCharList
is little lighterCharToken
is dark yellow now instead of dark purpleDot
is now purple instead of dark redExpression Substitution Mark
is a little lighterInterpolation
is now lime greenKernel Macros
are a burnt orangeMap
is now a dark blue instead of a dark yellowOperation Sign
is a little lighterParameters
are a little darkerParentheses
are redderPredefined
is orange instead of blueSpecification
is now red instead of purpleStruct
is now purple instead of yellowType
is now green instead of dark purpleVariable
is more tealishCONTRIBUTING.md
CONTRIBUTING.md
null
for For.resolveResultList
Protocol.resolveResultList
is null
match
Call
is an UnqualifiedNoArgumentCall
, in addition to being 0 resolved final arity, before checking if the name matches. - @KronicDeth
^^^
to its own three-operator precedence level to match 1.2
. This does mean the parsing will be wrong for Elixir 1.1
, but is simpler than maintaining two grammars for those that are still using Elixir 1.1
- @KronicDeth
ant
build files have been removed. To build the build plugin (for Install From Disk), use the ./gradlew buildPlugin
. - @JakeBecker
.beam
files, such as those in the Elixir SDK and in your project's build
directory will be decompiled to equivalent def
and defmacro
calls. The bodies will not be decompiled, only the call definition head and placeholder parameters. These decompiled call definition heads are enough to allow Go To Declaration, the Structure pane, and Completion to work with the decompiled .beam
files.
Published by KronicDeth almost 8 years ago
isVariable
CallDefinitionClause(Call)
needed between error handling to avoid a NullPointerException
:
in type specs could break the highlighting, which led to the inspections and quick fixes in this release.CommonProgramParametersPanel
to get the working directory and environment variables the same way the JUnit form does. Replace the custom "Command" input with the "Program arguments" input built into the CommonProgramParametersPanel
. CommonProgramParametersPanel
expects to store the "Program Arguments" in a "ProgramParameters" field, so old run configurations will lose their "Command" option value and it will be migrated to the new "ProgramParameters". - @KronicDeth
enclosingMacroCall
returns enclosing macro call when parent is ElixirDoBlock
, so that end
element goes to the macro call.Navigate > Test
will go to the Module that has the same canonical name as the current defimpl
, defmodule
, defprotocol
, or quote
with a Test
suffix addedNavigate > Test Subject
will go to the defimpl
, defmodule
, defprotocol
, or quote
that has the same canonical name as the current Module with the Test
suffix removed.:
is used instead of ::
for a type specification, mark it as an error with a Quick Fix to convert :
to ::
.=
operands the same as ::
operands in type specifications.=
is used instead of ::
in a type specification, mark it as an error with a Quick Fix to convert =
to ::
.myRunInModuleChekcBox
=> myRunInModuleCheckBox
- @KronicDeth
ElixirMultipleAliases
for isVariable
because ElixirMultipleAliases
can be hit in isVariable
when MyAlias.
is added on a line above a pre-existing tuple, such as when typing a new qualified call. - @KronicDeth
VirtualFile
is not null before creating attachment because PsiFile
can lack a VirtualFile
if the PsiFile
only exists in memory. - @KronicDeth
CallDefinitionClause(Call)
to CallDefinitionClause.fromCall(Call)
, so that null
can be returned when CallDefinitionClause.enclosingModular(Call)
returns null
. - @KronicDeth
functionName
instead of getName
when multiresolving unqualified functions because getName
will return the Alias when called on defmodule
.maybeQualifiedCallToModular
returned null
BOTH (1) if the call was unqualified OR (2) if the call was qualified, but its modular could not be resolved, so qualified calls to .beam
-only modules, like File.read!
returned null
because File
could not be resolved to a modular. Remove maybeqQualifiedToModular
and call qualifiedToModular
when myElement
is qualified. If the modular is null
, then return an empty ResolveResult[]
instead of looking for unqualified matches.maxScope
to Module
reference. maxScope
is generally the containing file for the element, but when using Module
to resolve import
s, it is the import
call's parent element, so that the resolve doesn't ricochet between the defmodule
and its child, the import
call until StackOverflowError
.LocalSearchScope.EMPTY
, the same as interpolation. - @KronicDeth
ElixirSystemUtil.getProcessOutput
already allowed for an empty, invalid ProcessOutput
when the workDir
wasn't a directory, so allow it to also be null
and return the empty ProcessOutput
. - @KronicDeth
:
as a type for ::
:
) used in type spec instead of type operator (::
)Type specifications separate the name from the definition using ::
.
@type name: definition
Replace the :
with ::
@type name :: definition
=
) used in type spec instead of type operator (::
)Type specifications separate the name from the definition using ::
.
@type name = definition
Replace the =
with ::
@type name :: definition
:
to ::
in type specsIf a type specification uses a single :
instead of ::
, then hit Alt+Enter on the :
to change it to ::
and fix the type spec.
=
to ::
in type specsIf a type specification uses =
instead of ::
, then hit Alt+Enter on the =
to change it to ::
and fix the type spec.
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
mix test
Run Configurations Manuallymix test
. Normally, this will be a directory like test
, relative to the "Working directory"...
button...
button on the "Environment variables" line to add environment variables.mix test
taskWhile 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.
mix test
Run Configurations from contextThe 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.
test
directory is marked as a Test Sources Root
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 menutest
directory.mix test
Run Configurations from directoryAlternatively, you can use keyboard shortcuts
Ctrl+Shift+R
will create the Run Configuration and Run it.mix test
Run Configurations from fileAlternatively, you can use keyboard shortcuts
Ctrl+Shift+R
will create the Run Configuration and Run it.Finally, you can use the editor tabs
mix test
Run Configurations from lineIf you want to be able to run a single test, you can create a Run Configuration for a line in that test
Alternatively, you can use keyboard shortcuts
Ctrl+Shift+R
will create the Run Configuration and Run it.Published by KronicDeth almost 8 years ago
v4.5.0 was a canary release, so it's release notes are included in this general release in case you didn't run the canary
NullPointerException
from org.elixir_lang.psi.scope.call_definition_clause.Variants.getLookupElementCollection
.StackOverflowError
s from certain forms of with
and helping me narrow down specific minimal reproduction cases.do
for do
blocks.ElixirNoParenthesesStrict
error handling, which revealed that isVariable
didn't handle it correctly.Prefix.primaryArguments
wasn't using Normalized
and still was using basic assert
s.do
end
matching was too aggressive and incorrectly matched on one liners starting at the do:
.Qualified#qualifier
by extracting it from CallDefinitionClause
CompletionProvider
.Modular
class with #forEachCallDefinitionClauseNameIdentifier
to enumerate all the identifiers that could be linked to in a modular.ElixirPsiImplUtil#maybeQualifiedCallToModular
by extracting resolveFully
from CallDefinitionClause
CompletionProvider
Arrow
interface for *ArrowOperation
s.emptySet
when lookupElementByPsiElement
is null
. - @KronicDeth
Don't do a naked assert
that there are 2 children because this can fail during error recovery on the operand, instead use the prefix.Normalized.operand()
through prefix.operand()
.
WARNING: This changes the @NotNull
array so that its sole element changes from @NotNull
to @Nullable
. It may trigger new bugs.
GeneratedParserUtilBase.DUMMY_BLOCK
because the DUMMY_BLOCK
MUST match the GeneratedParserUtilBase
to detect dummy blocks inserted for error handling. - @KronicDeth
ElixirNoParenthesesStrict
for isVariable
- @KronicDeth
do
in doBlock
- @KronicDeth
do
or fn
to end
when used as a keyword key. - @KronicDeth
iterator.atEnd()
before calling iterator.getTokenType()
to avoid IndexOutOfBounds
exception.When#leftOperand
will return null
(because it's normalized) if there are left-hand error elements, but when stripping guards we want best-effort to match human expectations, so don't use normalized null
, but use left, non-error element if it is unique. - @KronicDeth
QualifiedNoParenthesesCall
- @KronicDeth
name
for a CallDefinitionClause
lookup renderer can be longer than presentableText
, so still log an error, but with Logger.error
, so we get name
, presentableText
, and the original element
. - @KronicDeth
Arguments
elements in previousParentExpresion
to eliminate an unnecessary level of processing declarations since calls will enter their arguments.ENTRANCE
in ResolveState
in variable.MultiResolve.resolveResultList
, so that caller can override the default value.ENTRANCE
to matchAncestor
instead of previous expression to eliminate the looping that occurred when a variable was unbound (or a function) because the check for with
(and for
) was expecting the ENTRANCE
to be the previous child expression instead of the with
clause as a whole (or the Arguments
element as had been the case before 6fcc19b).Call#resolvedFunctionName
because import
can't rename functions.BracketOperation
s as they occur when putting maps or structs in front of lists. - @KronicDeth
Enum.each
the same as Enum.map
around def
- @KronicDeth
resolvedFinalArity
by 1
for piping. - @KronicDeth
import
import MyModule
import
statementimport MyModule, only: [name: arity]
import
statementimport MyModule, except: [name: arity]
if reference is not name/arity
.
import
statement.beam
file, such as the standard library will not resolve.).beam
file, such as the standard library will not complete.)
()
after the name in preparation for Elixir 1.4 where it is an error to have bare function calls. It also makes it more obvious that you inserted a function and not a variable.Completion uses the same presentation as Structure, so you can tell whether the name is function/macro (Time), whether it is public/private (Visibility) and the Module where it is defined. Between the icons and the Modules is the name itself, which is highlighted in bold, the parameters for the call definition follow, so that you can preview the patterns required for the different clauses.
Qualified functions and macro calls will complete using those functions and macros defined in the qualifying Module (defmodule
), Implementation (defimpl
) or Protocol (defprotocol
). Completion starts as shown as .
is typed after a qualifying Alias.
Function and macro calls that are unqualified are completed from the index of all function and macro definitions, both public and private. (The index contains only those Elixir functions and macro defined in parsable source, such as those in the project or its dependencies. Erlang functions and Elixir functions only in compiled .beam
files, such as the standard library will not complete.) Private function and macros are shown, so you can choose them and then make the chosen function or macro public if it is a remote call.
You'll know if function or macro usage is resolved and Go To Declaration will work if the call is annotated, which in the default themes will show up as italics.
Cmd+B
Cmd+Click
import
that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
Enter
Click
Cmd+B
Cmd+Click
import
that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
Enter
Click
Cmd+B
Cmd+Click
import
that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
Enter
Click
Published by KronicDeth about 8 years ago
Canary build of v4.5.0
Published by KronicDeth about 8 years ago
isParameter
didn't work for ElixirBracketArguments
.QualifiableAlias#fullyQualifiedName
was still using assert
instead of the Normalized
helpers and so could fail when QualifiableAlias
did not have 3 children as can happen during error recovery.isVariable
did not work in the else
block, which can occur when a variable does not resolve because it's not fully typed or it would resolve to a function.isVariable
not working for ambiguously nested no parentheses calls, so now the editor can highlight through code that causes a native compiler error.for
comprehensions being nested in one-line function calls leading to isParameter
not working. This is another case where the editor can highlight through code that causes a native compiler error.isParameter
.typespec_test.exs
that triggered #413 - @KronicDeth
import
is used for GeneratedParserUtilBase
in ElixirParser
- @KronicDeth
ElixirMultipleAliases#processDeclarations
, so that treeWalkUp
can stop at ElixirMultipleAliases
when determining how to do Alias completion. If a multiple alias is encountered, then de-prefixed names should be returned.Set
instead of null
from canonicalNameSet
ElixirMapUpdateArguments
even though they are an invalid typespec example from elixir-lang/elixir tests
rightOperand
is null
when highlighting types for Type
, which can occur when typing :
for an atom after the ::
for a Type
- @KronicDeth
GeneratedParserUtilBase
synced to GrammarKit version as was done originally in #406 - @KronicDeth
BracketArguments
for isParameter
and isVariable
- @KronicDeth
QualifiableAlias
has 3 children, which may not be true on error recovery, use the Normalized
static methods that are used elsewhere to handle error recovery around Infix operations as the .
in QualifiableAlias
es is a pseudo-Infix - @KronicDeth
@Nullable
to @NotNull
change when parser wasn't regenerated when canonicalNameSet
was changed to @NotNull
in the interface. - @KronicDeth
isVariable
for ElixirNoParenthesesManyStrictNoParenthesesExpression
- @KronicDeth
@type
without ::
- @KronicDeth
ElixirNoParenthesesManyStrictNoParenthesesExpression
indicates an ambiguous no parentheses nesting, but the highlighting should not error and do a best effort instead. - @KronicDeth
isParameter(Call)
called isParameter
on its parent if it wasn't a call definition clause, delegation or macro, but isParameter(PsiElement)
immediately calls getParent()
and does all the instanceof
tests on the parent. So, instead of isParameter(Call)
calling isParameter(PsiElement)
on its parent, it should just call it on itself, this way the check for ElixirInterpolation
will not be skipped and there's no need to handle ElixirInterpolatedString
. - @KronicDeth
Published by KronicDeth about 8 years ago
Canary build of v4.4.0-dev at 2016-09-08T13:48:05Z.
Published by KronicDeth about 8 years ago
NoSuchMethod
errors on GeneratedParserUtilBase
, which motivated me to actually ask JetBrains how to fix the problem, where Yann Cébron (@YannCebron)unquote({name, [], nil})
in type specs was brokenDBConnection.Connection.sync_stop/4
for variable resolution not working for pinned variable in receive
clauses.alias
, import
, require
, user
) folding.isParameter
errors.alias
call, from the alias call, you can Go To Declaration for the module itself. - @KronicDeth
treeWalkUp
now instead of custom code.Suffix
resolves to alias Prefix.Suffix
Suffix.Nested
resolves to alias Prefix.Suffix
As
resolves to
alias Prefix.Suffix, as: As`NestedSuffix
resolves to alias __MODULE__.NestedSuffix
__MODULE__
StubBased#canonicalName
, there now also StubBased#canonicalNames
, for when a call defines multiple canonical names, as is the case for defimpl <PROTOCOL>, for: [<TYPE>, ...]
. - @KronicDeth
AllName
index, if any nested modules are found for the unaliased name, then those nested names are aliased and also shown for completion. - @KronicDeth
resolvableName
allows nested modules under multiple aliases to be completed. - @KronicDeth
alias
, import
, require
or use
) groups. - @KronicDeth
as:
aliased name to both alias
and defmodule
as:
aliased name.alias Prefix.Suffix
alias Prefix.Suffix, as: As
alias Prefix.{MultipleAliasA, MultipleAliasB}
defimpl <PROTOCOL>, for: [<TYPE>, ...]
generates multiple canonical names, which are stored in the stub index.
AllName
index, the defimpl
's Implementation will render as if only the defimpl <PROTOCOL>, for: <TYPE>
was used for the <TYPE>
matching the lookup name in the Goto Symbol dialog. For example, if you search for Tuple
, JSX.Encoder.Tuple
will match for defimpl JSX.Encoder, for: for: [Tuple, PID, Port, Reference, Function, Any]
.Ecto
defines the clauses of __schema__(:type, ...)
using Enum.map
, but enclosingMacroCall
only knews to jump over enclosing macros like for
, so a special case was added for anonymous function given to Enum.map
.Call
appeared before operations (which are usually Call
s) like Match
.@type unquote({name, nil, []}) :: foo
, name
will be highlighted as a type parameter even though it is not strictly the name that will appear as a type parameter. - @KronicDeth
alias
and defmodule
, as resolving to only the alias
loses the nested name, so it wasn't possible to jump to the nested name's defmodule
.alias
and the defmodule
, so you can skip jumping to the alias
before jumping to the defmodule
.ElixirParser
uses the GeneratedParserUtilBase
from com.intellij.lang.parser
, but since that version is a synced copy, it is a snapshot of GeneratedParserUtilBase
from the version of GrammarKit that was current when the IDE was released. To ensure the generated parser works on all the IDEs, I copy GeneratedParserUtilBase
from org.intellij.grammar.parser
into org.elixir_lang.grammar.parser
and then use that version in ElixirParser
. This ensures neither the IDE's version nor the version in any installed GrammarKit plugin is used.StubIndex.getInstance.getAllKeys(...)
is a superset of actual keys in the actual project according to Peter Gromov of JetBrains.canonicalName
if it matches the literal name, as the duplicate name leads to duplicate entries in the completion lookup.
canonicalNameCollection
was renamed to canonicalNameSet
(with type changing from Collection<String>
to Set<String>
to match) to emphasize that the canonical names should be unique, but canonicalNameSet
itself should still include duplicates of name for those places where only canonical names are used.resolvableName
for the unaliasedName
for MultipleAliases
Aliases, so that they complete correctly for nested modules.SSHView
) and only complete nested Aliases (i.e. SSH.Key
).When you start typing an Alias, completion will look in three locations:
alias
aliased names in the current fileSuffix
for alias Prefix.Suffix
MultipleAliasA
or MultipleAliasB
for alias Prefix.{MultipleAliasA, MultipleAliasB}
As
for alias Prefix.Suffix, as: As
Prefix.Suffix
from defmodule Prefix.Suffix
MyProtocol
from defprotocol MyProtocol
MyProtocol.MyStruct
defimpl MyProtocol, for: MyStruct
defimpl MyProtocol
nested under defmodule MyStruct
Suffix.Nested
for alias Prefix.Suffix
where Prefix.Suffix.Nested
is an indexed module, implementation or protocol name.MultipleAliasA.Nested
for alias Prefix.{MultipleAliasA, MultipleAliasB}
where Prefix.MultipleAliasA.Nested
alias Prefix.{MultipleAliasA, MultipleAliasB}
is an indexed module, implementation or protocol name.As.Nested
for alias Prefix.Suffix, as: As
where Prefix.Suffix.Nested
is an indexed module, implementation, or protocol name.Go To Declaration is a feature of JetBrains IDEs that allows you to jump from the usage of a symbol, such as a Module
Alias, to its declaration, such as the defmodule
call.
alias
Suffix
if alias Prefix.Suffix
calledMultipleAliasA
if alias Prefix.{MultipleAliasA, MultipleAliasB}
calledAs
if alias Prefix.Suffix, as: As
Cmd+B
Cmd+Click
alias
that setup the aliased name or jumping directly to defmodule
of the unaliased name. Select which declaration you wantEnter
Click
A.B
in A.B.func()
A.B
in alias A.B
B
in alias A.{B, C}
Cmd+B
Cmd+Click
If you hold Cmd
and hover over the Alias before clicking, the target declaration will be shown.
Published by KronicDeth about 8 years ago
Canary build of v4.3.0-dev at 2016-09-01T14:43:52Z
Published by KronicDeth about 8 years ago
Canary build of v4.3.0-dev at 2016-08-22T08:18:35Z