Skip to content

Add 0.5 comments support #109

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

Merged
merged 1 commit into from
Jan 11, 2018
Merged

Conversation

zbraniecki
Copy link
Collaborator

Implements a subset of projectfluent/fluent#58 required for limited Firefox x-channel compatibility across beta and stable.

@zbraniecki zbraniecki requested a review from stasm December 13, 2017 15:41
@zbraniecki zbraniecki force-pushed the 05-comments branch 4 times, most recently from e089369 to 82533eb Compare December 13, 2017 21:27
this.content = content;
}
}

export class Section extends Entry {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove Section from ast.js.

// 0 - comment
// 1 - group comment
// 2 - resource comment
isPeekNextLineComment(level = -1, oldStyle) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a temporary, but how about we rename oldStyle to zeroFourSyntax to make it explicit?

constructor(content) {
super();
this.type = 'Comment';
this.content = content;
}
}

export class Comment extends BaseComment {
constructor(content) {
super();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could pass content to super and avoid setting it in again in the constructor here.

this.resetPeek();
return true;
}
if (level === 0 && this.currentPeekIs(' ')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this could use a while loop where you decrement level in each pass.

}
}

export class Comment extends Entry {
export class BaseComment extends Entry {
constructor(content) {
super();
this.type = 'Comment';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BaseComment

ps.next();
if (ps.currentIs('#')) {
ps.next();
if (ps.currentIs('#')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps put this in a for loop iterating from 1 to level?

@@ -117,7 +115,8 @@ export default class FluentParser {
getEntry(ps) {
let comment;

if (ps.currentIs('/')) {
if (ps.currentIs('/') ||
(ps.currentIs('#') && (ps.peekCharIs('#') || ps.peekCharIs(' ')))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this peek one char ahead? Isn't a single # enough to branch into getComment?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, not.

key = Value
#word

should not branch into getComment since the comment starting code is "# "|"## "|"### ".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like that should throw a SyntaxError inside of getComment.

@@ -179,7 +226,7 @@ export default class FluentParser {
ps.expectChar(']');
ps.expectChar(']');

return new AST.Section(symb, comment);
return new AST.Section(symb);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSection should return a GroupComment with the section's comment or null (or undefined) if the comment is missing.

{
"type": "ResourceComment",
"annotations": [],
"content": "This is a resource wide comment\nIt's multiline"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there no span here?

this.name = name;
this.comment = comment;
this.type = 'GroupComment';
this.content = content;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also pass content to super() here and in ResourceComment.

return false;
}

let ptr = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other parts of this file, ptr is used to store a peek index. Perhaps rename this simply to i?

return this.getMessage(ps, comment);
}

if (comment) {
return comment;
}

if (ps.currentIs('[')) {
return this.getSection(ps);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we skip sections and return a GroupComment if comment is present?

return new Comment(content);
}

getSection(ps) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps rename to skipSection and don't return anything for it?

@@ -1,2 +0,0 @@
[ This is a broken section ]]
//~ ERROR E0003, pos 1, args "["
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should still throw a syntax error, no?

@@ -1 +0,0 @@
[[ This is a correct section ]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to still test that this parses alright, even if it parses to an empty AST at this point.

return `\n${comment}\n\n`;
}
case 'Comment':
return `\n${serializeComment(entry)}\n\n`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have a flag on the FluentSerializer class which starts as isFirstEntry = true and only add those leading \n if it's false.

Copy link
Contributor

@stasm stasm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's bring back other tests from fixtures_behavior. Also, I think it should be possible to avoid the two node === null checks. See my comments inline.

if (comment) {
return new AST.GroupComment(comment.content);
}
return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something, but if you bring back the previous order of ifs, so first test for [ and then test for identifier start, you could get away without this return null here and just let the code flow to the next if.

You could then remove the node === null check in withSpan and parse.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and just let the code flow to the next if.

Then it'll return regular Comment for old style comment that was attached to a section, instead of GroupComment.

You could then remove the node === null check in withSpan and parse.

That's crashes if getEntry returns null (it does when section doesn't have a comment in 0.4 style).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean something like this:

  getEntry(ps) {
    let comment;

    if (ps.currentIs('/') || ps.currentIs('#')) {
      comment = this.getComment(ps);

      // The Comment content doesn't include the trailing newline. Consume
      // this newline here to be ready for the next entry.  undefined stands
      // for EOF.
      ps.expectChar(ps.current() ? '\n' : undefined);
    }

    if (ps.currentIs('[')) {
      this.skipSection(ps);
      if (comment) {
        return new AST.GroupComment(comment.content);
      }
    }

    if (ps.isIDStart() && (!comment || comment.type === 'Comment')) {
      return this.getMessage(ps, comment);
    }

    if (comment) {
      return comment;
    }

    throw new ParseError('E0002');
  }

Then you never return null.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do in case the file is:

[[ This is a section ]]

which is one of our tests :(

What do you prefer here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point, thanks. Let's keep the tests.

Can we at least remove the node === null check in withSpans? I think we only return null from getEntry which isn't decorated with withSpans because it handles spans in an own custom way.

}

for (const entry of resource.body) {
if (entry.types !== 'Junk' || this.withJunk) {
parts.push(this.serializeEntry(entry));
this.hasEntries = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid setting it in every pass of the loop and only do it if hasEntries is false.

return `\n${serializeGroupComment(entry)}\n\n`;
case 'ResourceComment':
if (this.hasEntries) {
return `${serializeResourceComment(entry)}\n\n`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should start with \n.

continue;
}

if (entry.type === 'Comment' && entry.oldStyle && entries.length === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see oldStyle anywhere else in the PR.

Copy link
Contributor

@stasm stasm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @zbraniecki, this looks great! Please don't remove any test fixtures in this PR. The parser should still report syntax errors on broken sections.

if (comment) {
return new AST.GroupComment(comment.content);
}
return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point, thanks. Let's keep the tests.

Can we at least remove the node === null check in withSpans? I think we only return null from getEntry which isn't decorated with withSpans because it handles spans in an own custom way.

@zbraniecki zbraniecki merged commit 92e77df into projectfluent:master Jan 11, 2018
@zbraniecki zbraniecki mentioned this pull request Jan 26, 2018
4 tasks
@zbraniecki zbraniecki deleted the 05-comments branch May 14, 2018 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants