Skip to content

Reports incorrect node locations for files with comments containing single quote #163

Description

@nwalters512

I originally reported this problem in stylelint (stylelint/stylelint#5438), but eventually determined it was caused by postcss-less.

  • Node Version: 14.17.0
  • NPM Version: 6.14.13
  • postcss Version: 8.3.5
  • postcss-less Version: master

LESS

This example may look kind of contrived, but it's based on many real-world examples in our code (long, rambling explanations that happen to single quotes). This is as simplified as I could get it.

a {
  // '
  color: pink;
}

/** ' */

JavaScript

Here is the test I added to test/parser/comments.test.js to reproduce the problem:

test('handles single quotes in comments', (t) => {
  const less = `a {\n  // '\n  color: pink;\n}\n\n/** ' */`;

  const root = parse(less);

  const [ruleNode, commentNode] = root.nodes;

  t.is(ruleNode.type, 'rule');
  t.is(commentNode.type, 'comment');

  const [innerCommentNode, declarationNode] = ruleNode.nodes;

  t.is(innerCommentNode.type, 'comment');
  t.is(declarationNode.type, 'decl');

  t.is(declarationNode.source.start.line, 3);
  t.is(declarationNode.source.start.column, 3);
  t.is(declarationNode.source.end.line, 3);
  t.is(declarationNode.source.end.column, 14);

  t.is(nodeToString(root), less);
});

All assertions about declarationNode.source.*.line fail.

Expected Behavior

I would expect that the declaration node for color: pink to be marked as starting and ending on line 3.

Actual Behavior

The declaration node for color: pink is marked as starting and ending on line 2. As you can see from the original LESS document, this is incorrect; line 2 is a comment.

How can we reproduce the behavior?

If you add the above test to test/parser/comments.test.js and run npm run test -- test/parser/comments.test.js, you can observe the test failing:

> ava "test/parser/comments.test.js"


  handles single quotes in comments

  test/parser/comments.test.js:198

   197:                                                
   198:   t.is(declarationNode.source.start.line, 3);  
   199:   t.is(declarationNode.source.start.column, 3);

  Difference:

  - 2
  + 3

  › test/parser/comments.test.js:198:5

  ─

  1 test failed

Potential fix

I spent a good deal of time trying to develop a fix for this, but I haven't yet figured out a way to work around the fact that the inline-comment node creates a new tokenizer in the middle of parsing (source). My current thinking is to try to do some kind of post-processing on the tree in the parse function - does that seem like a reasonable approach to you?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions