Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions packages/base/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Update `jsdoc/require-jsdoc` to loosen requirements for various kinds of symbols ([#433](https://github.com/MetaMask/eslint-config/pull/433))

- JSDoc is no longer required for arrow functions or function expressions which are values of object properties:

```typescript
const foo = {
// This arrow function is no longer required to be documented
bar: () => {
// ...
},
};

const foo = {
// This function expression is no longer required to be documented
bar: function () {
// ...
},
};
```

- JSDoc is no longer required for arrow functions or function expressions which are arguments to functions or methods:

```typescript
// This arrow function is no longer required to be documented
foo(() => {
// ...
});

// This function expression is no longer required to be documented
foo(function () {
// ...
}):
```

## [15.0.0]

### Changed
Expand All @@ -15,12 +51,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New things that now require documentation are:
- Arrow functions
- Class declarations
- TypeScript enum declarations
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's true that the base config did apparently require JSDoc for TypeScript symbols, that wasn't true in practice because the JSDoc plugin within the base config doesn't know about TypeScript.

- Function expressions
- TypeScript interface declarations
- Method definitions
- TypeScript type alias declarations
- TypeScript property signatures
- **BREAKING:** Convert various rules from `warn` to `error` ([#424](https://github.com/MetaMask/eslint-config/pull/424))
- The rules impacted are:
- `promise/no-callback-in-promise`
Expand Down
8 changes: 2 additions & 6 deletions packages/base/rules-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,13 @@
"error",
{
"require": {
"ArrowFunctionExpression": true,
"ClassDeclaration": true,
"FunctionDeclaration": true,
"FunctionExpression": true,
"MethodDefinition": true
},
"contexts": [
"TSInterfaceDeclaration",
"TSTypeAliasDeclaration",
"TSEnumDeclaration",
"TSPropertySignature"
":not(Property, NewExpression, CallExpression) > ArrowFunctionExpression",
":not(Property, NewExpression, CallExpression) > FunctionExpression"
]
}
],
Expand Down
15 changes: 9 additions & 6 deletions packages/base/src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -397,17 +397,20 @@ const rules = createConfig({
'error',
{
require: {
ArrowFunctionExpression: true,
// Classes
ClassDeclaration: true,
// Function declarations
FunctionDeclaration: true,
FunctionExpression: true,
// Methods
MethodDefinition: true,
},
contexts: [
'TSInterfaceDeclaration',
'TSTypeAliasDeclaration',
'TSEnumDeclaration',
'TSPropertySignature',
// Arrow functions that are not contained within plain objects or
// are not arguments to functions or methods
':not(Property, NewExpression, CallExpression) > ArrowFunctionExpression',
// Function expressions that are not contained within plain objects
// or are not arguments to functions or methods
':not(Property, NewExpression, CallExpression) > FunctionExpression',
],
},
],
Expand Down
76 changes: 76 additions & 0 deletions packages/typescript/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Update `jsdoc/require-jsdoc` to loosen requirements for various kinds of symbols ([#433](https://github.com/MetaMask/eslint-config/pull/433))

- JSDoc is no longer required for arrow functions or function expressions which are values of object properties:

```typescript
const foo = {
// This arrow function is no longer required to be documented
bar: () => {
// ...
},
};

const foo = {
// This function expression is no longer required to be documented
bar: function () {
// ...
},
};
```

- JSDoc is no longer required for arrow functions or function expressions which are arguments to functions or methods:

```typescript
// This arrow function is no longer required to be documented
foo(() => {
// ...
});

// This function expression is no longer required to be documented
foo(function () {
// ...
});
```

- JSDoc is no longer required for interfaces, type aliases, or enums that appear in `declare` blocks (even if they are exported):

```typescript
declare module "some-module" {
// This type is no longer required to be documented
type Bar = "baz";

// This interface is no longer required to be documented, even though it
// is exported
export interface Y {
// ...
}

// This enum is no longer required to be documented
enum Fooz {
Bar = "baz",
}
}
```

- JSDoc is no longer required for inline object types in return types:
```typescript
// This object type is no longer required to be documented
function foo(): {
bar: "baz";
} {
// ...
}
```

## [15.0.0]

### Changed
Expand All @@ -17,6 +83,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **BREAKING:** Update type import specifier rules ([#381](https://github.com/MetaMask/eslint-config/pull/381))
- `@typescript-eslint/consistent-type-imports` has been replaced with `import-x/consistent-type-specifier-style`
- The rule now prefers "top-level" type imports over inline. e.g. `import type { a } from 'x'` over `import { type a } from 'x'`
- **BREAKING:** Update `jsdoc/require-jsdoc` to require documentation for more things ([#394](https://github.com/MetaMask/eslint-config/pull/394))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changelog entry was missing when 15.0.0 was released. This should list TypeScript symbols for which documentation is required (not the changelog for the base config).

- New things that now require documentation are:
- Arrow functions
- Class declarations
- Function expressions
- Method definitions
- TypeScript enum declarations
- TypeScript interface declarations
- TypeScript type alias declarations
- TypeScript property signatures
- Disable `@typescript-eslint/no-unnecessary-type-arguments` ([#426](https://github.com/MetaMask/eslint-config/pull/426))
- We decided that "unnecessary" type arguments make types easier to read sometimes, so we should allow them.
- Disable `promise/valid-params` because it's redundant in type-checked projects ([#425](https://github.com/MetaMask/eslint-config/pull/425))
Expand Down
20 changes: 19 additions & 1 deletion packages/typescript/rules-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,25 @@
"jsdoc/require-example": "off",
"jsdoc/require-file-overview": "off",
"jsdoc/require-hyphen-before-param-description": "off",
"jsdoc/require-jsdoc": "error",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... this might be a breaking change. It seems that the typescript package has been overriding the base package :(

I'll have to double-check this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, so it was. It was overwritten by jsdoc.configs['flat/recommended-typescript-error'],.

That's fine, we can include this in v16 instead then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we still need a changelog update to reflect this

"jsdoc/require-jsdoc": [
"error",
{
"require": {
"ClassDeclaration": true,
"FunctionDeclaration": true,
"MethodDefinition": true
},
"contexts": [
":not(Property, NewExpression, CallExpression) > ArrowFunctionExpression",
":not(Property, NewExpression, CallExpression) > FunctionExpression",
":not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSInterfaceDeclaration",
":not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSTypeAliasDeclaration",
":not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSEnumDeclaration",
"TSInterfaceDeclaration TSPropertySignature",
"TSTypeAliasDeclaration TSPropertySignature"
]
}
],
"jsdoc/require-param": "error",
"jsdoc/require-param-description": "error",
"jsdoc/require-param-name": "error",
Expand Down
60 changes: 59 additions & 1 deletion packages/typescript/src/index.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
import { createConfig } from '@metamask/eslint-config';
import base, { createConfig } from '@metamask/eslint-config';
import * as resolver from 'eslint-import-resolver-typescript';
import importX from 'eslint-plugin-import-x';
import jsdoc from 'eslint-plugin-jsdoc';
// TODO: Look into why this doesn't resolve.
// eslint-disable-next-line import-x/no-unresolved
import typescript from 'typescript-eslint';

/**
* Collects all options for a given array-valued rule across one or more flat
* config arrays, excluding the leading severity element.
*
* ESLint flat config does not merge array-valued rules across config objects —
* a later config silently replaces earlier ones. This helper makes it possible
* to extend an upstream rule configuration rather than copy-pasting its options.
*
* @param {string} ruleName - The rule to collect options for.
* @param {import('eslint').Linter.Config[][]} configs - Flat config arrays to
* collect options from.
* @returns {unknown[]} The options from all matching rule entries, with the
* leading severity element omitted.
*/
function collectExistingRuleOptions(ruleName, configs) {
return configs.flat().flatMap((config) => {
const rule = config.rules?.[ruleName];
if (!Array.isArray(rule)) {
return [];
}
// Rule entries are ['error' | 'warn' | number, ...options].
// Skip the first element (severity) and collect the rest.
return rule.slice(1);
});
}

const baseJsdocRuleOptions = collectExistingRuleOptions(
'jsdoc/require-jsdoc',
base,
);

const config = createConfig({
name: '@metamask/eslint-config-typescript',

Expand Down Expand Up @@ -225,6 +256,33 @@ const config = createConfig({
// Use TypeScript types rather than JSDoc types.
'jsdoc/no-types': 'error',

// Extend rule defined in base config to require JSDoc for
// TypeScript-specific symbols.
'jsdoc/require-jsdoc': [
'error',
{
require: baseJsdocRuleOptions[0].require,
contexts: [
...baseJsdocRuleOptions[0].contexts,
Comment thread
mcmire marked this conversation as resolved.
// Type interfaces that are not defined within `declare` blocks,
// even if they are exported
':not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSInterfaceDeclaration',
// Type aliases that are not defined within `declare` blocks,
// even if they are exported
':not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSTypeAliasDeclaration',
// Enums that are not defined within `declare` blocks,
// even if they are exported
':not(TSModuleBlock, TSModuleBlock > ExportNamedDeclaration) > TSEnumDeclaration',
// Properties that are part of a named interface, not inline within a
// return type
'TSInterfaceDeclaration TSPropertySignature',
// Properties that are part of a named type alias, not inline within a
// return type
'TSTypeAliasDeclaration TSPropertySignature',
],
Comment thread
mcmire marked this conversation as resolved.
},
],

// These all conflict with `jsdoc/no-types`.
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
Expand Down
Loading