v4.7.0

@KronicDeth KronicDeth released this Dec 6, 2016 · 46 commits to master since this release

Thanks

  • Thanks to Jake Becker (@JakeBecker) for adding Mix ExUnit Run Configurations and create from context.
  • Thanks to @andyl for requesting Navigate > Test and Navigate > Test Subject as it was a good complement to Jake Becker's new Mix ExUnit Run Configurations
  • Thanks to Alexander Merkulov (@merqlove) for outline the testing workflow that Jack Becker ended up implementing
  • Thanks to @davit55 and Matt Briggs (@mbriggs) for confirming that lookup name could exceed the element text and it wasn't just an artifact of my development environment
  • Thanks to @taorg for a full test case to show how MultipleAliases would need to be supported in isVariable
  • Thanks to Josh Taylor (@joshuataylor for posting a screenshot of the bad lookup formatting for variables.
  • Thanks to Matt Briggs (@mbriggs) for posting an error about the error reporter 😝
  • Thanks to Josh Taylor (@joshuataylor, Matt Briggs (@mbriggs), Cris (@crisonyx), @sngyai, @lucdang, Cris (@crisonyx), Sven Marquardt (@Eiamnacken), and Aaron Eikenberry (@aeikenberry) for reporting that CallDefinitionClause(Call) needed between error handling to avoid a NullPointerException
  • Thanks to Matt Briggs (@mbriggs) for posting the source for a reproduction-case for the StackOverflow that was plaguing @andshape, Robert Hencke (@rhencke), Alexander Merkulov (@merqlove), @fieldinrain, Roman (@roman462), Andrei Dziahel (@develop7), and Josué Henrique Ferreira da Silva (@josuehenrique)
  • Thanks to Tiziano Puppi (@tizpuppi) for demonstrating how a typing a typo could cause an error in variable use scope.
  • Thanks to nsm (@nsmuffin) for posting that working directory being null wasn't treated the same as not being a directory.
  • Thanks to Ryan Scheel (@Havvy for showing how missing a : in type specs could break the highlighting, which led to the inspections and quick fixes in this release.

Changelog

v4.7.0

Enhancements

  • #523 - Use the 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
  • #482 - @JakeBecker, @KronicDeth
    • Create / Run Mix ExUnit Run Configurations
      • Run Configuration from Directory
      • Run Configuration from File
      • Run Configuration from LIne
    • Run Configurations support Common Program Parameters
      • Program Arguments
      • Working directory
      • Environment variables
  • #531 - @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 added
    • Navigate > 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.
  • #533 - Regression test for #500 - @KronicDeth
  • #545 - Regression test for #517 - @KronicDeth
  • #548 - Regression test for #521 - @KronicDeth
  • #549 - @KronicDeth
    • Regression test for #525
    • If : is used instead of :: for a type specification, mark it as an error with a Quick Fix to convert : to ::.
    • Highlight = operands the same as :: operands in type specifications.
    • If = is used instead of :: in a type specification, mark it as an error with a Quick Fix to convert = to ::.

Bug Fixes

  • #523 - Fix typo: myRunInModuleChekcBox => myRunInModuleCheckBox - @KronicDeth
  • #532 - Don't log error when name length exceeds presentable text length because it appears to be common for normal users and not a development environment artifact. - @KronicDeth
  • #533 - Check parent of 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
  • #534 - Add space between variable and match in lookup element presentation - @KronicDeth
  • #535 - Check VirtualFile is not null before creating attachment because PsiFile can lack a VirtualFile if the PsiFile only exists in memory. - @KronicDeth
  • #537 - Convert CallDefinitionClause(Call) to CallDefinitionClause.fromCall(Call), so that null can be returned when CallDefinitionClause.enclosingModular(Call) returns null. - @KronicDeth
  • #539 - @KronicDeth
    • Use 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.
    • Pass maxScope to Module reference. maxScope is generally the containing file for the element, but when using Module to resolve imports, 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.
  • #545 - A variable cannot be declared in update arguments, so return LocalSearchScope.EMPTY, the same as interpolation. - @KronicDeth
  • #548 - 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
  • #549 - @KronicDeth
    • If a single keyword pair is used for a type spec, treat : as a type for ::
    • Limit variable use scope for variables "declared" in module attributes to the module attribute because the variable can't be declared there and it is really a variable usage without declaration.

README Changes

Inspections

Keyword pair colon (:) 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

Match operator (=) 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

Quick Fixes

Convert : to :: in type specs

If a type specification uses a single : instead of ::, then hit Alt+Enter on the : to change it to :: and fix the type spec.

Convert = to :: in type specs

If a type specification uses = instead of ::, then hit Alt+Enter on the = to change it to :: and fix the type spec.

Run Configurations

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

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 "Program arguments" with the argument(s) to pass to mix test. Normally, this will be a directory like test, relative to the "Working directory"
  5. Fill in the "Working directory"
    • Type the absolute path to the directory.
    • Select the path using directory picker by clicking the ... button
  6. (Optionally) click the ... button on the "Environment variables" line to add environment variables.
  7. Click "OK" to save the Run Configuration and close the dialog
  8. Click the RUn arrow in the Toolbar to run the mix test task
  9. The Run pane will open showing the Test Results Test Results

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
    1. 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
    2. Right-click the test directory.
    3. 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.

Downloads

v4.6.0

@KronicDeth KronicDeth released this Nov 11, 2016 · 119 commits to master since this release

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

Thanks

  • Thanks to Matt Briggs (@mbriggs) and Andrei Dziahel (@develop7) for reporting the NullPointerException from org.elixir_lang.psi.scope.call_definition_clause.Variants.getLookupElementCollection.
  • Thanks to Sergey Zubtsovskiy (@szubtsovskiy) for reporting StackOverflowErrors from certain forms of with and helping me narrow down specific minimal reproduction cases.
  • Thanks to @mdhirsch for finding a parser bug (!) after all this time: newlines weren't allowed before do for do blocks.
  • Thanks to Scott Bennett (sbennett33) for finding a case that triggered the ElixirNoParenthesesStrict error handling, which revealed that isVariable didn't handle it correctly.
  • Thanks to Andrei Dziahel (@develop7) for reporting an error that while I couldn't reproduce did lead to an improved error reporter, so I can figure it out if it happens again.
  • Thanks to Danni Friedland (BlueHotDog) for reporting a bug that led me to find that Prefix.primaryArguments wasn't using Normalized and still was using basic asserts.
  • Thanks to Aaron Foster (AnimalRepellentGranules) for reporting that the do end matching was too aggressive and incorrectly matched on one liners starting at the do:.

Changelog

v4.6.0

Enhancements

Bug Fixes

  • #454 - Return emptySet when lookupElementByPsiElement is null. - @KronicDeth
  • #455 - @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.

  • #461 - Use shipped GeneratedParserUtilBase.DUMMY_BLOCK because the DUMMY_BLOCK MUST match the GeneratedParserUtilBase to detect dummy blocks inserted for error handling. - @KronicDeth
  • #465 - Skip over ElixirNoParenthesesStrict for isVariable - @KronicDeth
  • #466 - Allow newlines before do in doBlock - @KronicDeth
  • #467 - Don't match do or fn to end when used as a keyword key. - @KronicDeth
  • #474 - @KronicDeth
    • Check if iterator.atEnd() before calling iterator.getTokenType() to avoid IndexOutOfBounds exception.
    • Don't add current call definition clause being written to completion
  • #476 - 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
  • #477 - Highlight types in QualifiedNoParenthesesCall - @KronicDeth
  • #478 - Still not obvious why 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
  • #479 - @KronicDeth
    • Skip Arguments elements in previousParentExpresion to eliminate an unnecessary level of processing declarations since calls will enter their arguments.
    • Only put new ENTRANCE in ResolveState in variable.MultiResolve.resolveResultList, so that caller can override the default value.
    • Set 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).
  • #483 - @KronicDeth
    • Resolves functions qualified by Aliases that are either direct Module references or one-step aliases.
    • Remove Call#resolvedFunctionName because import can't rename functions.
  • #484 - Don't type-highlight BracketOperations as they occur when putting maps or structs in front of lists. - @KronicDeth
  • #485 - Treat Enum.each the same as Enum.map around def - @KronicDeth
  • #486 - Increase resolvedFinalArity by 1 for piping. - @KronicDeth
  • #498 - @KronicDeth
    • Go To Declaration resolves through import
      • for import MyModule
        • the import statement
        • the call definition clause in the imported Module.
      • for import MyModule, only: [name: arity]
        • the import statement
        • the call definition clause in the imported Module.
      • for import MyModule, except: [name: arity] if reference is not name/arity.
        • the import statement
        • the call definition clause in the imported Module.

v4.5.0

Enhancements

  • #452 - @KronicDeth
    • Go To Declaration for functions and macros (only those defined in parseable-Elixir source. References to Erlang functions or only those available in .beam file, such as the standard library will not resolve.)
    • Completion for functions and macros (only those defined in parseable-Elixir source. Erlang functions and Elixir function only in compiled .beam file, such as the standard library will not complete.)
      • Completion uses the same presentation as Structure View, so the you can tell whether the name is a function/macro, whether it is public/private, and the Module where it is defined.
      • Completed functions/macro insert () 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 works for all functions when a bare identifier is used. For a qualified identifier, only functions/macros under than Module are shown.

README Changes

Completion

Function and Macro Calls

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.

Function and Macro Calls Completion

Qualified

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.

Unqualified

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.

Go To Declaration

Function or Macro

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.

Imported Functions or Macros
  1. Place the cursor over name of the function or macro call.
  2. Activate the Go to Declaration action with one of the following:
    1. Cmd+B
    2. Select Navigate > Declaration from the menu.
    3. Cmd+Click
  3. A Go To Declaration lookup menu will appear, allowing you to jump to either the import that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
    1. Use arrow keys to select and hit Enter
    2. Click
Local Functions or Macros
  1. Place the cursor over name of the function or macro call.
  2. Activate the Go to Declaration action with one of the following:
    1. Cmd+B
    2. Select Navigate > Declaration from the menu.
    3. Cmd+Click
  3. Whether a lookup a Go To Declaration lookup menu appears depends on the number of clauses in the function or macro definition:
    1. If there is only one clause in the function or macro definition, you'll jump immediately to that clause
    2. If there is more than one clause in the function or macro definition, a Go To Declaration lookup menu will appear, allowing you to jump to either the import that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
      1. Use arrow keys to select and hit Enter
      2. Click
Remote Functions or Macros
  1. Place the cursor over name of the function or macro call that is qualified by an Alias.
  2. Activate the Go to Declaration action with one of the following:
    1. Cmd+B
    2. Select Navigate > Declaration from the menu.
    3. Cmd+Click
    1. If there is only one clause in the function or macro definition, you'll jump immediately to that clause
    2. If there is more than one clause in the function or macro definition, a Go To Declaration lookup menu will appear, allowing you to jump to either the import that imported the function or macro or jumping directly to the function or macro definition clause. Select which declaration you want.
      1. Use arrow keys to select and hit Enter
      2. Click

Downloads

v4.5.0

@KronicDeth KronicDeth released this Oct 9, 2016 · 201 commits to master since this release

Canary build of v4.5.0

Changes since v4.4.0

Downloads

v4.4.0

@KronicDeth KronicDeth released this Sep 18, 2016 · 226 commits to master since this release

Thanks

  • Thanks to Andrei Dziahel (@develop7 for reporting that indexing of the standard library was broken, which led to me making the type annotator (highlighter) work on invalid typespecs. Thanks to Robert Zotter (@zapient) and Gerald Philip MacKenzie (@gmack) for reporting the same bug, so I knew it was affect multiple users and I should release the fix ASAP.
  • Thanks to Alexander Merkulov (@merqlove) helping other users with SDK errors.
  • Thanks to @dima-starosud for pointing out that I broke the fix for GeneratedParserUtilBase when I regenerated the parser, so it was still broke in 4.3.0 when it being unbroke was one of the important bug fixes.
  • Thanks to Josué Henrique Ferreira da Silva (@josuehenrique) for finding a case where isParameter didn't work for ElixirBracketArguments.
  • Thanks to Claudio D'Alicandro (@claudio-dalicandro) for pointing out that 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.
  • Thanks to Andrei Dziahel (@develop7 for a most excellent bug report with reproduction steps, source code and even <details> to hide sections, which showed that 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.
  • Thanks to Josué Henrique Ferreira da Silva (@josuehenrique) for a full module reproducing isVariable not working for ambiguously nested no parentheses calls, so now the editor can highlight through code that causes a native compiler error.
  • Thanks to @adequateDeveloper for a repository to reproduce 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.
  • Thanks to Carlos Brito Lage (@cblage) for reporting a use case of interpolation that skipped a round of isParameter.

Changelog

v4.4.0

Enhancements

Bug Fixes

  • #419 - @KronicDeth
  • #424 - Check if rightOperand is null when highlighting types for Type, which can occur when typing : for an atom after the :: for a Type - @KronicDeth
  • #425 - Use GeneratedParserUtilBase synced to GrammarKit version as was done originally in #406 - @KronicDeth
  • #426 - Check parent of BracketArguments for isParameter and isVariable- @KronicDeth
  • #428 - Instead of asserting that a 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 QualifiableAliases is a pseudo-Infix - @KronicDeth
  • #432 - Add missing @Nullable to @NotNull change when parser wasn't regenerated when canonicalNameSet was changed to @NotNull in the interface. - @KronicDeth
  • #434 - Search above block items and block lists for calls to check use scope - @KronicDeth
  • #435 - Check parent isVariable for ElixirNoParenthesesManyStrictNoParenthesesExpression - @KronicDeth
  • #439 - Highlight @type without :: - @KronicDeth
  • #440 - ElixirNoParenthesesManyStrictNoParenthesesExpression indicates an ambiguous no parentheses nesting, but the highlighting should not error and do a best effort instead. - @KronicDeth
  • #441 - 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

Downloads

v4.4.0-dev+20160908134805

@KronicDeth KronicDeth released this Sep 8, 2016 · 269 commits to master since this release

Canary build of v4.4.0-dev at 2016-09-08T13:48:05Z.

Changes since v4.4.0

Downloads

v4.3.0

@KronicDeth KronicDeth released this Sep 5, 2016 · 276 commits to master since this release

Thanks

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

Changelog

v4.3.0

Enhancements

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

Bug Fixes

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

README Changes

Completion

Aliases and Modules

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

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

Go To Declaration

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

Alias

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

Module

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

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

Downloads

v4.3.0-dev+20160901144352

@KronicDeth KronicDeth released this Aug 31, 2016 · 308 commits to master since this release

Canary build of v4.3.0-dev at 2016-09-01T14:43:52Z

Downloads

v4.3.0-dev+20160822081835

@KronicDeth KronicDeth released this Aug 22, 2016 · 329 commits to master since this release

Canary build of v4.3.0-dev at 2016-08-22T08:18:35Z

Downloads

v4.2.0

@KronicDeth KronicDeth released this Aug 13, 2016 · 343 commits to master since this release

Thanks

  • Thanks to Filip Haglund (@drathier) and Andrei Dziahel (@develop7) for reporting reproduction cases for map update arguments not working with isVariable
  • Thanks Gerard de Brieder (@smeevil) for testing the canary build and finding the the do end completion mistakenly completed do: end.
  • Andrei Dziahel (@develop7) for find a working reproduction that Go To Symbol broke when trying to display def in the else of an if with Plug.Endpoint.
  • Nima Shariatian @nimashariatian for requesting I add the delimiter auto-insertion and matching.
  • Thanks to Jorg Heymans (@jorgheymans), Andrew Phillipo @aphillipo, and Filip Haglund (@drathier) on their input on the usability issues with the doc template and the need for @doc.

Changelog

v4.2.0

Enhancements

  • #371 - @KronicDeth
    • BraceMatcher
      • Matches the following pairs:
        • do to end
        • fn to end
        • """ to """
        • ''' to '''
        • << to >>
        • < to >
        • [ to ]
        • { to }
        • ( to )
      • Completes the following pairs:
        • [ with ]
        • { with }
        • ( with )
    • QuoteHandler completes standard quotes (that start with " or ')
      • ' with '
      • " with "
      • ''' with '''
      • """ with """
    • TypedHandler completes the non-standard quotes and braces
      • do with end
      • fn with end
      • <<with>>`
      • < with > (for promoters)
      • / with / (for promoters)
      • | with | (for promoters)

Bug Fixes

  • #372 - Check parent for isVariable(ElixirMapUpdateArguments) - @KronicDeth
  • #374 - @KronicDeth
    • IntelliJ 15.0.4 is no longer available from JetBrains, so if the cache is not available, the builds don't work, so use 15.0.6, which is available in 15.0.4's place as the test version for 15.X.
    • IntelliJ 2016.2 is no longer available from JetBrains, so if the cache is not available, the builds don't work, so use 2016.2, which is available in 2016.1's places at the test version for 2016.X.
  • #378 - enclosingMacroCall could climb out the stab after a do, but not the else in an if, which is used for defined functions conditionally in Phoenix.Endpoint.server/0 - @KronicDeth
  • #380 - A lot of ppl use the doc template after already typing @, but the doc template starts with @, so it ends up inserting @@doc .... The @doc template is the same code, but since the name starts with @, it doesn't insert a second @. Unfortunately, the template search code doesn't prompt when just typing @, so you end up having to type @doc before only one template is selected. The @doc template will show in the lookup as soon as @d is typed, but you have to select it from the list then before tabbing to accept. - @KronicDeth
  • #381 - Look at end of do instead of start for end completion to stop ignoring the : in do:, when caret - 3 would land on the o, now all tests are meant to land on the o, so do: won't complete with end incorrectly anymore. - @KronicDeth
  • #382 - Ignore ElixirVariable in highlightTypesAndTypeParameterUsages - @KronicDeth

README Updates

Delimiters

Auto-inserting

The right-delimiter will be automatically inserted when the left
delimiter is typed. In some cases, to prevent false positives, the
the delimiter is only completed if when used for sigils.

Preceded By Left Right
do end
fn end
[ ]
{ }
( )
' '
''' '''
" "
""" """
<< >>
~<sigil-name> < >
~<sigil-name> / /
~<sigil-name> | |

Matching

All delimiters that are auto-inserted are also matched for highlighting

Left Right
do end
fn end
[ ]
{ }
( )
' '
''' '''
" "
""" """
<< >>
< >
/ /
| |

Downloads

4.2.0-dev+20160812134719

@KronicDeth KronicDeth released this Aug 12, 2016 · 359 commits to master since this release

Canary build of 4.2.0-dev at 2016-08-12T13:47:19

Downloads