On Wed, Aug 30, 2017 at 9:50 PM, Tim Mackinnon <tim@testit.works> wrote: > 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.
Excellent!!! > 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… Yes but we have to handle broken code then. Did you check how smart suggestions did it for code that compiled? > > 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