-
Notifications
You must be signed in to change notification settings - Fork 79
Indentation/Whitespace in 0.7 #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've given this a glance, and I realize that I'm not as good a reviewer as stas hoped.
Big picture, can you rebase and target the zeroseven branch for this?
I've tried my best to go through the test changes, and the fixtures_structure ones I agree with.
I have some open questions on the behavior ones, and I didn't go through the whole test suite to see if there are more changes that I'd expect. There is at least one in indent.ftl, though.
fluent-syntax/src/ftlstream.js
Outdated
@@ -5,10 +5,11 @@ import { ParseError } from "./errors"; | |||
import { includes } from "./util"; | |||
|
|||
const INLINE_WS = [" ", "\t"]; | |||
const ANY_WS = [" ", "\t", "\r", "\n"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if you want to do this as part of this patch or not, but \t
is a regular char now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, cool! updated!
@@ -8,7 +8,7 @@ key2 = { { foo } } | |||
# } | |||
|
|||
key4 = { { foo } | |||
# ~ERROR E0003, pos 93, args "}" | |||
# ~ERROR E0003, pos 96, args "}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is weird. Why is #
OK in a placeable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not. The error is exactly on that character:
! E0003 on line 2:
| key4 = { { foo }
| # ~ERROR E0003, pos 93, args "}"
… ^----- Expected token: "}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so we dove into this with Axel. The reason this annotation stops at 96 now, is that the test infra removes the # ~ERROR
comment, so the parser continues and stops on the first character of # key5
two \n
's later which is 96 :)
@@ -8,7 +8,6 @@ a } | |||
|
|||
key3 = { a | |||
} | |||
# ~ERROR E0003, pos 36, args "}" | |||
|
|||
key4 = { | |||
{ a }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key4 error should also go away, I think.
1eaae0a
to
3755c5b
Compare
19508ea
to
c9e3c8d
Compare
c9e3c8d
to
9f1858c
Compare
Updated to your feedback! Thank you! :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @zbraniecki, for this PR! I think this is pretty close. The one big thing which I see here is that this PR doesn't support unindented placeables yet. I would also like to see all other reference fixtures copied into fluent-syntax/test/fixtures_reference
to make sure we're not missing anything else.
fluent-syntax/src/ftlstream.js
Outdated
|
||
if (this.currentPeekIs("*")) { | ||
if (def) { | ||
this.skipToPeek(); | ||
this.peek(); | ||
} | ||
|
||
if (this.currentPeekIs("[") && !this.peekCharIs("[")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive-by comment: is !this.peekCharIs("[")
a remnant of sections?
fluent-syntax/src/ftlstream.js
Outdated
@@ -4,11 +4,12 @@ import { ParserStream } from "./stream"; | |||
import { ParseError } from "./errors"; | |||
import { includes } from "./util"; | |||
|
|||
const INLINE_WS = [" ", "\t"]; | |||
const INLINE_WS = [" "]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since space is the only valid inline blank character, maybe just define it as:
const INLINE_WS = " "
?
fluent-syntax/src/parser.js
Outdated
ps.peekInlineWS(); | ||
if (ps.isPeekNextLineVariantStart()) { | ||
ps.peekBlank(); | ||
if (ps.currentPeek() === "*" || ps.currentPeek() === "[") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer to stick to the existing abstraction in form of isPeekNextLineVariantStart
here, even if it means calling peekBlankInline
first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this is a bit more tricky. The situation is unusual in this place because we want to try to get a variant list, but if that doesn't work, we bail back to the {
and go for getPattern
.
That means that if we transition to use isPeekNextLineVariantStart
I need to complicate it to not always skip.
fluent-syntax/src/ftlstream.js
Outdated
return true; | ||
} | ||
|
||
this.resetPeek(); | ||
return false; | ||
} | ||
|
||
isPeekNextLineValue() { | ||
isPeekNextLineValue(skipToPeek = true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that all isPeek...
methods skip by default now, maybe we should call them simply isNextLineValue()
etc?
Perhaps it's just me, but I often forget which methods skip and which do not. Making it a bit explicit would certainly make the code easier to follow for me:
isPeekNextLineValue({skip}) { ... }
Then, we could use it everywhere in a self-documenting fashion:
ps.isNextLineValue({skip: true})
ps.isNextLineValue({skip: false})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, I'd make this change to all isSomething
methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous in turn means that now not all of them skip, most of them do, but one of them doesn't, which makes it inconsistent as well :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't understand your comment. Do you agree that making the skipping behavior explicit in the parameter passed into all isSomething
methods helps understand the reader what the method will do? Like this:
ps.isPeekNextLineValue({skip: true})
ps.isPeekNextLineValue({skip: false})
I'd get rid of Peek
in the names of these methods to make them shorter. Which gives:
ps.isNextLineValue({skip: true})
ps.isNextLineValue({skip: false})
fluent-syntax/src/parser.js
Outdated
} | ||
|
||
return this.getPattern(ps); | ||
} | ||
|
||
getVariantList(ps) { | ||
ps.expectChar("{"); | ||
ps.skipInlineWS(); | ||
ps.skipBlank(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to ensure at least one line break before moving on to parsing variants. Same as you do in getExpression
.
fluent-syntax/src/parser.js
Outdated
|
||
let ch; | ||
while ((ch = ps.current())) { | ||
|
||
// The end condition for getPattern's while loop is a newline | ||
// which is not followed by a valid pattern continuation. | ||
if (ch === "\n" && !ps.isPeekNextLineValue()) { | ||
if (ch === "\n" && !ps.isPeekNextLineValue(false)) { | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't break here before first checking if there's an unindented placeable on the next line. The following snippets are valid Fluent 0.7:
key1 =
{ placeable}
key2 =
{ $selector ->
*[one] One
}
The reference parser has a number of fixtures for testing this in select_indent.ftl and variants_indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might require a different logic than the one provided by isPeekNextLineValue
. If so, my other comment about parametrizing {skip: true}
might not hold anymore. I'd still rename isPeekSomething
to isSomething
, though.
Updated to review, and copied reference tests. :) I was even able to remove a couple from the blacklist! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thanks for a quick turn-around! I'd like to get a clarification about your answer to my {skip: true}
suggestion before approving this PR. Otherwise, this is ready to land.
fluent-syntax/src/ftlstream.js
Outdated
return true; | ||
} | ||
|
||
this.resetPeek(); | ||
return false; | ||
} | ||
|
||
isPeekNextLineValue() { | ||
isPeekNextLineValue(skipToPeek = true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't understand your comment. Do you agree that making the skipping behavior explicit in the parameter passed into all isSomething
methods helps understand the reader what the method will do? Like this:
ps.isPeekNextLineValue({skip: true})
ps.isPeekNextLineValue({skip: false})
I'd get rid of Peek
in the names of these methods to make them shorter. Which gives:
ps.isNextLineValue({skip: true})
ps.isNextLineValue({skip: false})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay, thanks, @zbraniecki!
* Indentation/Whitespace in 0.7 * Apply feedback * Apply 2nd round of feedback
This PR supersets #272. It covers all of the 0.7 indentation changes I could find, aligning the parser with the grammar.mjs as close I dared.
I think all the resulting test changes make sense as well. :)