Skip to content

Commit

Permalink
fix type aware
Browse files Browse the repository at this point in the history
just patch ts.sys
typescript-eslint has handling for a lot of scenarios for file changes and project changes etc
use mts extension to keep same offsets
  • Loading branch information
patricklx committed Nov 14, 2023
1 parent 90d1fc4 commit db50e78
Show file tree
Hide file tree
Showing 10 changed files with 756 additions and 519 deletions.
524 changes: 10 additions & 514 deletions lib/parsers/gjs-gts-parser.js

Large diffs are not rendered by default.

518 changes: 518 additions & 0 deletions lib/parsers/transform.js

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions lib/parsers/ts-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const fs = require('node:fs');
const ts = require('typescript');
const { transformForLint } = require('./transform');
const babel = require('@babel/core');
const { replaceRange } = require('./transform');

module.exports.patchTs = function patchTs() {
const readDirectory = ts.sys.readDirectory;
ts.sys.readDirectory = function (...args) {
const results = readDirectory.call(this, ...args);
return results.map((f) => f.replace(/\.gts$/, '.ts'));
};
ts.sys.fileExists = function (fileName) {
return fs.existsSync(fileName.replace(/\.mts$/, '.gts')) || fs.existsSync(fileName);
};
ts.sys.readFile = function (fname) {
let fileName = fname;
let content = '';
try {
content = fs.readFileSync(fileName).toString();
} catch {
fileName = fileName.replace(/\.mts$/, '.gts');
content = fs.readFileSync(fileName).toString();
}
if (fileName.endsWith('.gts')) {
content = transformForLint(content).output;
}
if (fileName.endsWith('.ts') || fileName.endsWith('.gts')) {
content = replaceExtensions(content);
}
return content;
};
};

function replaceExtensions(code) {
let jsCode = code;
const babelParseResult = babel.parse(jsCode, {
parserOpts: { ranges: true, plugins: ['typescript'] },
});
const length = jsCode.length;
for (const b of babelParseResult.program.body) {
if (b.type === 'ImportDeclaration' && b.source.value.endsWith('.gts')) {
const value = b.source.value.replace(/\.gts$/, '.mts');
const strWrapper = jsCode[b.source.start];
jsCode = replaceRange(jsCode, b.source.start, b.source.end, strWrapper + value + strWrapper);
}
}
if (length !== jsCode.length) {
throw new Error('bad replacement');
}
return jsCode;
}

module.exports.replaceExtensions = replaceExtensions;
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
]
},
"dependencies": {
"@babel/core": "^7.23.3",
"@babel/eslint-parser": "^7.22.15",
"@ember-data/rfc395-data": "^0.0.4",
"@glimmer/syntax": "^0.85.12",
Expand All @@ -83,7 +84,8 @@
"lodash.camelcase": "^4.3.0",
"lodash.kebabcase": "^4.1.1",
"requireindex": "^1.2.0",
"snake-case": "^3.0.3"
"snake-case": "^3.0.3",
"typescript": "^5.2.2"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6",
Expand Down Expand Up @@ -112,8 +114,7 @@
"npm-run-all": "^4.1.5",
"prettier": "^3.0.3",
"release-it": "^16.2.1",
"sort-package-json": "^2.6.0",
"typescript": "^5.2.2"
"sort-package-json": "^2.6.0"
},
"peerDependencies": {
"eslint": ">= 8"
Expand Down
5 changes: 5 additions & 0 deletions tests/lib/rules-preprocessor/ember_ts/bar.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const fortyTwoFromGTS = '42';

<template>
{{fortyTwoFromGTS}}
</template>
1 change: 1 addition & 0 deletions tests/lib/rules-preprocessor/ember_ts/baz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const fortyTwoFromTS = '42';
14 changes: 14 additions & 0 deletions tests/lib/rules-preprocessor/ember_ts/foo.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { fortyTwoFromGTS } from './bar.gts';
import { fortyTwoFromTS } from './baz.ts';

export const fortyTwoLocal = '42';

const helloWorldFromTS = fortyTwoFromTS[0] === '4' ? 'hello' : 'world';
const helloWorldFromGTS = fortyTwoFromGTS[0] === '4' ? 'hello' : 'world';
const helloWorld = fortyTwoLocal[0] === '4' ? 'hello' : 'world';
//
<template>
{{helloWorldFromGTS}}
{{helloWorldFromTS}}
{{helloWorld}}
</template>
76 changes: 76 additions & 0 deletions tests/lib/rules-preprocessor/gjs-gts-parser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -761,4 +761,80 @@ describe('multiple tokens in same file', () => {
expect(resultErrors[2].message).toBe("'bar' is not defined.");
expect(resultErrors[2].line).toBe(17);
});

it('lints while being type aware', async () => {
const eslint = new ESLint({
ignore: false,
useEslintrc: false,
plugins: { ember: plugin },
overrideConfig: {
root: true,
env: {
browser: true,
},
plugins: ['ember'],
extends: ['plugin:ember/recommended'],
overrides: [
{
files: ['**/*.gts'],
parser: 'eslint-plugin-ember/gjs-gts-parser',
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
extraFileExtensions: ['.gts'],
},
extends: [
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:ember/recommended',
],
rules: {
'no-trailing-spaces': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
},
},
{
files: ['**/*.ts'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
extraFileExtensions: ['.gts'],
},
extends: [
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:ember/recommended',
],
rules: {
'no-trailing-spaces': 'error',
},
},
],
rules: {
quotes: ['error', 'single'],
semi: ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'lines-between-class-members': 'error',
'no-undef': 'error',
'no-unused-vars': 'error',
'ember/no-get': 'off',
'ember/no-array-prototype-extensions': 'error',
'ember/no-unused-services': 'error',
},
},
});

const results = await eslint.lintFiles(['**/*.gts', '**/*.ts']);

const resultErrors = results.flatMap((result) => result.messages);
expect(resultErrors).toHaveLength(3);

expect(resultErrors[0].message).toBe("Use 'String#startsWith' method instead."); // Actual result is "Unsafe member access [0] on an `any` value."
expect(resultErrors[0].line).toBe(6);

expect(resultErrors[1].line).toBe(7);
expect(resultErrors[1].message).toBe("Use 'String#startsWith' method instead.");

expect(resultErrors[2].line).toBe(8);
expect(resultErrors[2].message).toBe("Use 'String#startsWith' method instead.");
});
});
4 changes: 2 additions & 2 deletions tests/lib/rules-preprocessor/tsconfig.eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"strictNullChecks": true
},
"include": [
"*"
]
"**/*"
],
}
72 changes: 72 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@
json5 "^2.2.3"
semver "^6.3.1"

