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: improve rule schemas, add test to validate schemas, add tooling to generate schema types #6899

Merged
merged 18 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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 .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ jobs:
'eslint-plugin-tslint',
'parser',
'repo-tools',
'rule-schema-to-typescript-types',
'scope-manager',
'type-utils',
'typescript-estree',
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@
"@types/marked": "*",
"@types/natural-compare-lite": "^1.4.0",
"@types/prettier": "*",
"@typescript-eslint/rule-schema-to-typescript-types": "5.58.0",
"cross-fetch": "*",
"jest-specific-snapshot": "*",
"json-schema": "*",
"markdown-table": "^3.0.2",
"marked": "^4.0.15",
Expand Down
39 changes: 18 additions & 21 deletions packages/eslint-plugin/src/rules/array-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,30 +105,27 @@ export default util.createRule<Options, MessageIds>({
errorStringGenericSimple:
"Array type using '{{readonlyPrefix}}{{type}}[]' is forbidden for non-simple types. Use '{{className}}<{{type}}>' instead.",
},
schema: {
$defs: {
arrayOption: {
enum: ['array', 'generic', 'array-simple'],
schema: [
{
$defs: {
arrayOption: {
enum: ['array', 'generic', 'array-simple'],
},
},
},
prefixItems: [
{
properties: {
default: {
$ref: '#/$defs/arrayOption',
description: 'The array type expected for mutable cases...',
},
readonly: {
$ref: '#/$defs/arrayOption',
description:
'The array type expected for readonly cases. If omitted, the value for `default` will be used.',
},
properties: {
default: {
$ref: '#/items/0/$defs/arrayOption',
description: 'The array type expected for mutable cases...',
bradzacher marked this conversation as resolved.
Show resolved Hide resolved
},
readonly: {
$ref: '#/items/0/$defs/arrayOption',
description:
'The array type expected for readonly cases. If omitted, the value for `default` will be used.',
},
type: 'object',
},
],
type: 'array',
},
type: 'object',
},
],
},
defaultOptions: [
{
Expand Down
66 changes: 31 additions & 35 deletions packages/eslint-plugin/src/rules/ban-ts-comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,45 +39,41 @@ export default util.createRule<[Options], MessageIds>({
tsDirectiveCommentDescriptionNotMatchPattern:
'The description for the "@ts-{{directive}}" directive must match the {{format}} format.',
},
schema: {
$defs: {
directiveConfigSchema: {
oneOf: [
{
type: 'boolean',
default: true,
},
{
enum: ['allow-with-description'],
},
{
type: 'object',
properties: {
descriptionFormat: { type: 'string' },
schema: [
{
$defs: {
directiveConfigSchema: {
oneOf: [
{
type: 'boolean',
default: true,
},
},
],
{
enum: ['allow-with-description'],
},
{
type: 'object',
properties: {
descriptionFormat: { type: 'string' },
},
},
],
},
},
},
prefixItems: [
{
properties: {
'ts-expect-error': {
$ref: '#/$defs/directiveConfigSchema',
},
'ts-ignore': { $ref: '#/$defs/directiveConfigSchema' },
'ts-nocheck': { $ref: '#/$defs/directiveConfigSchema' },
'ts-check': { $ref: '#/$defs/directiveConfigSchema' },
minimumDescriptionLength: {
type: 'number',
default: defaultMinimumDescriptionLength,
},
properties: {
'ts-expect-error': { $ref: '#/items/0/$defs/directiveConfigSchema' },
'ts-ignore': { $ref: '#/items/0/$defs/directiveConfigSchema' },
'ts-nocheck': { $ref: '#/items/0/$defs/directiveConfigSchema' },
'ts-check': { $ref: '#/items/0/$defs/directiveConfigSchema' },
minimumDescriptionLength: {
type: 'number',
default: defaultMinimumDescriptionLength,
},
additionalProperties: false,
},
],
type: 'array',
},
type: 'object',
additionalProperties: false,
},
],
},
defaultOptions: [
{
Expand Down
58 changes: 42 additions & 16 deletions packages/eslint-plugin/src/rules/ban-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as util from '../util';
type Types = Record<
string,
| null
| false
| boolean
| string
| {
message: string;
Expand Down Expand Up @@ -34,9 +34,9 @@ function stringifyNode(
}

function getCustomMessage(
bannedType: null | string | { message?: string; fixWith?: string },
bannedType: null | true | string | { message?: string; fixWith?: string },
): string {
if (bannedType == null) {
if (bannedType == null || bannedType === true) {
bradzacher marked this conversation as resolved.
Show resolved Hide resolved
return '';
}

Expand Down Expand Up @@ -128,24 +128,50 @@ export default util.createRule<Options, MessageIds>({
},
schema: [
{
$defs: {
banConfig: {
oneOf: [
{
type: 'null',
description: 'Bans the type with the default message',
},
{
enum: [false],
description:
'Un-bans the type (useful when paired with `extendDefaults`)',
},
{
enum: [true],
description: 'Bans the type with the default message',
},
{
type: 'string',
description: 'Bans the type with a custom message',
},
{
type: 'object',
description: 'Bans a type',
properties: {
message: {
type: 'string',
description: 'Custom error message',
},
fixWith: {
type: 'string',
description: 'Type to autofix replace with.',
},
},
additionalProperties: false,
},
],
},
},
type: 'object',
properties: {
types: {
type: 'object',
additionalProperties: {
oneOf: [
{ type: 'null' },
{ type: 'boolean' },
{ type: 'string' },
{
type: 'object',
properties: {
message: { type: 'string' },
fixWith: { type: 'string' },
},
additionalProperties: false,
},
],
$ref: '#/items/0/$defs/banConfig',
},
},
extendDefaults: {
Expand Down
89 changes: 42 additions & 47 deletions packages/eslint-plugin/src/rules/explicit-member-accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,6 @@ type MessageIds =
| 'missingAccessibility'
| 'addExplicitAccessibility';

const accessibilityLevel = {
oneOf: [
{
const: 'explicit',
description: 'Always require an accessor.',
},
{
const: 'no-public',
description: 'Require an accessor except when public.',
},
{
const: 'off',
description: 'Never check whether there is an accessor.',
},
],
};

export default util.createRule<Options, MessageIds>({
name: 'explicit-member-accessibility',
meta: {
Expand All @@ -62,41 +45,53 @@ export default util.createRule<Options, MessageIds>({
'Public accessibility modifier on {{type}} {{name}}.',
addExplicitAccessibility: "Add '{{ type }}' accessibility modifier",
},
schema: {
$defs: {
accessibilityLevel,
},
prefixItems: [
{
type: 'object',
properties: {
accessibility: { $ref: '#/$defs/accessibilityLevel' },
overrides: {
type: 'object',
properties: {
accessors: { $ref: '#/$defs/accessibilityLevel' },
constructors: { $ref: '#/$defs/accessibilityLevel' },
methods: { $ref: '#/$defs/accessibilityLevel' },
properties: { $ref: '#/$defs/accessibilityLevel' },
parameterProperties: {
$ref: '#/$defs/accessibilityLevel',
},
schema: [
{
$defs: {
accessibilityLevel: {
oneOf: [
{
enum: ['explicit'],
description: 'Always require an accessor.',
},

additionalProperties: false,
},
ignoredMethodNames: {
type: 'array',
items: {
type: 'string',
{
enum: ['no-public'],
description: 'Require an accessor except when public.',
},
{
enum: ['off'],
description: 'Never check whether there is an accessor.',
},
],
},
},
type: 'object',
properties: {
accessibility: { $ref: '#/items/0/$defs/accessibilityLevel' },
overrides: {
type: 'object',
properties: {
accessors: { $ref: '#/items/0/$defs/accessibilityLevel' },
constructors: { $ref: '#/items/0/$defs/accessibilityLevel' },
methods: { $ref: '#/items/0/$defs/accessibilityLevel' },
properties: { $ref: '#/items/0/$defs/accessibilityLevel' },
parameterProperties: {
$ref: '#/items/0/$defs/accessibilityLevel',
},
},

additionalProperties: false,
},
ignoredMethodNames: {
type: 'array',
items: {
type: 'string',
},
},
additionalProperties: false,
},
],
type: 'array',
},
additionalProperties: false,
},
],
},
defaultOptions: [{ accessibility: 'explicit' }],
create(context, [option]) {
Expand Down