Open mattBrzezinski opened 4 years ago
Labels should probably be bug
and parser
.
@ice1000 I haven't worked with Kotlin, could you point me to where these changes need to be made?
I found the compact function and the function function. I assume we want to be changing the nameIdentifier
here?
Also what are the easiest steps for testing changes? Rebuild the plugin, load it up and test? Or is there a quicker way?
EDIT: Just figure out testing can be done w/ gradle buildPlugin && gradle runIde
Also what are the easiest steps for testing changes? Rebuild the plugin, load it up and test? Or is there a quicker way?
gradlew runIde
will start an IDE with the latest plugin compiled, hope it's helpful
EDIT: Just saw your EDIT
You wanna update this code:
Spent some more time working on this and trying to learn more of Kotlin. An example function that I'm playing with is:
function Base.length()
return 0
end
The PSI Tree for is:
FILE(0,39)
JuliaStatementsImpl(STATEMENTS)(0,39)
JuliaFunctionImpl(FUNCTION)(0,39)
PsiElement(FUNCTION_KEYWORD)('function')(0,8)
PsiElement(SYM)('Base')(9,13)
PsiElement(DOT_SYM)('.')(13,14)
JuliaSymbolImpl(SYMBOL)(14,20)
PsiElement(SYM)('length')(14,20)
JuliaFunctionSignatureImpl(FUNCTION_SIGNATURE)(20,22)
PsiElement(LEFT_BRACKET)('(')(20,21)
PsiElement(RIGHT_BRACKET)(')')(21,22)
PsiElement(EOL)('\n')(22,23)
JuliaStatementsImpl(STATEMENTS)(27,36)
JuliaReturnExprImpl(RETURN_EXPR)(27,35)
PsiElement(RETURN_KEYWORD)('return')(27,33)
JuliaIntegerImpl(INTEGER)(34,35)
PsiElement(INT_LITERAL)('0')(34,35)
PsiElement(EOL)('\n')(35,36)
PsiElement(END_KEYWORD)('end')(36,39)
I cannot seem to be able to get access to the PSIElement Base
here, I've tried element.findElementAt(N)
but it always returns back function
regardless of N
. I've also tried accessing it via children
but that returns back the entire object itself.
Not sure how these elements are created but would we not always want to store the nameIdentifier
as the string following function
? i.e. just combine the following (if SYM
and DOT_SYM
are present).
PsiElement(SYM)('Base')(9,13)
PsiElement(DOT_SYM)('.')(13,14)
JuliaSymbolImpl(SYMBOL)(14,20)
Have you tried using the combination of .firstChild
/.nextSibling
?
Fuck!! I think I need to give this project a big refactoring. I got a lot of better practices on doing many things, and this project keeps using oldschool stupid way. Like, .children.filter { bla }
can be rewritten as .childrenWithLeaves.filter { bla }
given these utilities:
And that's gonna be a lazy stream operation.
Also .children
gives you an array with non-leaf PsiElement
s, which is the problem you're getting. .childrenWithLeaves
gives you leaves so that's what you need
And mostly we're filtering .children
's return value as well so why not use .childrenWithLeaves
in the very beginning
Man I just don't wanna open this project in my IDE. Why am I being lazy like this
I'm in a bad mood
I talk too much
Thanks! I should be able to have this issue wrapped up in the next while, got the element I needed now :)
Ignore the poor naming, this is my WIP commit:
https://github.com/mattBrzezinski/julia-intellij/commit/589bcf58f61441b9e342a8d84d900df3e30c4c4c
This seems like it should work, however when it does the replace it just deletes the function it's attempting to replace. Any ideas on how to debug this?
Any ideas on how to debug this?
Possible cause: your generated julia code doesn't parse
Oops forgot to include my example code to convert:
function Base.length()
return 0
end
Base.length() = return 0
function length()
return 0
end
With your comment addressed: https://github.com/JuliaEditorSupport/julia-intellij/commit/2a3ace65281606246b9268710080c2c177566df3
I'm having classes, will reply later
Any thoughts? Played around with it a bit more, but seem stuck.
Have you tried
Do you know how to use the debugger to evaluate an expression?
Could you check the output of JuliaTokenType.fromText(<the string you passed to `JuliaReplaceWithTextIntention`>)
? If it's null, you're producing the wrong string
I tried following the guide for setting up the Debugger here however it seems out of date.
Btw, kids
is a very lovely name. I like it, it's not poor at all
I tried following the guide for setting up the Debugger here however it seems out of date.
I mean, debug the plugin
I've just been using gradle runIde
to verify my changes.
Set a breakpoint in the IDE, right click "runIde" task in the gradle window and select "debug"
Then you'll be able to view the local variables while the IDE is running
You can evaluate expressions during debugging
Like this
Speaking of element.findElementAt(N)
, you shouldn't use it. You should find the DOT
token, and if it exists, return the token before it (.prevSibling
). This would be more robust because you may have functions that aren't extension functions
And if the .prevSibling
is a whitespace token, continue to find its prevSibling
I got many utilities for things like this in other projects such as intellij-pest or intellij-dtlc, feel free to copy them to the utils.kt
files
Got the debugger setup, the value is always what is expected. Either length
or Base.length
depending on which function is being analyzed.
Function I am trying to compact:
function Base.length()
return 0
end
Could you check the output of
JuliaTokenType.fromText(<the string you passed to `JuliaReplaceWithTextIntention`>)
? If it's null, you're producing the wrong string
Did you follow this?
This is from JuliaReplaceWithTextIntention()
new = "Base.length () = 0"
result = JuliaTokenType.fromText(new, project) # PsiWhiteSpace
Inside fromText()
createFileFromText(JuliaLanguage.INSTANCE, code) . code: " Base.length () = 0"
Ok got this working.... I had to change:
val values = kids.joinToString(separator="") { it.text }
To
val values = kids.joinToString(separator="") { it.text }.trim()
And it works how it's supposed to.
EDIT: I lied. It only works one way, from ordinary to compact. The opposite fails because of the PsiTree. I'll keep poking away at this, thanks for the help :)
Yay! (From someone who still don't wanna open his IDE)
Last piece to this is removing the overloaded function from being prepended to function
when converting from a compact to ordinary function. I cannot seem to find where this is being set.
PsiElement
has a delete
method. You may want your own JulaBlablablaQuickFix
class if you need
Sorry, I'm not following. Currently with the proposed CR above when you have:
Base.length() = 0
It will return:
Base.function Base.length()
return 0
end
I cannot find where Base.function
is being set. I can trace it back to fromText
, and everything seems fine. But after the break point on this function it just prepends Base.
to function
.
No
length() = 0
is parsed as a function, Base.
is a prefix out of the function
I believe that's the reason why you're getting the result
Or maybe you've deleted the wrong PsiElement
, so length() = 0
gets replaced with a function blabla
thing and the prefix Base.
is kept
Looking at the PsiTree for the above example. There are three elements to it (denoted with square brackets).
JuliaSymbolImpl(SYMBOL)
: Base
PsiElement(DOT_SYM)
: .
JuliaCompactFunctionImpl(COMPACT_FUNCTION)
: length() = return 0
[Base][.][length() = return 0]
When doing the replace I'm changing the length() = return 0
. Everything else is getting thrown away, with this call. I can't find where the prefix
is being set however.
I meant "prefix" by the combination of Base
and .
, two tokens
The first argument to the constructor of JuliaReplaceWithTextIntention
is the PsiElement
gets replaced by the action. You can change it from element
to something else
Yeah, I can't find where this is being set when converting from compact to an ordinary function.
Here we're just writing function ....
but I'm not understanding where Base.
is prepended to function
?
Here we're just writing function .... but I'm not understanding where Base. is prepended to function?
YOU ARE ON THE WRONG TRACK
The JuliaReplaceWithTextIntention
does two things:
Base.length() = 0
, but what gets passed to the compactFunction
method is length() = 0
PsiElement
, which is length() = 0
function ...
thingSo you get Base.function ...
If you have an overloaded function such as:
Converting this to a compact function results in:
Converting this back to an ordinary function results in:
However, converting from the block above results in the proper compact version of:
Properly this should just go back and forth between: