Skip to content

Commit

Permalink
feat(check-types, no-undefined-types, valid-types): Add `struct…
Browse files Browse the repository at this point in the history
…uredTags` setting to control whether the type and namepath portions should be checked for validity and whether such portions are required, and to let user-defined "namepath-defining" tags be added to defined types. Closes #481

BREAKING CHANGE:

Drops `checkSeesForNamepaths` setting. Use `{settings: {jsdoc: {structuredTags: {name: 'namepath', type: false, required: ['name'],}}}}` instead.

Also:
1. Clarifies in more cases where a problem is specific to the mode or not
2. Reports simultaneous invalid name *and* type errors
3. `typdef` now requires `allowEmptyNamepaths: false,` to report empty names (as with other tags)
4. Requires a name for `event` and `external` (and `extends` in jsdoc mode); some tweaking of other tags per docs
  • Loading branch information
brettz9 committed Jul 19, 2020
1 parent 69fd79d commit 89f2ad0
Show file tree
Hide file tree
Showing 17 changed files with 1,458 additions and 384 deletions.
43 changes: 43 additions & 0 deletions .README/README.md
Expand Up @@ -380,6 +380,49 @@ key nor the value will be reported. Thus in `check-types`, this fact can
be used to allow both `object` and `Object` if one has a `preferredTypes`
key `object: 'Object'` and `Object: 'object'`.

### `structuredTags`

An object indicating tags whose types and names/namepaths (whether defining or
referencing namepaths) will be checked, subject to configuration. If the tags
have predefined behavior or `allowEmptyNamepaths` behavior, this option will
override that behavior for any specified tags, though this option can also be
used for tags without predefined behavior. Its keys are tag names and its
values are objects with the following optional properties:
- `name` - String set to one of the following:
- `"text"` - When a name is present, plain text will be allowed in the
name position (non-whitespace immediately after the tag and whitespace),
e.g., in `@throws This is an error`, "This" would normally be the name,
but "text" allows non-name text here also. This is the default.
- `"namepath-defining"` - As with `namepath-referencing`, but also
indicates the tag adds a namepath to definitions, e.g., to prevent
`no-undefined-types` from reporting references to that namepath.
- `"namepath-referencing"` - This will cause any name position to be
checked to ensure it is a valid namepath. You might use this to ensure
that tags which normally allow free text, e.g., `@see` will instead
require a namepath.
- `false` - This will disallow any text in the name position.
- `type`:
- `true` - Allows valid types within brackets. This is the default.
- `false` - Explicitly disallows any brackets or bracketed type. You
might use this with `@throws` to suggest that only free form text
is being input or with `@augments` (for jsdoc mode) to disallow
Closure-style bracketed usage along with a required namepath.
- `required` - Array of one of the following (defaults to an empty array,
meaning none are required):
- One or both of the following strings (if both are included, then both
are required):
- `"name"` - Indicates that a name position is required (not just that
if present, it is a valid namepath). You might use this with `see`
to insist that a value (or namepath, depending on the `name` value)
is always present.
- `"type"` - Indicates that the type position (within curly brackets)
is required (not just that if present, it is a valid type). You
might use this with `@throws` or `@typedef` which might otherwise
normally have their types optional. See the type groups 3-5 above.
- `"typeOrName"` - Must have either type (e.g., `@throws {aType}`) or
name (`@throws Some text`); does not require that both exist but
disallows just an empty tag.

## Advanced

### AST and Selectors
Expand Down
6 changes: 5 additions & 1 deletion .README/rules/check-types.md
Expand Up @@ -120,13 +120,17 @@ Boolean | **boolean** | **boolean** | `(true) instanceof Boolean` -> **`false`**
Number | **number** | **number** | `(41) instanceof Number` -> **`false`**
String | **string** | **string** | `("test") instanceof String` -> **`false`**

If you define your own tags and don't wish their bracketed portions checked
for types, you can use `settings.jsdoc.structuredTags` with a tag `type` of
`false`.

|||
|---|---|
|Context|everywhere|
|Tags|`augments`, `class`, `constant`, `enum`, `implements`, `member`, `module`, `namespace`, `param`, `property`, `returns`, `throws`, `type`, `typedef`, `yields`|
|Aliases|`constructor`, `const`, `extends`, `var`, `arg`, `argument`, `prop`, `return`, `exception`, `yield`|
|Closure-only|`package`, `private`, `protected`, `public`, `static`|
|Options|`noDefaults`, `exemptTagContexts`, `unifyParentAndChildTypeChecks`|
|Settings|`preferredTypes`, `mode`|
|Settings|`preferredTypes`, `mode`, `structuredTags`|

<!-- assertions checkTypes -->
7 changes: 6 additions & 1 deletion .README/rules/no-undefined-types.md
Expand Up @@ -36,6 +36,11 @@ Also note that if there is an error [parsing](https://github.com/jsdoctypeparser
types for a tag, the function will silently ignore that tag, leaving it to
the `valid-types` rule to report parsing errors.

If you define your own tags, you can use `settings.jsdoc.structuredTags`
to indicate that a tag's `name` is "namepath-defining" (and should prevent
reporting on use of that namepath elsewhere) and/or that a tag's `type` is
`false` (and should not be checked for types).

#### Options

An option object may have the following key:
Expand All @@ -51,6 +56,6 @@ An option object may have the following key:
|Aliases|`constructor`, `const`, `extends`, `var`, `arg`, `argument`, `prop`, `return`, `exception`, `yield`|
|Closure-only|`package`, `private`, `protected`, `public`, `static`|
|Options|`definedTypes`|
|Settings|`preferredTypes`, `mode`|
|Settings|`preferredTypes`, `mode`, `structuredTags`|

<!-- assertions noUndefinedTypes -->
26 changes: 16 additions & 10 deletions .README/rules/valid-types.md
Expand Up @@ -31,15 +31,15 @@ e.g., `@modifies`):
The following tags have their name/namepath portion (the non-whitespace
text after the tag name) checked:

1. Name(path)-defining tags requiring namepath: `@external`, `@host`,
`@name`, `@typedef`, and `@template` (TypeScript/Closure only);
`@param` (`@arg`, `@argument`) and `@property`
1. Name(path)-defining tags requiring namepath: `@event`, `@callback`,
`@external`, `@host`, `@name`, `@typedef`, and `@template`
(TypeScript/Closure only); `@param` (`@arg`, `@argument`) and `@property`
(`@prop`) also fall into this category, but while this rule will check
their namepath validity, we leave the requiring of the name portion
to the rules `require-param-name` and `require-property-name`,
respectively.
1. Name(path)-defining tags (which may have value without namepath or their
namepath can be expressed elsewhere on the block): `@event`, `@callback`,
namepath can be expressed elsewhere on the block):
`@class`, `@constructor`, `@constant`, `@const`, `@function`, `@func`,
`@method`, `@interface` (TypeScript tag only), `@member`, `@var`,
`@mixin`, `@namespace`, `@module` (module paths are not planned for
Expand Down Expand Up @@ -70,24 +70,30 @@ text after the tag name) checked:
allow `#`, `.`, or `~` at the end (which is not allowed at the end of
normal paths).

If you define your own tags, `settings.jsdoc.structuredTags` will allow
these custom tags to be checked, with the name portion of tags checked for
valid namepaths (based on the tag's `name` value), their type portions checked
for valid types (based on the tag's `type` value), and either portion checked
for presence (based on `false` `name` or `type` values or their `required`
value). See the setting for more details.

#### Options

- `allowEmptyNamepaths` (default: true) - Set to `false` to bulk disallow
empty name paths with namepath groups 2 and 4 (these might often be
expected to have an accompanying name path, though they have some
indicative value without one; these may also allow names to be defined
in another manner elsewhere in the block)
- `checkSeesForNamepaths` (default: false) - Set this to `true` to insist
that `@see` only use name paths (the tag is normally permitted to
allow other text)
in another manner elsewhere in the block); you can use
`settings.jsdoc.structuredTags` with the `required` key set to "name" if you
wish to require name paths on a tag-by-tag basis.

|||
|---|---|
|Context|everywhere|
|Tags|For name only unless otherwise stated: `alias`, `augments`, `borrows`, `callback`, `class` (for name and type), `constant` (for name and type), `enum` (for type), `event`, `external`, `fires`, `function`, `implements` (for type), `interface`, `lends`, `listens`, `member` (for name and type), `memberof`, `memberof!`, `mixes`, `mixin`, `modifies`, `module` (for name and type), `name`, `namespace` (for name and type), `param` (for name and type), `property` (for name and type), `returns` (for type), `see` (optionally for name), `this`, `throws` (for type), `type` (for type), `typedef` (for name and type), `yields` (for type)|
|Aliases|`extends`, `constructor`, `const`, `host`, `emits`, `func`, `method`, `var`, `arg`, `argument`, `prop`, `return`, `exception`, `yield`|
|Closure-only|For type only: `package`, `private`, `protected`, `public`, `static`|
|Options|`allowEmptyNamepaths`, `checkSeesForNamepaths`|
|Settings|`mode`|
|Options|`allowEmptyNamepaths`|
|Settings|`mode`, `structuredTags`|

<!-- assertions validTypes -->

0 comments on commit 89f2ad0

Please sign in to comment.