Skip to content
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

feat(eslint-plugin): add key-spacing rule extension for interface & type declarations #6211

Merged
merged 43 commits into from Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
eb02b4d
🚧 key-spacing for interface on default settings
coyotte508 Dec 14, 2022
6d78fe8
🚧 Support type literals as welll
coyotte508 Dec 14, 2022
259a3ca
🚧 Add full typing for the options
coyotte508 Dec 14, 2022
8f32b5d
🚧 Add 'mode' param
coyotte508 Dec 14, 2022
34bb6d8
🐛 Fix index signatures
coyotte508 Dec 15, 2022
ecaafa7
✨ Support classes
coyotte508 Dec 15, 2022
b17665b
🩹 fixes
coyotte508 Dec 15, 2022
18bb8ab
✅ Add tests on mode, multiLine, singleLine
coyotte508 Dec 15, 2022
4113478
🏷️ Allow options.multiline.align to be an object
coyotte508 Dec 15, 2022
5e951ba
🎨 Use ast utils to locate last character before token
coyotte508 Dec 15, 2022
b12c530
✨ Support comments in-between properties
coyotte508 Dec 15, 2022
729e642
✅ Add test cases for nested type declarations & multiline type annota…
coyotte508 Dec 15, 2022
d93c1a7
✨ Autofix for non-aligned values
coyotte508 Dec 15, 2022
ee519e3
✨ Autofix for aligned values
coyotte508 Dec 15, 2022
bc3b5d2
✏️
coyotte508 Dec 15, 2022
eebb18f
🚨
coyotte508 Dec 15, 2022
179aca2
🐛 Support optional ? token
coyotte508 Dec 15, 2022
db2d1bd
✅ Add tests with class property assignments
coyotte508 Dec 15, 2022
dbe502d
📝 Add documentation on key-spacing
coyotte508 Dec 15, 2022
8d5d3dd
🎨 Use .at() to access last element of array
coyotte508 Dec 15, 2022
af0a489
✅ Fix tests
coyotte508 Dec 15, 2022
c18b929
fixup! ✅ Fix tests
coyotte508 Dec 15, 2022
37eecdc
✅ Add some coverage
coyotte508 Dec 16, 2022
75ac325
Merge branch 'main' into key-spacing
coyotte508 Dec 16, 2022
1b62445
🐛 Fix edge case in determining aligned groups
coyotte508 Dec 16, 2022
4b0759c
⚡️ Use Array.concat instead of .push(...)
coyotte508 Dec 16, 2022
6d61144
🎨 Improve readability
coyotte508 Jan 24, 2023
47156ec
🎨 Use tempate literals in tests
coyotte508 Jan 24, 2023
ae33b9b
✅ Add test with anonymous types
coyotte508 Jan 24, 2023
722e092
✅ Add test with quoted keys
coyotte508 Jan 24, 2023
301731b
➕ Add grapheme-splitter to deal with emojis
coyotte508 Jan 24, 2023
9eaebb2
✅ Add test case for multiline comments
coyotte508 Jan 24, 2023
ee6d9bc
🚨 Remove 'in' statements, reduce amount of null-assertions
coyotte508 Jan 24, 2023
dbc6a91
✅ Add test case for properties without type annotation or assignments
coyotte508 Jan 24, 2023
b1033ef
✅ Add wacky test cases
coyotte508 Jan 24, 2023
a7a5b2c
✅ Add coverage
coyotte508 Jan 24, 2023
cb5876e
✅ Add coverage, again
coyotte508 Jan 24, 2023
2787762
✅ Add coverage, again
coyotte508 Jan 24, 2023
79d8ec0
✅ Add coverage when align is an object, but align.on is missing
coyotte508 Jan 24, 2023
2092487
KeyTypeNodeWithTypeAnnotation
JoshuaKGoldberg Jan 24, 2023
23036de
Merge branch 'main' into key-spacing
JoshuaKGoldberg Jan 24, 2023
e483407
Merge branch 'main' into key-spacing
JoshuaKGoldberg Jan 24, 2023
0184de9
Extract to shared helper
JoshuaKGoldberg Jan 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/eslint-plugin/package.json
Expand Up @@ -49,6 +49,7 @@
"@typescript-eslint/utils": "5.46.1",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"grapheme-splitter": "^1.0.4",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
Expand Down
30 changes: 27 additions & 3 deletions packages/eslint-plugin/src/rules/key-spacing.ts
@@ -1,9 +1,24 @@
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import GraphemeSplitter from 'grapheme-splitter';

