[Draft] Elixir 1.19 Support#3776
Conversation
|
Alright I missed a whole lot of bracketed operations |
It was introduced with Elixir 1.14 Tests: 3574 passing (1m 17s) 253 failing
8cace29 to
d5afbd8
Compare
It was introduced with Elixir 1.16 The Implementation I did feels very jank. Tests: 3785 passing (41.8s) 42 failing
# Conflicts: # build.gradle.kts
Do I understand what caused this change? No.
Is it perfect? No, some other instances of "NOT" broke because they
want to be snuggled in __block__
e.g.
This one wants __block__
cache/elixir-1.19.5/lib/elixir/lib/option_parser.ex:778
Enum.split_while(&(&1 not in ?0..?9))
While this one does not
cache/elixir-1.19.5/lib/elixir/lib/keyword.ex:1308
:lists.filter(fn {k, _} -> k not in keys end, keywords)
These tests would fail because the files they parse for testing no longer exist. I removed those and added other tests for new files that weren't tested before, resulting in a net increase of 3 tests.
|
hmmmmm, for unqualifiedNoArgumentCalls Especially this part
The ellipsis used to be a variable, but now they should be a function call?
|
Tests 3906 passing (52.3s) 19 failing
|
Handling ellipsis reduces failing tests to 19 3906 passing (52.3s) |
When capture expression:
- `not` is wrapped in __block__
When stabby lambda expression:
- `not` is NOT wrapped in block
see
KronicDeth#3776 (comment)
I can't figure out what should be done.
|
I got completely stuck trying to figure out the behavior of NOT. I added a few tests isolating cases where it should be wrapped in a block, and cases where it should not. It feels clear cut: in you find I tried to play around with /**
* Builds a block for stab bodies. Unlike `toBlock`, handles rearranging unary operations `not` and `!` and putting
* solitary `unquote_splicing` calls in blocks.
*
* @param quotedChildren
*/
@Contract(pure = true)
internal fun buildBlock(quotedChildren: List<OtpErlangObject>, metadata: OtpErlangList): OtpErlangObject =
when (quotedChildren.size) {
0 -> NIL
1 -> {
val quotedChild = quotedChildren.first()
// @see https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L588
if (Macro.isLocalCall(quotedChild)) {
// @see https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L547
when ((quotedChild as OtpErlangTuple).elementAt(0)) {
UNQUOTE_SPLICING ->
QuotableImpl.blockFunctionCall(quotedChildren, metadata)
else ->
quotedChild
}
} else {
quotedChild
}
}
else -> QuotableImpl.blockFunctionCall(quotedChildren, metadata)
}I tortured the when ((quotedChild as OtpErlangTuple).elementAt(0)) {
UNQUOTE_SPLICING ->
QuotableImpl.blockFunctionCall(quotedChildren, metadata)
EXCLAMATION_POINT, NOT -> {
if (node!!.elementType == ElixirTypes.STAB_BODY && node.treeParent.elementType !== ElixirTypes.STAB_OPERATION) {
QuotableImpl.blockFunctionCall(quotedChildren, otpErlangList())
} else {
quotedChild
}
}
else ->
quotedChild
}to no avail. The only pattern I could glean is that everything that is supposed to be wrapped with a block is a
It feels like I need to fully understand the grammar to figure out how to proceed but look at this thing https://github.com/KronicDeth/intellij-elixir/blob/main/src/org/elixir_lang/Elixir.bnf It scares me. It reflects off my smooth brain. |
|
Now I realize why I'm not understanding elixir.bnf I should've been reading this file instead https://github.com/elixir-lang/elixir/blob/main/lib/elixir/src/elixir_parser.yrl |
This `def operator?(:..//, 3)` would result in the following error: <unmatched expression> expected, got ',' I updated the lexer file to include this operator in the same way other three token operators are included, then regenerated the lexer. Regenerating the lexer resulting in some errors addressed below: Add stack.clear() to reset because Intellij showed a warning to add it manually to ElixirFlexLexer.reset because the generator can't do that automatically when regenerating. Wrap `myFixture.configureByFile(path)` in a command An error was being thrown to put undoable actions inside an executeCommand. The error advised checking https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/openapi/command/CommandProcessor.java
Otherwise, releaseQuoter this step would fail with an error.
This is definitely bad and doesn't address the root issue, but it's a starting point. At least it would serve as a conversation starter in a review.
This block of code threw a runtime exception while testing for some reason. The test passes, but it still throws an exception. From: `/macro.ex:0-10` ### Element Class Name ``` org.elixir_lang.psi.impl.ElixirUnmatchedUnqualifiedNoParenthesesCallImpl ``` com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: java.lang.Throwable: Cannot construct CallDefinitionClause from quote's enclosing macro call
|
It's funky because this error happens in a doc string :D |
This form seems to work alright. The txt file became different, however, so I skipped this test's checkResult step.
Turns out I can just look at the previous char and see it's an open brace. Tests: 3922 passing (50.9s) 8 failing
|
Thanks for the amazing work, and for the detailed updates! I'm having a look at this now we've released v23.0.0! |
|
I noticed while testing changes that autocomplete breaks for some reason when you add a call
This issue seems relevant #2980 |
|
Does the actual file have something that can't be parsed? I found this with #3770 (See the screenshots, the file has errors) |
|
No, it's a pretty clean file, no errors or anything. Here's a video example Screencast_20260211_094129.webm |
|
@KarimElsayad247 Thanks for all this work :) |
It was introduced with Elixir 1.14 Tests: 3574 passing (1m 17s) 253 failing
It was introduced with Elixir 1.16 The Implementation I did feels very jank. Tests: 3785 passing (41.8s) 42 failing
Do I understand what caused this change? No.
Is it perfect? No, some other instances of "NOT" broke because they
want to be snuggled in __block__
e.g.
This one wants __block__
cache/elixir-1.19.5/lib/elixir/lib/option_parser.ex:778
Enum.split_while(&(&1 not in ?0..?9))
While this one does not
cache/elixir-1.19.5/lib/elixir/lib/keyword.ex:1308
:lists.filter(fn {k, _} -> k not in keys end, keywords)
These tests would fail because the files they parse for testing no longer exist. I removed those and added other tests for new files that weren't tested before, resulting in a net increase of 3 tests.
Tests 3906 passing (52.3s) 19 failing
When capture expression:
- `not` is wrapped in __block__
When stabby lambda expression:
- `not` is NOT wrapped in block
see
KronicDeth#3776 (comment)
I can't figure out what should be done.
This `def operator?(:..//, 3)` would result in the following error: <unmatched expression> expected, got ',' I updated the lexer file to include this operator in the same way other three token operators are included, then regenerated the lexer. Regenerating the lexer resulting in some errors addressed below: Add stack.clear() to reset because Intellij showed a warning to add it manually to ElixirFlexLexer.reset because the generator can't do that automatically when regenerating. Wrap `myFixture.configureByFile(path)` in a command An error was being thrown to put undoable actions inside an executeCommand. The error advised checking https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/openapi/command/CommandProcessor.java
Otherwise, releaseQuoter this step would fail with an error.
This is definitely bad and doesn't address the root issue, but it's a starting point. At least it would serve as a conversation starter in a review.
This block of code threw a runtime exception while testing for some reason. The test passes, but it still throws an exception. From: `/macro.ex:0-10` ### Element Class Name ``` org.elixir_lang.psi.impl.ElixirUnmatchedUnqualifiedNoParenthesesCallImpl ``` com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments: java.lang.Throwable: Cannot construct CallDefinitionClause from quote's enclosing macro call
This form seems to work alright. The txt file became different, however, so I skipped this test's checkResult step.
Turns out I can just look at the previous char and see it's an open brace. Tests: 3922 passing (50.9s) 8 failing
…on-jps-plugin-fix-by-sh41













I'm building upon @joshuataylor 's branch https://github.com/joshuataylor/intellij-elixir/tree/feature/elixir-119
This is still a draft/WIP
The goal (for me) is to resolve all failing tests
Number of failing tests when compiling on 1.19 without any fixes: