Open clshortfuse opened 1 year ago
In interest of moving this forward, I believe we need to analyze for \
tokens in
called from
I think, the issue is not related to parsing Unicode names. The name contains a #
, which is not a valid identifier (x#x
). In TypeScript, a property name can be a StringLiteral
type a = {
'x5t#S256': 1
}
const b: a = {
'x5t#S256': 1,
}
However, when we define a property name in JSDoc, it can only be an Identifier
or QualifiedName
.
https://github.com/microsoft/TypeScript/blob/b1a96a37b5cb5dd18ca72cc09014c1f110089b1b/src/compiler/parser.ts#L9664-L9680
I'm not sure if it's okay to allow the use of StringLiteral
as property names in JSDoc.
/cc @RyanCavanaugh @sandersn
@a-tarasyuk You seem to be right it's about what it computes to after parsing, not so much the parsing itself:
/**
* @typedef MyObject
* @prop {string} [\u0066\u006f\u006f] escaped foo
*/
/** @type {MyObject} */
const a = {
foo: 'bar'
};
This parses fine. But \u0020
(`) can't be used in JSDocs, though it's accepted in
Record<?,?>`:
/**
* @typedef {Record<'With Space', string>} WithSpaceObject
*/
/** @type {WithSpaceObject} */
const b = {
'With Space': 'okay'
};
Regardless of parsing, jsdoc should support the same kinds of property names as typescript itself, which means, I think, it should include StringLiteral. I haven't double-checked that against the code though.
I haven't even thought about how to parse things that aren't legal identifiers, since most params aren't optional and so don't surround the param name with brackets. Using \0020 instead of a literal space seems like it's parseable though.
@sandersn If JSDocPropertyTag.name
starts to support StringLiteral
, it might be more appropriate for JSDocPropertyTag
and JSDocParameterTag
to use their types instead of inheriting from JSDocPropertyLikeTag
(StringLiteral
should be forbidden in JSDocParameterTag
). Or is it okay to allow the use of StringLiteral
in JSDocPropertyLikeTag
? I'm not sure about the deprecation process for this case...
Are you proposing adding an override type for JSDocPropertyTag.name? That seems reasonable, although I'm having trouble visualising the complete solution.
Changing JSDocPropertyTag.name to a supertype of its current type doesn't seem like a huge problem -- although, again, I could be missing something.
@sandersn I have been considering two ways to accomplish that
name
from JSDocPropertyLikeTag
and use it for JSDocParameterTag
/JSDocPropertyLikeTag
. Then, add conditions in parser/binder/etc. to manage that (for instance, the parser uses one method to handle both tags).export interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
readonly parent: JSDoc;
readonly typeExpression?: JSDocTypeExpression;
/** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */
readonly isNameFirst: boolean;
readonly isBracketed: boolean;
}
export interface JSDocPropertyTag extends JSDocPropertyLikeTag {
readonly kind: SyntaxKind.JSDocPropertyTag;
readonly name: JSDocPropertyName;
}
export interface JSDocParameterTag extends JSDocPropertyLikeTag {
readonly kind: SyntaxKind.JSDocParameterTag;
readonly name: EntityName;
}
JSDocPropertyLikeTag
in favor of using all properties for each tag.
export interface JSDocPropertyTag extends JSDocTag, Declaration {
readonly kind: SyntaxKind.JSDocPropertyTag;
readonly name: JSDocPropertyName;
readonly parent: JSDoc;
readonly typeExpression?: JSDocTypeExpression;
/** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */
readonly isNameFirst: boolean;
readonly isBracketed: boolean;
}
export interface JSDocParameterTag extends JSDocTag, Declaration { readonly kind: SyntaxKind.JSDocParameterTag; readonly name: EntityName; readonly parent: JSDoc; readonly typeExpression?: JSDocTypeExpression; /* Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like / readonly isNameFirst: boolean; readonly isBracketed: boolean; }
Both approaches involve deprecating or removing the public API, and I'm not sure which one would be safer.
How about a variant of the first option: what about leaving JSDocPropertyLikeTag.name
, but with type JSDocPropertyName
(assuming JSDocPropertyName is a supertype of EntityName).
I'm not sure I like StringLiteral for parsing identifiers with otherwise-illegal characters. Is that what you're proposing? Is there precedent for that? Maybe it would be better to make a new kind of identifier.
Also, it's kind of weird that#
is used for class-property access like C#prop
, so maybe it's worth asking whether that specifically should be allowed, and whether there are any other specific uses that people have wanted and found missing.
I can think of Amazon's DynamoDB syntax over JSON that uses #
for ExpressionAttributeNames:
An expression attribute name must begin with a pound sign (#), and be followed by one or more alphanumeric characters.
I've also seen #text
as a key, mostly when working with XML or HTML nodes.
If you mean what other characters, JSON-LD uses @id
(\u0040
) and :
which also isn't supported by Typescript's JSDoc parser (edit):
Ran across this too, and I found a workaround using inline intersection types (playground link):
/**
* @see https://datatracker.ietf.org/doc/html/rfc7517#section-4
* @typedef {Object} JWKBase
* @prop {string} kty key type
*
* @typedef {JWKBase & { ['x5t#S256']: string }} JWK
*/
/** @type {JWK} */
const o = {
kty: 'foo',
'x5t#S256': 'bar',
};
Messy, but it works!
Bug Report
🔎 Search Terms
jsdoc escape property names
🕗 Version & Regression Information
jsdoc
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
Errors:
]' expected.
Type '{ kty: string; 'x5t#256': string; }' is not assignable to type 'JWK'. Object literal may only specify known properties, and ''x5t#256'' does not exist in type 'JWK'.
🙂 Expected behavior
No errors and to parse escaped property names correctly.
Additional Info
Originally posted by @brettz9 in https://github.com/jsdoc/jsdoc/issues/1468#issuecomment-743490820
Edit: Fixed typo in property name. Incidentally shows the importance of types. 😅