Skip to content

Commit

Permalink
feat(prefer-immutable-types): allow for changing suggestion messages
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaStevens committed Jun 10, 2024
1 parent 7b070b6 commit 5478188
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 51 deletions.
17 changes: 14 additions & 3 deletions docs/rules/prefer-immutable-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,15 @@ type Options = {
};

suggestions?: {
ReadonlyShallow?: Array<Array<{ pattern: string; replace: string }>>;
ReadonlyDeep?: Array<Array<{ pattern: string; replace: string }>>;
Immutable?: Array<Array<{ pattern: string; replace: string }>>;
ReadonlyShallow?: Array<
Array<{ pattern: string; replace: string; message?: string }>
>;
ReadonlyDeep?: Array<
Array<{ pattern: string; replace: string; message?: string }>
>;
Immutable?: Array<
Array<{ pattern: string; replace: string; message?: string }>
>;
};

overrides?: Array<{
Expand Down Expand Up @@ -297,14 +303,19 @@ const defaults = {
pattern:
"^([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*\\[\\])$",
replace: "readonly $1",
message: "Prepend with readonly.",
},
{
pattern: "^(Array|Map|Set)<(.+)>$",
replace: "Readonly$1<$2>",
message: "Use Readonly$1 instead of $1.",
},
],
[
{
pattern: "^(.+)$",
replace: "Readonly<$1>",
message: "Surround with Readonly.",
},
],
],
Expand Down
87 changes: 58 additions & 29 deletions src/rules/prefer-immutable-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ type FixerConfigRaw = {
replace: string;
};

type SuggestionsConfigRaw = Array<FixerConfigRaw & { message?: string }>;

type FixerConfigRawMap = Partial<
Record<
"ReadonlyShallow" | "ReadonlyDeep" | "Immutable",
Expand All @@ -103,7 +105,7 @@ type FixerConfigRawMap = Partial<
type SuggestionConfigRawMap = Partial<
Record<
"ReadonlyShallow" | "ReadonlyDeep" | "Immutable",
FixerConfigRaw[][] | undefined
SuggestionsConfigRaw[] | undefined
>
>;

Expand All @@ -112,7 +114,7 @@ type FixerConfig = {
replace: string;
};

type SuggestionsConfig = FixerConfig[];
type SuggestionsConfig = Array<FixerConfig & { message?: string }>;

