mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Parse *= separately in types (#39457)
* Parse *= separately in types Previously, when the scanner produced `*=` as a single token, the type parser ran special-case code to produce an "optional all type", which only makes sense when the `=` really should be attached to the `*`. This is often not the case. The correct solution, which I missed when I first wrote this code, is to have the scanner go back and produce a separate `=` token, which is what this PR does. * add test from #38551 * we ❤️ semicolons
This commit is contained in:
+8
-15
@@ -2701,19 +2701,10 @@ namespace ts {
|
||||
return finishNode(factory.createThisTypeNode(), pos);
|
||||
}
|
||||
|
||||
function parseJSDocAllType(postFixEquals: boolean): JSDocAllType | JSDocOptionalType {
|
||||
function parseJSDocAllType(): JSDocAllType | JSDocOptionalType {
|
||||
const pos = getNodePos();
|
||||
nextToken();
|
||||
|
||||
const node = factory.createJSDocAllType();
|
||||
if (postFixEquals) {
|
||||
// Trim the trailing `=` from the `*=` token
|
||||
const end = Math.max(getNodePos() - 1, pos);
|
||||
return finishNode(factory.createJSDocOptionalType(finishNode(node, pos, end)), pos);
|
||||
}
|
||||
else {
|
||||
return finishNode(node, pos);
|
||||
}
|
||||
return finishNode(factory.createJSDocAllType(), pos);
|
||||
}
|
||||
|
||||
function parseJSDocNonNullableType(): TypeNode {
|
||||
@@ -3396,12 +3387,14 @@ namespace ts {
|
||||
case SyntaxKind.ObjectKeyword:
|
||||
// If these are followed by a dot, then parse these out as a dotted type reference instead.
|
||||
return tryParse(parseKeywordAndNoDot) || parseTypeReference();
|
||||
case SyntaxKind.AsteriskToken:
|
||||
return parseJSDocAllType(/*postfixEquals*/ false);
|
||||
case SyntaxKind.AsteriskEqualsToken:
|
||||
return parseJSDocAllType(/*postfixEquals*/ true);
|
||||
// If there is '*=', treat it as * followed by postfix =
|
||||
scanner.reScanAsteriskEqualsToken();
|
||||
// falls through
|
||||
case SyntaxKind.AsteriskToken:
|
||||
return parseJSDocAllType();
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
// If there is '??', consider that is prefix '?' in JSDoc type.
|
||||
// If there is '??', treat it as prefix-'?' in JSDoc type.
|
||||
scanner.reScanQuestionToken();
|
||||
// falls through
|
||||
case SyntaxKind.QuestionToken:
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace ts {
|
||||
getTokenFlags(): TokenFlags;
|
||||
reScanGreaterToken(): SyntaxKind;
|
||||
reScanSlashToken(): SyntaxKind;
|
||||
reScanAsteriskEqualsToken(): SyntaxKind;
|
||||
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
|
||||
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
|
||||
scanJsxIdentifier(): SyntaxKind;
|
||||
@@ -954,6 +955,7 @@ namespace ts {
|
||||
getNumericLiteralFlags: () => tokenFlags & TokenFlags.NumericLiteralFlags,
|
||||
getTokenFlags: () => tokenFlags,
|
||||
reScanGreaterToken,
|
||||
reScanAsteriskEqualsToken,
|
||||
reScanSlashToken,
|
||||
reScanTemplateToken,
|
||||
reScanTemplateHeadOrNoSubstitutionTemplate,
|
||||
@@ -2086,6 +2088,12 @@ namespace ts {
|
||||
return token;
|
||||
}
|
||||
|
||||
function reScanAsteriskEqualsToken(): SyntaxKind {
|
||||
Debug.assert(token === SyntaxKind.AsteriskEqualsToken, "'reScanAsteriskEqualsToken' should only be called on a '*='");
|
||||
pos = tokenPos + 1;
|
||||
return token = SyntaxKind.EqualsToken;
|
||||
}
|
||||
|
||||
function reScanSlashToken(): SyntaxKind {
|
||||
if (token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) {
|
||||
let p = tokenPos + 1;
|
||||
|
||||
@@ -3902,6 +3902,7 @@ declare namespace ts {
|
||||
isUnterminated(): boolean;
|
||||
reScanGreaterToken(): SyntaxKind;
|
||||
reScanSlashToken(): SyntaxKind;
|
||||
reScanAsteriskEqualsToken(): SyntaxKind;
|
||||
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
|
||||
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
|
||||
scanJsxIdentifier(): SyntaxKind;
|
||||
|
||||
@@ -3902,6 +3902,7 @@ declare namespace ts {
|
||||
isUnterminated(): boolean;
|
||||
reScanGreaterToken(): SyntaxKind;
|
||||
reScanSlashToken(): SyntaxKind;
|
||||
reScanAsteriskEqualsToken(): SyntaxKind;
|
||||
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
|
||||
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
|
||||
scanJsxIdentifier(): SyntaxKind;
|
||||
|
||||
@@ -12,3 +12,10 @@ function f(...args) {
|
||||
var x;
|
||||
>x : Symbol(x, Decl(a.js, 7, 3))
|
||||
|
||||
|
||||
/** @param {function():*=} f */
|
||||
function cbf(f) {
|
||||
>cbf : Symbol(cbf, Decl(a.js, 7, 6))
|
||||
>f : Symbol(f, Decl(a.js, 11, 13))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
/** @param {...*=} args
|
||||
@return {*=} */
|
||||
function f(...args) {
|
||||
>f : (...args: (any | undefined)[]) => any | undefined
|
||||
>args : any[]
|
||||
>f : (...args?: any[] | undefined) => any | undefined
|
||||
>args : any
|
||||
|
||||
return null
|
||||
>null : null
|
||||
@@ -13,3 +13,10 @@ function f(...args) {
|
||||
var x;
|
||||
>x : any
|
||||
|
||||
|
||||
/** @param {function():*=} f */
|
||||
function cbf(f) {
|
||||
>cbf : (f?: (() => any) | undefined) => void
|
||||
>f : (() => any) | undefined
|
||||
}
|
||||
|
||||
|
||||
@@ -12,3 +12,8 @@ function f(...args) {
|
||||
|
||||
/** @type *= */
|
||||
var x;
|
||||
|
||||
|
||||
/** @param {function():*=} f */
|
||||
function cbf(f) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user