ex_check v0.14: new automations & curated tools to supercharge your Elixir workflow Understanding the Tradeoffs with Elixir Typespecs and Dialyzer

IntelliJ Elixir v11.9.2

Changelog

Bug Fixes

  • Protect from nested heredocs in documentation from stopping documentation’s heredoc as happens in Module and Ecto.Query.
    • Use ~S for @moduledoc too, in addition to @doc.
    • Check if the documentation contains “”” or ‘’’ and use the opposite one as the promoter/terminator.
      • If neither is used, use “””.
      • If both are used, use “””, but then escape “”” as \”\”\”.
    • Trim trailing whitespace from documentation lines to match formatter output.
  • Set runIde maxHeapSize to 7g
    • Set to the same I run my own IDE at, so the debugged instance isn’t any slower than the normal IDE when I need to do extended all day testing to trigger bugs.
  • Test that all FormattingTest files can be parsed.
  • YYINITIAL is special - wrappers of the lexer assume that if in YYINITIAL, it is safe to shift the lexer over when there is an error, having {OPENING_CURLY} pushAndBegin(YYINITIAL) when it was either in YYINITIAL or INTERPOLATION means that the lexer looked like it was restartable when it really wasn’t. This code has been in the lexer for 6 years.
    • When in YYINITIAL, { no longer recurses into YYINITIAL as } does not need to be counted to determine if it is closing an interpolation.
    • When in INTERPOLATION, { enters INTERPOLATION_CURLY to allow counting and matching of } until it can exit and go back to INTERPOLATION, where } will exit the interpolation.
    • When in INTERPOLATION_CURLY, { enters another level of INTERPOLATION_CURLY to allow counting and matching of } until it can exit and go up a level.
  • The } in YYINITIAL did yybegin(ADDITION_OR_SUBTRACTION_MAYBE), but it should have been pushAndBegin(ADDITION_OR_SUBTRACTION) as ADDITION_OR_SUBTRACTION_MAYBE or its following states all exit with handleInLastState() or popAndBegin(). This was not caught in #1859 because the extra YYINITIAL from pushAndBegin(YYINTIAL) hid the bug.
  • Prevent nested YYINITIAL bugs in the future by erroring
    • If trying to pushAndBegin(YYINITIAL).
    • If trying to push(YYINITIAL) and the state stack is not empty
  • Clear the state Stack when ElixirFlexLexer#reset is called, as at the level of typing and pasting, the ElixirFlexLexer is wrapped in many layers of lexers including LexerEditorHighlighter where the ElixirFlexLexer is no longer re-instantiated when there is no text, but instead, ElixirFlexLexer#reset is only called. This has always been an invariant violation since the stack state was added 7 years ago. It likely only became more apparent with the changes to +/- parsing in #1859 that made return-to-YYINITIAL less likely.
    • Since this stack.clear() has to be manually added to ElixirFlexLexer.java, which is generated from Elixir.flex, ResetTest is added to check that the code is still there.
  • For a reason I haven’t been able to explain, the LexerEditorHighlighter stops working after : is typed at the start of an atom in certain situations, such as before ) inside a function call, like when adding an argument. In this case, the old version of the lexer would mark ) as a BAD_CHARACTER and continue to do so until an expected atom start of [a-zA-Z_], , , or an operator occurred. Now, if an invalid atom start is matched, the ATOM_START state ends and the previous state handles the text, which in the function case mean ) is parsed as CLOSING_PARENTHESIS. This change allows the highlighting to continue. I do not know if returning BAD_CHARACTER will always break the LexerEditorHighlighter, but I don’t think, so since the GroovyLexer in intellij-community returns it, but it may be the case that it isn’t actually returned ever when users are typing and only handled by the lexer for completeness. Installation Instructions