I’m looking for some feedback on the usage of RBParser>>#parseMethod:onError:.
I am looking at ways of improving the way we edit code - and making things work (as least for me - but maybe for everyone) a bit more like IntelliJ where they have some great code operations and very good keyboard support. We are certainly close, but at times feel a bit clumsy - which is a shame as we have far better infrastructure to support equivalent features. So I thought I would have a go. Anyway - step one (which I think I’ve come close on), was to teach senders/implementors to look at the AST so you don’t have to highlight exactly what you want to search on - instead it can infer from your cursor… however my next step was to improve how we can select code to ease refactoring, bracketing etc… So this is where I’ve hit a few issues which strike me as confusing (and I will freely admit that I’m not a mega compiler, parser guy - but I”d love to be…). The following code blows up strangely - and I think its very confusing… as it turns out that #parseMethod:onError: doesn’t work like I would expect (and this is where I’m after feedback). It seems that the onError block does’t actually exit parsing - it takes the result and then keeps running with something in an intermediate state - thus below, when I try to parse with a subset of the code (and maybe this is a naive approach to handle the case when you start typing code in the middle of a complete method, but want to parse it before you’ve entered a final “.” or “;”) - you actually end up with an AST that is using all of the source code because the result of the error block is then applied inside the executing method. I find this very confusing? There are no comments in this code, and for me the convention of onError: is to execute in isolation unless there is a parameter that the error block can interact with. I’m wondering if those with more knowledge agree - or if it is my naiveté? This was my original code (and yes it needs refactoring a bit) - but anyway: bestNodeInTextAreaOnError: aBlock "Find the best node in the editor text area at the current pointer location" | ast start stop node source | start := self textArea startIndex. stop := self textArea stopIndex. source := self textArea string trimRight. ast := RBParser parseMethod: source onError: [ RBParser parseExpression: source onError: [ source := (source truncateTo: stop) trimRight. RBParser parseMethod: source onError: [ RBParser parseExpression: source onError: aBlock ]]]. stop > source size ifTrue: [ start := stop := source size]. node := ast bestNodeFor: (start to: stop). node ifNil: aBlock. ^node But this doesn’t work, as “ast” is incorrect when it parses truncated source. To work around what I’m seeing I have to instead extract the ast assignment to another method that looks as follows - but to me it seems very unexpected to have the explicit ^ statements? agressivelyParse: source at: loc "Find the best node in the editor text area at the current pointer location" ^RBParser parseMethod: source onError: [ ^RBParser parseExpression: source onError: [ | reducedSrc | reducedSrc := (source truncateTo: loc) trimRight. ^RBParser parseMethod: reducedSrc onError: [ ^RBParser parseExpression: reducedSrc onError: [^nil]]]]. This forces the ast to be exactly what I would expect - but I’m wondering if I am missing something obvious? Tim