"@babel/core@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.3.tgz#5ec09c8803b91f51cc887dedc2654a35852849c9"
integrity sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==
dependencies:
"@ampproject/remapping" "^2.2.0"
"@babel/code-frame" "^7.22.13"
"@babel/generator" "^7.23.3"
"@babel/helper-compilation-targets" "^7.22.15"
"@babel/helper-module-transforms" "^7.23.3"
"@babel/helpers" "^7.23.2"
"@babel/parser" "^7.23.3"
"@babel/template" "^7.22.15"
"@babel/traverse" "^7.23.3"
"@babel/types" "^7.23.3"
convert-source-map "^2.0.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.3"
semver "^6.3.1"

"@babel/eslint-parser@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz#263f059c476e29ca4972481a17b8b660cb025a34"
Expand All @@ -68,6 +89,16 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"

"@babel/generator@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.3.tgz#86e6e83d95903fbe7613f448613b8b319f330a8e"
integrity sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==
dependencies:
"@babel/types" "^7.23.3"
"@jridgewell/gen-mapping" "^0.3.2"
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"

"@babel/helper-annotate-as-pure@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
Expand Down Expand Up @@ -146,6 +177,17 @@
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.20"

"@babel/helper-module-transforms@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1"
integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==
dependencies:
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-module-imports" "^7.22.15"
"@babel/helper-simple-access" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.20"

"@babel/helper-optimise-call-expression@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e"
Expand Down Expand Up @@ -226,6 +268,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==

"@babel/parser@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.3.tgz#0ce0be31a4ca4f1884b5786057cadcb6c3be58f9"
integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==

"@babel/plugin-proposal-class-properties@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
Expand Down Expand Up @@ -375,6 +422,22 @@
debug "^4.1.0"
globals "^11.1.0"

"@babel/traverse@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b"
integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==
dependencies:
"@babel/code-frame" "^7.22.13"
"@babel/generator" "^7.23.3"
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-function-name" "^7.23.0"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/parser" "^7.23.3"
"@babel/types" "^7.23.3"
debug "^4.1.0"
globals "^11.1.0"

"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.3":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
Expand All @@ -384,6 +447,15 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"

"@babel/types@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.3.tgz#d5ea892c07f2ec371ac704420f4dcdb07b5f9598"
integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==
dependencies:
"@babel/helper-string-parser" "^7.22.5"
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"

"@bcoe/v8-coverage@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
Expand Down

0 comments on commit db50e78

Please sign in to comment.