import * as util from '../util';
import { getESLintCoreRule } from '../util/getESLintCoreRule';

let splitter: GraphemeSplitter;
function isASCII(value: string): boolean {
return /^[\u0020-\u007f]*$/u.test(value);
}
function getStringLength(value: string): number {
if (isASCII(value)) {
return value.length;
}

splitter ??= new GraphemeSplitter();

return splitter.countGraphemes(value);
}
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved

const baseRule = getESLintCoreRule('key-spacing');

export type Options = util.InferOptionsTypeFromRule<typeof baseRule>;
Expand Down Expand Up @@ -35,6 +50,14 @@ export default util.createRule<Options, MessageIds>({
const sourceCode = context.getSourceCode();
const baseRules = baseRule.create(context);

/**
* @returns the column of the position after converting all unicode characters in the line to 1 char length
*/
function adjustedColumn(position: TSESTree.Position): number {
const line = position.line - 1; // position.line is 1-indexed
return getStringLength(sourceCode.lines[line].slice(0, position.column));
}

/**
* Starting from the given a node (a property.key node here) looks forward
* until it finds the last token before a colon punctuator and returns it.
Expand Down Expand Up @@ -241,11 +264,12 @@ export default util.createRule<Options, MessageIds>({

for (const node of group) {
if (isKeyTypeNode(node)) {
const keyEnd = adjustedColumn(getKeyLocEnd(node));
alignColumn = Math.max(
alignColumn,
align === 'colon'
? getKeyLocEnd(node).column + expectedWhitespaceBeforeColon
: getKeyLocEnd(node).column +
? keyEnd + expectedWhitespaceBeforeColon
: keyEnd +
':'.length +
expectedWhitespaceAfterColon +
expectedWhitespaceBeforeColon,
Expand All @@ -261,7 +285,7 @@ export default util.createRule<Options, MessageIds>({
align === 'colon'
? node.typeAnnotation!
: node.typeAnnotation!.typeAnnotation;
const difference = toCheck.loc.start.column - alignColumn;
const difference = adjustedColumn(toCheck.loc.start) - alignColumn;

if (difference) {
context.report({
Expand Down
40 changes: 40 additions & 0 deletions packages/eslint-plugin/tests/rules/key-spacing.test.ts
Expand Up @@ -41,6 +41,20 @@ let x: {
},
{
code: `
let x: {
a: number;
"𐌘": string;
[𐌘]: Date;
"🌷": "bar", // 2 code points
"🎁": "baz", // 2 code points
"🇮🇳": "qux", // 4 code points
"🏳️‍🌈": "xyz", // 6 code points
};
`,
options: [{ align: 'value' }],
},
{
code: `
interface X {
a: number;
abc: string; c: number;
Expand Down Expand Up @@ -394,6 +408,32 @@ let x: {
},
{
code: `
let x: {
a: number;
"🌷": "bar", // 2 code points
"🎁": "baz", // 2 code points
"🇮🇳": "qux", // 4 code points
"🏳️‍🌈": "xyz", // 6 code points
[𐌘]: string
"𐌘": string
};
`,
output: `
let x: {
a: number;
"🌷": "bar", // 2 code points
"🎁": "baz", // 2 code points
"🇮🇳": "qux", // 4 code points
"🏳️‍🌈": "xyz", // 6 code points
[𐌘]: string
"𐌘": string
};
`,
options: [{ align: 'value' }],
errors: [{ messageId: 'missingValue' }],
},
{
code: `
class X {
a: number;
abc: string
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Expand Up @@ -7908,6 +7908,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==

grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==

gray-matter@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798"
Expand Down