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

fix: correctly parse $id and $comment JSDoc tags #1129

Merged
merged 9 commits into from Feb 16, 2022
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -3,6 +3,8 @@ coverage/
dist/
node_modules/
!auto.config.ts
/.idea/

# local config for auto
.env

12 changes: 9 additions & 3 deletions src/AnnotationsReader/BasicAnnotationsReader.ts
Expand Up @@ -5,15 +5,17 @@ import { Annotations } from "../Type/AnnotatedType";
import { symbolAtNode } from "../Utils/symbolAtNode";

export class BasicAnnotationsReader implements AnnotationsReader {
private static requiresDollar = new Set<string>(["id", "comment"]);
private static textTags = new Set<string>([
"title",
"description",
"id",

"format",
"pattern",

// New since draft-07:
"$comment",
"comment",
"contentMediaType",
"contentEncoding",
]);
Expand Down Expand Up @@ -70,11 +72,15 @@ export class BasicAnnotationsReader implements AnnotationsReader {
const annotations = jsDocTags.reduce((result: Annotations, jsDocTag) => {
const value = this.parseJsDocTag(jsDocTag);
if (value !== undefined) {
result[jsDocTag.name] = value;
if (BasicAnnotationsReader.requiresDollar.has(jsDocTag.name)) {
result["$" + jsDocTag.name] = value;
} else {
result[jsDocTag.name] = value;
}
}

return result;
}, {});

return Object.keys(annotations).length ? annotations : undefined;
}

Expand Down
6 changes: 6 additions & 0 deletions src/Interfaces/AnnotationsReader.ts
@@ -0,0 +1,6 @@
import ts from "typescript";
import { Annotations } from "../Type/AnnotatedType";

export interface AnnotationsReader {
getAnnotations(node: ts.Node): Annotations | undefined;
}
5 changes: 5 additions & 0 deletions src/Interfaces/MutableParser.ts
@@ -0,0 +1,5 @@
import { SubNodeParser } from "./SubNodeParser";

export interface MutableParser {
addNodeParser(parser: SubNodeParser): MutableParser;
}
5 changes: 5 additions & 0 deletions src/Interfaces/MutableTypeFormatter.ts
@@ -0,0 +1,5 @@
import { SubTypeFormatter } from "./SubTypeFormatter";

export interface MutableTypeFormatter {
addTypeFormatter(formatter: SubTypeFormatter): MutableTypeFormatter;
}
6 changes: 6 additions & 0 deletions src/Interfaces/SubNodeParser.ts
@@ -0,0 +1,6 @@
import ts from "typescript";
import { NodeParser } from "../NodeParser";

export interface SubNodeParser extends NodeParser {
supportsNode(node: ts.Node): boolean;
}
6 changes: 6 additions & 0 deletions src/Interfaces/SubTypeFormatter.ts
@@ -0,0 +1,6 @@
import { BaseType } from "../Type/BaseType";
import { TypeFormatter } from "./TypeFormatter";

export interface SubTypeFormatter extends TypeFormatter {
supportsType(type: BaseType): boolean;
}
7 changes: 7 additions & 0 deletions src/Interfaces/TypeFormatter.ts
@@ -0,0 +1,7 @@
import { Definition } from "../Schema/Definition";
import { BaseType } from "../Type/BaseType";

export interface TypeFormatter {
getDefinition(type: BaseType): Definition;
getChildren(type: BaseType): BaseType[];
}
32 changes: 32 additions & 0 deletions test/valid-data-annotations.test.ts
@@ -0,0 +1,32 @@
import { assertValidSchema } from "./utils";

describe("valid-data-annotations", () => {
it(
"annotation-custom",
assertValidSchema("annotation-custom", "MyObject", "basic", [
"customNumberProperty",
"customStringProperty",
"customComplexProperty",
"customMultilineProperty",
"customUnquotedProperty",
])
);

it("annotation-empty-basic", assertValidSchema("annotation-empty", "MyObject", "basic", ["customEmptyAnnotation"]));
it(
"annotation-empty-extended",
assertValidSchema("annotation-empty", "MyObject", "extended", ["customEmptyAnnotation"])
);
it(
"annotation-deprecated-empty-basic",
assertValidSchema("annotation-deprecated-empty", "MyObject", "basic", ["customEmptyAnnotation"])
);
it(
"annotation-deprecated-empty-extended",
assertValidSchema("annotation-deprecated-empty", "MyObject", "extended", ["customEmptyAnnotation"])
);

it("annotation-comment", assertValidSchema("annotation-comment", "MyObject", "extended"));

it("annotation-id", assertValidSchema("annotation-id", "MyObject", "extended", [], "Test"));
});
25 changes: 0 additions & 25 deletions test/valid-data-other.test.ts
Expand Up @@ -59,31 +59,6 @@ describe("valid-data-other", () => {
it("generic-prefixed-number", assertValidSchema("generic-prefixed-number", "MyObject"));
it("generic-void", assertValidSchema("generic-void", "MyObject"));

it(
"annotation-custom",
assertValidSchema("annotation-custom", "MyObject", "basic", [
"customNumberProperty",
"customStringProperty",
"customComplexProperty",
"customMultilineProperty",
"customUnquotedProperty",
])
);

it("annotation-empty-basic", assertValidSchema("annotation-empty", "MyObject", "basic", ["customEmptyAnnotation"]));
it(
"annotation-empty-extended",
assertValidSchema("annotation-empty", "MyObject", "extended", ["customEmptyAnnotation"])
);
it(
"annotation-deprecated-empty-basic",
assertValidSchema("annotation-deprecated-empty", "MyObject", "basic", ["customEmptyAnnotation"])
);
it(
"annotation-deprecated-empty-extended",
assertValidSchema("annotation-deprecated-empty", "MyObject", "extended", ["customEmptyAnnotation"])
);

it("nullable-null", assertValidSchema("nullable-null", "MyObject"));

it("undefined-alias", assertValidSchema("undefined-alias", "MyType"));
Expand Down
15 changes: 15 additions & 0 deletions test/valid-data/annotation-comment/main.ts
@@ -0,0 +1,15 @@
/**
* @comment Top level comment
*/
export interface MyObject {
/**
* @comment Property comment
*/
nested: MyNestedObject
}

/**
* @comment Nested object comment
domoritz marked this conversation as resolved.
Show resolved Hide resolved
*/
export interface MyNestedObject {}

25 changes: 25 additions & 0 deletions test/valid-data/annotation-comment/schema.json
@@ -0,0 +1,25 @@
{
"$ref": "#/definitions/MyObject",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyNestedObject": {
"$comment": "Nested object comment",
"additionalProperties": false,
"type": "object"
},
"MyObject": {
"$comment": "Top level comment",
"additionalProperties": false,
"properties": {
"nested": {
"$comment": "Property comment",
"$ref": "#/definitions/MyNestedObject"
}
},
"required": [
"nested"
],
"type": "object"
}
}
}
11 changes: 11 additions & 0 deletions test/valid-data/annotation-id/main.ts
@@ -0,0 +1,11 @@
/**
* @id #MyObject
*/
export interface MyObject {
nested: MyNestedObject
}

/**
* @id #MyNestedObject
*/
export interface MyNestedObject {}
25 changes: 25 additions & 0 deletions test/valid-data/annotation-id/schema.json
@@ -0,0 +1,25 @@
{
"$id": "Test",
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/MyObject",
"definitions": {
"MyNestedObject": {
"$id": "#MyNestedObject",
"additionalProperties": false,
"type": "object"
},
"MyObject": {
"$id": "#MyObject",
"additionalProperties": false,
"properties": {
"nested": {
"$ref": "#/definitions/MyNestedObject"
}
},
"required": [
"nested"
],
"type": "object"
}
}
}