Skip to content

Commit

Permalink
Merge branch 'master' into prefer-regexp-exec-autofix
Browse files Browse the repository at this point in the history
  • Loading branch information
phaux committed Mar 22, 2021
2 parents e41cf62 + 7ad343b commit c141be1
Show file tree
Hide file tree
Showing 7 changed files with 388 additions and 84 deletions.
2 changes: 2 additions & 0 deletions packages/eslint-plugin/docs/rules/unbound-method.md
Expand Up @@ -4,6 +4,8 @@ Warns when a method is used outside of a method call.

Class functions don't preserve the class scope when passed as standalone variables.

If your function does not access `this`, [you can annotate it with `this: void`](https://www.typescriptlang.org/docs/handbook/2/functions.html#declaring-this-in-a-function), or consider using an arrow function instead.

## Rule Details

Examples of **incorrect** code for this rule
Expand Down
93 changes: 75 additions & 18 deletions packages/eslint-plugin/src/rules/member-delimiter-style.ts
@@ -1,4 +1,5 @@
import {
TSESLint,
TSESTree,
AST_NODE_TYPES,
} from '@typescript-eslint/experimental-utils';
Expand All @@ -11,6 +12,9 @@ type TypeOptions = {
delimiter?: Delimiter;
requireLast?: boolean;
};
type TypeOptionsWithType = TypeOptions & {
type: string;
};
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
type BaseOptions = {
multiline?: TypeOptions;
Expand All @@ -29,6 +33,20 @@ type MessageIds =
| 'unexpectedSemi'
| 'expectedComma'
| 'expectedSemi';
type LastTokenType = TSESTree.Token;

interface MakeFixFunctionParams {
optsNone: boolean;
optsSemi: boolean;
lastToken: LastTokenType;
missingDelimiter: boolean;
lastTokenLine: string;
isSingleLine: boolean;
}

type MakeFixFunctionReturnType =
| ((fixer: TSESLint.RuleFixer) => TSESLint.RuleFix)
| null;

const definition = {
type: 'object',
Expand All @@ -54,6 +72,47 @@ const definition = {
additionalProperties: false,
};

const isLastTokenEndOfLine = (token: string, line: string): boolean => {
const positionInLine = line.indexOf(token);

return positionInLine === line.length - 1;
};

const makeFixFunction = ({
optsNone,
optsSemi,
lastToken,
missingDelimiter,
lastTokenLine,
isSingleLine,
}: MakeFixFunctionParams): MakeFixFunctionReturnType => {
// if removing is the action but last token is not the end of the line
if (
optsNone &&
!isLastTokenEndOfLine(lastToken.value, lastTokenLine) &&
!isSingleLine
) {
return null;
}

return (fixer: TSESLint.RuleFixer): TSESLint.RuleFix => {
if (optsNone) {
// remove the unneeded token
return fixer.remove(lastToken);
}

const token = optsSemi ? ';' : ',';

if (missingDelimiter) {
// add the missing delimiter
return fixer.insertTextAfter(lastToken, token);
}

// correct the current delimiter
return fixer.replaceText(lastToken, token);
};
};

export default util.createRule<Options, MessageIds>({
name: 'member-delimiter-style',
meta: {
Expand Down Expand Up @@ -127,7 +186,7 @@ export default util.createRule<Options, MessageIds>({
*/
function checkLastToken(
member: TSESTree.TypeElement,
opts: TypeOptions,
opts: TypeOptionsWithType,
isLast: boolean,
): void {
/**
Expand All @@ -147,10 +206,14 @@ export default util.createRule<Options, MessageIds>({
const lastToken = sourceCode.getLastToken(member, {
includeComments: false,
});

if (!lastToken) {
return;
}

const sourceCodeLines = sourceCode.getLines();
const lastTokenLine = sourceCodeLines[lastToken?.loc.start.line - 1];

const optsSemi = getOption('semi');
const optsComma = getOption('comma');
const optsNone = getOption('none');
Expand Down Expand Up @@ -193,22 +256,14 @@ export default util.createRule<Options, MessageIds>({
},
},
messageId,
fix(fixer) {
if (optsNone) {
// remove the unneeded token
return fixer.remove(lastToken);
}

const token = optsSemi ? ';' : ',';

if (missingDelimiter) {
// add the missing delimiter
return fixer.insertTextAfter(lastToken, token);
}

// correct the current delimiter
return fixer.replaceText(lastToken, token);
},
fix: makeFixFunction({
optsNone,
optsSemi,
lastToken,
missingDelimiter,
lastTokenLine,
isSingleLine: opts.type === 'single-line',
}),
});
}
}
Expand Down Expand Up @@ -239,7 +294,9 @@ export default util.createRule<Options, MessageIds>({
node.type === AST_NODE_TYPES.TSInterfaceBody
? interfaceOptions
: typeLiteralOptions;
const opts = isSingleLine ? typeOpts.singleline : typeOpts.multiline;
const opts = isSingleLine
? { ...typeOpts.singleline, type: 'single-line' }
: { ...typeOpts.multiline, type: 'multi-line' };

members.forEach((member, index) => {
checkLastToken(member, opts ?? {}, index === members.length - 1);
Expand Down
39 changes: 29 additions & 10 deletions packages/eslint-plugin/src/rules/object-curly-spacing.ts
Expand Up @@ -63,7 +63,7 @@ export default createRule<Options, MessageIds>({
* @param token The token to use for the report.
*/
function reportNoBeginningSpace(
node: TSESTree.TSTypeLiteral,
node: TSESTree.TSMappedType | TSESTree.TSTypeLiteral,
token: TSESTree.Token,
): void {
const nextToken = context
Expand All @@ -89,7 +89,7 @@ export default createRule<Options, MessageIds>({
* @param token The token to use for the report.
*/
function reportNoEndingSpace(
node: TSESTree.TSTypeLiteral,
node: TSESTree.TSMappedType | TSESTree.TSTypeLiteral,
token: TSESTree.Token,
): void {
const previousToken = context
Expand All @@ -115,7 +115,7 @@ export default createRule<Options, MessageIds>({
* @param token The token to use for the report.
*/
function reportRequiredBeginningSpace(
node: TSESTree.TSTypeLiteral,
node: TSESTree.TSMappedType | TSESTree.TSTypeLiteral,
token: TSESTree.Token,
): void {
context.report({
Expand All @@ -137,7 +137,7 @@ export default createRule<Options, MessageIds>({
* @param token The token to use for the report.
*/
function reportRequiredEndingSpace(
node: TSESTree.TSTypeLiteral,
node: TSESTree.TSMappedType | TSESTree.TSTypeLiteral,
token: TSESTree.Token,
): void {
context.report({
Expand All @@ -162,7 +162,7 @@ export default createRule<Options, MessageIds>({
* @param last The last token to check (should be closing brace)
*/
function validateBraceSpacing(
node: TSESTree.TSTypeLiteral,
node: TSESTree.TSMappedType | TSESTree.TSTypeLiteral,
first: TSESTree.Token,
second: TSESTree.Token | TSESTree.Comment,
penultimate: TSESTree.Token | TSESTree.Comment,
Expand All @@ -175,7 +175,10 @@ export default createRule<Options, MessageIds>({

const openingCurlyBraceMustBeSpaced =
options.arraysInObjectsException &&
secondType === AST_NODE_TYPES.TSIndexSignature
[
AST_NODE_TYPES.TSMappedType,
AST_NODE_TYPES.TSIndexSignature,
].includes(secondType)
? !options.spaced
: options.spaced;

Expand All @@ -197,15 +200,19 @@ export default createRule<Options, MessageIds>({
isClosingBracketToken(penultimate)) ||
(options.objectsInObjectsException &&
isClosingBraceToken(penultimate));
const penultimateType =
shouldCheckPenultimate &&
sourceCode.getNodeByRangeIndex(penultimate.range[0])!.type;
const penultimateType = shouldCheckPenultimate
? sourceCode.getNodeByRangeIndex(penultimate.range[0])!.type
: undefined;

const closingCurlyBraceMustBeSpaced =
(options.arraysInObjectsException &&
penultimateType === AST_NODE_TYPES.TSTupleType) ||
(options.objectsInObjectsException &&
penultimateType === AST_NODE_TYPES.TSTypeLiteral)
penultimateType !== undefined &&
[
AST_NODE_TYPES.TSMappedType,
AST_NODE_TYPES.TSTypeLiteral,
].includes(penultimateType))
? !options.spaced
: options.spaced;

Expand Down Expand Up @@ -246,6 +253,18 @@ export default createRule<Options, MessageIds>({
const rules = baseRule.create(context);
return {
...rules,
TSMappedType(node: TSESTree.TSMappedType): void {
const first = sourceCode.getFirstToken(node)!;
const last = sourceCode.getLastToken(node)!;
const second = sourceCode.getTokenAfter(first, {
includeComments: true,
})!;
const penultimate = sourceCode.getTokenBefore(last, {
includeComments: true,
})!;

validateBraceSpacing(node, first, second, penultimate, last);
},
TSTypeLiteral(node: TSESTree.TSTypeLiteral): void {
if (node.members.length === 0) {
return;
Expand Down

0 comments on commit c141be1

Please sign in to comment.