Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1865,9 +1865,12 @@ namespace ts {
let commaStart = -1; // Meaning the previous token was not a comma
while (true) {
if (isListElement(kind, /*inErrorRecovery*/ false)) {
const startPos = scanner.getStartPos();
result.push(parseListElement(kind, parseElement));
commaStart = scanner.getTokenPos();

if (parseOptional(SyntaxKind.CommaToken)) {
// No need to check for a zero length node since we know we parsed a comma
continue;
}

Expand All @@ -1888,6 +1891,13 @@ namespace ts {
if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
nextToken();
}
if (startPos === scanner.getStartPos()) {
// What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever
// Consume a token to advance the parser in some way and avoid an infinite loop
// This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions,
// or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied
nextToken();
}
continue;
}

Expand Down Expand Up @@ -2221,7 +2231,6 @@ namespace ts {
return finishNode(node);
}

const startPos = scanner.getStartPos();
node.decorators = parseDecorators();
node.modifiers = parseModifiers();
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
Expand All @@ -2245,14 +2254,6 @@ namespace ts {
node.type = parseParameterType();
node.initializer = parseBindingElementInitializer(/*inParameter*/ true);

if (startPos === scanner.getStartPos()) {
// What we're parsing isn't actually remotely recognizable as a parameter and we've consumed no tokens whatsoever
// Consume a token to advance the parser in some way and avoid an infinite loop in `parseDelimitedList`
// This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions,
// or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied
nextToken();
}

return addJSDocComment(finishNode(node));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
tests/cases/compiler/example.js(3,20): error TS1003: Identifier expected.


==== tests/cases/compiler/example.js (1 errors) ====
// @ts-check
/**
* @type {function(@foo)}
~
!!! error TS1003: Identifier expected.
*/
let x;
9 changes: 9 additions & 0 deletions tests/cases/compiler/jsdocParameterParsingInfiniteLoop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @filename: example.js
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @ts-check
/**
* @type {function(@foo)}
*/
let x;