/**
* The options this rule can take.
Expand Down Expand Up @@ -216,6 +218,7 @@ const suggestionsSchema: JSONSchema4 = {
properties: {
pattern: { type: "string" },
replace: { type: "string" },
message: { type: "string" },
},
additionalProperties: false,
},
Expand Down Expand Up @@ -286,14 +289,19 @@ const defaultOptions: RawOptions = [
pattern:
"^([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*\\[\\])$",
replace: "readonly $1",
message: "Prepend with readonly.",
},
{
pattern: "^(Array|Map|Set)<(.+)>$",
replace: "Readonly$1<$2>",
message: "Use Readonly$1 instead of $1.",
},
],
[
{
pattern: "^(.+)$",
replace: "Readonly<$1>",
message: "Surround with Readonly.",
},
],
],
Expand All @@ -314,6 +322,8 @@ const errorMessages = {
propertyImmutability:
'Property should have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
propertyModifier: "Property should have a readonly modifier.",
propertyModifierSuggestion: "Add readonly modifier.",
userDefined: "{{ message }}",
} as const;

/**
Expand Down Expand Up @@ -342,7 +352,7 @@ type Descriptor = RuleResult<

type AllFixers = {
fix: ReportFixFunction | null;
suggestionFixers: ReportFixFunction[] | null;
suggestionFixers: Array<{ fix: ReportFixFunction; message: string }> | null;
};

/**
Expand Down Expand Up @@ -394,14 +404,27 @@ function getConfiguredSuggestionFixers(
suggestionsConfigs: ReadonlyArray<SuggestionsConfig>,
) {
return suggestionsConfigs
.map((configs): NonNullable<Descriptor["fix"]> | null => {
const config = configs.find((c) => c.pattern.test(text));
if (config === undefined) {
return null;
}
return (fixer) =>
fixer.replaceText(node, text.replace(config.pattern, config.replace));
})
.map(
(
configs,
): { fix: NonNullable<Descriptor["fix"]>; message: string } | null => {
const config = configs.find((c) => c.pattern.test(text));
if (config === undefined) {
return null;
}
return {
fix: (fixer) =>
fixer.replaceText(
node,
text.replace(config.pattern, config.replace),
),
message:
config.message === undefined
? `Replace with: ${text.replace(config.pattern, config.replace)}`
: text.replace(config.pattern, config.message),
};
},
)
.filter(isDefined);
}

Expand Down Expand Up @@ -526,17 +549,16 @@ function getParameterTypeViolations(
}

if (parameterProperty && !param.readonly) {
const messageId = "propertyModifier";
const fix: NonNullable<Descriptor["fix"]> | null = (fixer) =>
fixer.insertTextBefore(param.parameter, "readonly ");

return {
node: param,
messageId,
messageId: "propertyModifier",
fix: fixerConfigs === false ? null : fix,
suggest: [
{
messageId,
messageId: "propertyModifierSuggestion",
fix,
},
],
Expand Down Expand Up @@ -596,9 +618,11 @@ function getParameterTypeViolations(
data,
fix,
suggest:
suggestionFixers?.map((fix) => ({
messageId,
data,
suggestionFixers?.map(({ fix, message }) => ({

Check warning on line 621 in src/rules/prefer-immutable-types.ts

View workflow job for this annotation

GitHub Actions / lint_js

'fix' is already declared in the upper scope on line 599 column 15
messageId: "userDefined",
data: {
message,
},
fix,
})) ?? null,
};
Expand Down Expand Up @@ -722,9 +746,11 @@ function getReturnTypeViolations(
data,
fix,
suggest:
suggestionFixers?.map((fix) => ({
messageId,
data,
suggestionFixers?.map(({ fix, message }) => ({

Check warning on line 749 in src/rules/prefer-immutable-types.ts

View workflow job for this annotation

GitHub Actions / lint_js

'fix' is already declared in the upper scope on line 729 column 15
messageId: "userDefined",
data: {
message,
},
fix,
})) ?? null,
},
Expand Down Expand Up @@ -795,9 +821,11 @@ function getReturnTypeViolations(
data,
fix,
suggest:
suggestionFixers?.map((fix) => ({
messageId,
data,
suggestionFixers?.map(({ fix, message }) => ({

Check warning on line 824 in src/rules/prefer-immutable-types.ts

View workflow job for this annotation

GitHub Actions / lint_js

'fix' is already declared in the upper scope on line 801 column 11
messageId: "userDefined",
data: {
message,
},
fix,
})) ?? null,
},
Expand Down Expand Up @@ -890,17 +918,16 @@ function checkVariable(
const fix: NonNullable<Descriptor["fix"]> | null = (fixer) =>
fixer.insertTextBefore(node.key, "readonly ");

const messageId = "propertyModifier";
return {
context,
descriptors: [
{
node,
messageId,
messageId: "propertyModifier",
fix: rawFixerConfig === undefined ? null : fix,
suggest: [
{
messageId,
messageId: "propertyModifierSuggestion",
fix,
},
],
Expand Down Expand Up @@ -995,9 +1022,11 @@ function checkVariable(
data,
fix,
suggest:
suggestionFixers?.map((fix) => ({
messageId,
data,
suggestionFixers?.map(({ fix, message }) => ({

Check warning on line 1025 in src/rules/prefer-immutable-types.ts

View workflow job for this annotation

GitHub Actions / lint_js

'fix' is already declared in the upper scope on line 1013 column 38
messageId: "userDefined",
data: {
message,
},
fix,
})) ?? null,
};
Expand Down
Loading

0 comments on commit 5478188

Please sign in to comment.