Repository: ember-cli/eslint-plugin-ember
Pull request #1792 (2023-03-01 16:06:33)

[gjs] Return original diagnostic if transformed line matches original line in glimmer preprocessor
This PR will fix part of the issue in #1659 where line/col numbers are reported as 0:0. The bug was typically caused by a few things:
1. the `token` had matches on multiple lines
2. multiple diagnostic messages mapped to the same line because `token` was too generic

May not fix every single instance, but will be a general improvement.

hmajoros: newly added test fails without my fix with this error:
```
 ● line/col numbers should be correct › line and col should be correct

    expect(received).toStrictEqual(expected) // deep equality

    - Expected  - 4
    + Received  + 4

    @@ -1,10 +1,10 @@
      Object {
    -   "column": 28,
    -   "endColumn": 64,
    -   "endLine": 13,
    -   "line": 13,
    +   "column": 0,
    +   "endColumn": 36,
    +   "endLine": 0,
    +   "line": 0,
        "message": "Don't use Ember's array prototype extensions",
        "messageId": "main",
        "nodeType": "Literal",
        "ruleId": "ember/no-array-prototype-extensions",
        "severity": 2,

      230 |     expect(resultErrors).toHaveLength(2);
      231 |
    > 232 |     expect(resultErrors[0]).toStrictEqual({
          |                             ^
      233 |       column: 28,
      234 |       endColumn: 64,
      235 |       endLine: 13,

      at Object.toStrictEqual (tests/lib/rules-preprocessor/gjs-gts-processor-test.js:232:29)
```

Patch:
diff --git a/lib/preprocessors/glimmer.js b/lib/preprocessors/glimmer.js
index 00308529..86a6cad8 100644
--- a/lib/preprocessors/glimmer.js
+++ b/lib/preprocessors/glimmer.js
@@ -104,6 +104,11 @@ function mapRange(messages, filename) {
   const originalLines = original.split('\n');
 
   return flattened.map((message) => {
+    if (lines[message.line - 1] === originalLines[message.line - 1]) {
+      // original line and transformed line match exactly. return original diagnostic message
+      return message;
+    }
+
     const line = lines[message.line - 1];
     const token = line.slice(message.column - 1, message.endColumn - 1);
 


Test patch:
diff --git a/tests/lib/rules-preprocessor/gjs-gts-processor-test.js b/tests/lib/rules-preprocessor/gjs-gts-processor-test.js
index 3c226710..2a953654 100644
--- a/tests/lib/rules-preprocessor/gjs-gts-processor-test.js
+++ b/tests/lib/rules-preprocessor/gjs-gts-processor-test.js
@@ -36,6 +36,8 @@ function initESLint(options) {
       extends: ['plugin:ember/recommended'],
       rules: {
         'no-undef': 'error',
+        'ember/no-get': 'off',
+        'ember/no-array-prototype-extensions': 'error',
       },
     },
     ...options,
@@ -197,3 +199,58 @@ describe('template-vars', () => {
     }
   });
 });
+
+describe('line/col numbers should be correct', () => {
+  it('line and col should be correct', async () => {
+    const eslint = initESLint();
+    const code = `
+    import Component from '@glimmer/component';
+    import { get } from '@ember/object';
+    
+    export default class MyComponent extends Component {
+      constructor() {
+        super(...arguments);
+      }
+
+      get truncatedList() {
+        return get(
+          this.truncatedList,
+          this.isImgList ? 'firstObject.attributes.firstObject' : 'firstObject'
+        );
+      }
+
+      <template>
+        <div>this is necessary to break the tests</div>
+      </template>
+    }
+    `;
+    const results = await eslint.lintText(code, { filePath: 'my-component.gjs' });
+
+    const resultErrors = results.flatMap((result) => result.messages);
+    expect(resultErrors).toHaveLength(2);
+
+    expect(resultErrors[0]).toStrictEqual({
+      column: 28,
+      endColumn: 64,
+      endLine: 13,
+      line: 13,
+      message: "Don't use Ember's array prototype extensions",
+      messageId: 'main',
+      nodeType: 'Literal',
+      ruleId: 'ember/no-array-prototype-extensions',
+      severity: 2,
+    });
+
+    expect(resultErrors[1]).toStrictEqual({
+      column: 67,
+      endColumn: 80,
+      endLine: 13,
+      line: 13,
+      message: "Don't use Ember's array prototype extensions",
+      messageId: 'main',
+      nodeType: 'Literal',
+      ruleId: 'ember/no-array-prototype-extensions',
+      severity: 2,
+    });
+  });
+});