@typedef supports nested @property names (#22967)

Previously it did not, because this capability is not documented on
usejsdoc.org. However, several people requested this feature.
This commit is contained in:
Nathan Shively-Sanders 2018-03-29 09:39:23 -07:00 committed by GitHub
parent 4e76dec0b4
commit eca3d68eb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 128 additions and 9 deletions

View File

@ -6497,7 +6497,7 @@ namespace ts {
const result = target === PropertyLikeParse.Parameter ?
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos) :
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, name);
const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, name, target);
if (nestedTypeLiteral) {
typeExpression = nestedTypeLiteral;
isNameFirst = true;
@ -6511,15 +6511,17 @@ namespace ts {
return finishNode(result);
}
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName) {
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName, target: PropertyLikeParse) {
if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
const typeLiteralExpression = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
let child: JSDocParameterTag | false;
let child: JSDocPropertyLikeTag | JSDocTypeTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral;
const start = scanner.getStartPos();
let children: JSDocParameterTag[];
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Parameter, name))) {
children = append(children, child);
let children: JSDocPropertyLikeTag[];
while (child = tryParse(() => parseChildParameterOrPropertyTag(target, name))) {
if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
children = append(children, child);
}
}
if (children) {
jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
@ -6623,7 +6625,7 @@ namespace ts {
let jsdocTypeLiteral: JSDocTypeLiteral;
let childTypeTag: JSDocTypeTag;
const start = scanner.getStartPos();
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Property))) {
while (child = tryParse(() => parseChildPropertyTag())) {
if (!jsdocTypeLiteral) {
jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
}
@ -6683,8 +6685,10 @@ namespace ts {
return a.escapedText === b.escapedText;
}
function parseChildParameterOrPropertyTag(target: PropertyLikeParse.Property): JSDocTypeTag | JSDocPropertyTag | false;
function parseChildParameterOrPropertyTag(target: PropertyLikeParse.Parameter, name: EntityName): JSDocParameterTag | false;
function parseChildPropertyTag() {
return parseChildParameterOrPropertyTag(PropertyLikeParse.Property) as JSDocTypeTag | JSDocPropertyTag | false;
}
function parseChildParameterOrPropertyTag(target: PropertyLikeParse, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
let canParseTag = true;
let seenAsterisk = false;

View File

@ -0,0 +1,39 @@
=== tests/cases/conformance/jsdoc/a.js ===
/** @typedef {Object} App
* @property {string} name
* @property {Object} icons
* @property {string} icons.image32
* @property {string} icons.image64
*/
var ex;
>ex : Symbol(ex, Decl(a.js, 6, 3))
/** @type {App} */
const app = {
>app : Symbol(app, Decl(a.js, 9, 5))
name: 'name',
>name : Symbol(name, Decl(a.js, 9, 13))
icons: {
>icons : Symbol(icons, Decl(a.js, 10, 17))
image32: 'x.png',
>image32 : Symbol(image32, Decl(a.js, 11, 12))
image64: 'y.png',
>image64 : Symbol(image64, Decl(a.js, 12, 25))
}
}
/** @typedef {Object} Opp
* @property {string} name
* @property {Object} oops
* @property {string} horrible
* @type {string} idea
*/
/** @type {Opp} */
var mistake;
>mistake : Symbol(mistake, Decl(a.js, 25, 3))

View File

@ -0,0 +1,44 @@
=== tests/cases/conformance/jsdoc/a.js ===
/** @typedef {Object} App
* @property {string} name
* @property {Object} icons
* @property {string} icons.image32
* @property {string} icons.image64
*/
var ex;
>ex : any
/** @type {App} */
const app = {
>app : { name: string; icons: { image32: string; image64: string; }; }
>{ name: 'name', icons: { image32: 'x.png', image64: 'y.png', }} : { name: string; icons: { image32: string; image64: string; }; }
name: 'name',
>name : string
>'name' : "name"
icons: {
>icons : { image32: string; image64: string; }
>{ image32: 'x.png', image64: 'y.png', } : { image32: string; image64: string; }
image32: 'x.png',
>image32 : string
>'x.png' : "x.png"
image64: 'y.png',
>image64 : string
>'y.png' : "y.png"
}
}
/** @typedef {Object} Opp
* @property {string} name
* @property {Object} oops
* @property {string} horrible
* @type {string} idea
*/
/** @type {Opp} */
var mistake;
>mistake : { name: string; oops: { horrible: string; }; }

View File

@ -0,0 +1,32 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @strict: true
// @Filename: a.js
/** @typedef {Object} App
* @property {string} name
* @property {Object} icons
* @property {string} icons.image32
* @property {string} icons.image64
*/
var ex;
/** @type {App} */
const app = {
name: 'name',
icons: {
image32: 'x.png',
image64: 'y.png',
}
}
/** @typedef {Object} Opp
* @property {string} name
* @property {Object} oops
* @property {string} horrible
* @type {string} idea
*/
/** @type {Opp} */
var mistake;