Skip to content

Commit fa4b49d

Browse files
authored
fix(51374): ts(80004): Quick fix... > Annotate with type from JSDoc :: object types (#51378)
* fix(51374): transform JSDocTypeLiteral * add additional tests * add additional tests
1 parent eac566b commit fa4b49d

File tree

6 files changed

+110
-8
lines changed

6 files changed

+110
-8
lines changed

src/compiler/checker.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13007,14 +13007,6 @@ namespace ts {
1300713007
return isPropertyDeclaration(node) && !hasAccessorModifier(node) && node.questionToken;
1300813008
}
1300913009

13010-
function isOptionalJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag {
13011-
if (!isJSDocPropertyLikeTag(node)) {
13012-
return false;
13013-
}
13014-
const { isBracketed, typeExpression } = node;
13015-
return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
13016-
}
13017-
1301813010
function createTypePredicate(kind: TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: Type | undefined): TypePredicate {
1301913011
return { kind, parameterName, parameterIndex, type } as TypePredicate;
1302013012
}

src/compiler/utilities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7778,4 +7778,12 @@ namespace ts {
77787778
return isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node)
77797779
|| isInterfaceDeclaration(node) || isTypeDeclaration(node) || (isModuleDeclaration(node) && !isExternalModuleAugmentation(node) && !isGlobalScopeAugmentation(node));
77807780
}
7781+
7782+
export function isOptionalJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag {
7783+
if (!isJSDocPropertyLikeTag(node)) {
7784+
return false;
7785+
}
7786+
const { isBracketed, typeExpression } = node;
7787+
return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
7788+
}
77817789
}

src/services/codefixes/annotateWithTypeFromJSDoc.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,26 @@ namespace ts.codefix {
9090
return transformJSDocFunctionType(node as JSDocFunctionType);
9191
case SyntaxKind.TypeReference:
9292
return transformJSDocTypeReference(node as TypeReferenceNode);
93+
case SyntaxKind.JSDocTypeLiteral:
94+
return transformJSDocTypeLiteral(node as JSDocTypeLiteral);
9395
default:
9496
const visited = visitEachChild(node, transformJSDocType, nullTransformationContext);
9597
setEmitFlags(visited, EmitFlags.SingleLine);
9698
return visited;
9799
}
98100
}
99101

102+
function transformJSDocTypeLiteral(node: JSDocTypeLiteral) {
103+
const typeNode = factory.createTypeLiteralNode(map(node.jsDocPropertyTags, tag =>
104+
factory.createPropertySignature(
105+
/*modifiers*/ undefined,
106+
isIdentifier(tag.name) ? tag.name : tag.name.right,
107+
isOptionalJSDocPropertyLikeTag(tag) ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
108+
tag.typeExpression && visitNode(tag.typeExpression.type, transformJSDocType) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword))));
109+
setEmitFlags(typeNode, EmitFlags.SingleLine);
110+
return typeNode;
111+
}
112+
100113
function transformJSDocOptionalType(node: JSDocOptionalType) {
101114
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("undefined", emptyArray)]);
102115
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path="fourslash.ts" />
2+
// @strict: true
3+
4+
////class C {
5+
//// /**
6+
//// * @private
7+
//// * @param {number} foo
8+
//// * @param {Object} [bar]
9+
//// * @param {String} bar.a
10+
//// * @param {Number} [bar.b]
11+
//// * @param bar.c
12+
//// */
13+
//// m(foo, bar) { }
14+
////}
15+
16+
verify.codeFix({
17+
description: ts.Diagnostics.Annotate_with_type_from_JSDoc.message,
18+
index: 2,
19+
newFileContent:
20+
`class C {
21+
/**
22+
* @private
23+
* @param {number} foo
24+
* @param {Object} [bar]
25+
* @param {String} bar.a
26+
* @param {Number} [bar.b]
27+
* @param bar.c
28+
*/
29+
m(foo: number, bar: { a: string; b?: number; c: any; }) { }
30+
}`,
31+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path="fourslash.ts" />
2+
// @strict: true
3+
4+
////class C {
5+
//// /**
6+
//// * @private
7+
//// * @param {number} foo
8+
//// * @param {Object} [bar]
9+
//// * @param {String} bar.a
10+
//// * @param {Object} [baz]
11+
//// * @param {number} baz.c
12+
//// */
13+
//// m(foo, bar, baz) { }
14+
////}
15+
16+
verify.codeFix({
17+
description: ts.Diagnostics.Annotate_with_type_from_JSDoc.message,
18+
index: 3,
19+
newFileContent:
20+
`class C {
21+
/**
22+
* @private
23+
* @param {number} foo
24+
* @param {Object} [bar]
25+
* @param {String} bar.a
26+
* @param {Object} [baz]
27+
* @param {number} baz.c
28+
*/
29+
m(foo: number, bar: { a: string; }, baz: { c: number; }) { }
30+
}`,
31+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// <reference path="fourslash.ts" />
2+
// @strict: true
3+
4+
////class C {
5+
//// /**
6+
//// * @private
7+
//// * @param {Object} [foo]
8+
//// * @param {Object} foo.a
9+
//// * @param {String} [foo.a.b]
10+
//// */
11+
//// m(foo) { }
12+
////}
13+
14+
verify.codeFix({
15+
description: ts.Diagnostics.Annotate_with_type_from_JSDoc.message,
16+
index: 1,
17+
newFileContent:
18+
`class C {
19+
/**
20+
* @private
21+
* @param {Object} [foo]
22+
* @param {Object} foo.a
23+
* @param {String} [foo.a.b]
24+
*/
25+
m(foo: { a: { b?: string; }; }) { }
26+
}`,
27+
});

0 commit comments

Comments
 (0)