postcss-less icon indicating copy to clipboard operation
postcss-less copied to clipboard

Reports incorrect node locations for files with comments containing single quote

Open nwalters512 opened this issue 3 years ago • 0 comments

I originally reported this problem in stylelint (https://github.com/stylelint/stylelint/issues/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?

nwalters512 avatar Aug 10 '21 20:08 nwalters512