diff --git a/lib/lib.es2022.object.d.ts b/lib/lib.es2022.object.d.ts
index 63460100667e4..2fe2a1917f15e 100644
--- a/lib/lib.es2022.object.d.ts
+++ b/lib/lib.es2022.object.d.ts
@@ -18,7 +18,7 @@ and limitations under the License.
///
-interface Object {
+interface ObjectConstructor {
/**
* Determines whether an object has a property with the specified name.
* @param o An object.
diff --git a/lib/tsc.js b/lib/tsc.js
index 7704b1a2be538..636e39ae1f4ff 100644
--- a/lib/tsc.js
+++ b/lib/tsc.js
@@ -69,7 +69,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
var ts;
(function (ts) {
ts.versionMajorMinor = "4.6";
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
var NativeCollections;
(function (NativeCollections) {
var globals = typeof globalThis !== "undefined" ? globalThis :
@@ -25262,9 +25262,7 @@ var ts;
return;
}
if (initializer) {
- if (token() === 18) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26));
return;
}
parseErrorForMissingSemicolonAfter(name);
diff --git a/lib/tsserver.js b/lib/tsserver.js
index ff74f351d1bd6..60a159a673ef0 100644
--- a/lib/tsserver.js
+++ b/lib/tsserver.js
@@ -100,7 +100,7 @@ var ts;
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
/* @internal */
var Comparison;
(function (Comparison) {
@@ -31354,18 +31354,8 @@ var ts;
if (tryParseSemicolon()) {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === 18 /* OpenBraceToken */) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
return;
}
parseErrorForMissingSemicolonAfter(name);
@@ -124974,12 +124964,8 @@ var ts;
}
}
ts.findNextToken = findNextToken;
- /**
- * Finds the rightmost token satisfying `token.end <= position`,
- * excluding `JsxText` tokens containing only whitespace.
- */
function findPrecedingToken(position, sourceFile, startNode, excludeJsdoc) {
- var result = find(startNode || sourceFile);
+ var result = find((startNode || sourceFile));
ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
function find(n) {
@@ -140014,6 +140000,41 @@ var ts;
if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
break;
}
+ if (ts.scanner.getToken() === 15 /* TemplateHead */) {
+ var stack = [ts.scanner.getToken()];
+ var token = ts.scanner.scan();
+ loop: while (ts.length(stack)) {
+ switch (token) {
+ case 1 /* EndOfFileToken */:
+ break loop;
+ case 100 /* ImportKeyword */:
+ tryConsumeImport();
+ break;
+ case 15 /* TemplateHead */:
+ stack.push(token);
+ break;
+ case 18 /* OpenBraceToken */:
+ if (ts.length(stack)) {
+ stack.push(token);
+ }
+ break;
+ case 19 /* CloseBraceToken */:
+ if (ts.length(stack)) {
+ if (ts.lastOrUndefined(stack) === 15 /* TemplateHead */) {
+ if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === 17 /* TemplateTail */) {
+ stack.pop();
+ }
+ }
+ else {
+ stack.pop();
+ }
+ }
+ break;
+ }
+ token = ts.scanner.scan();
+ }
+ nextToken();
+ }
// check if at least one of alternative have moved scanner forward
if (tryConsumeDeclare() ||
tryConsumeImport() ||
@@ -144036,6 +144057,7 @@ var ts;
return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
}
function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
+ var _b;
var options = _a.options, getRules = _a.getRules, host = _a.host;
// formatting context is used by rules provider
var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
@@ -144067,11 +144089,12 @@ var ts;
}
}
if (previousRange && formattingScanner.getStartPos() >= originalRange.end) {
- var token = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
+ var tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token :
undefined;
- if (token) {
- processPair(token, sourceFile.getLineAndCharacterOfPosition(token.pos).line, enclosingNode, previousRange, previousRangeStartLine, previousParent, enclosingNode,
+ if (tokenInfo) {
+ var parent = ((_b = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)) === null || _b === void 0 ? void 0 : _b.parent) || previousParent;
+ processPair(tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, parent, previousRange, previousRangeStartLine, previousParent, parent,
/*dynamicIndentation*/ undefined);
}
}
diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js
index 9290a3661080e..fcb589891a4d5 100644
--- a/lib/tsserverlibrary.js
+++ b/lib/tsserverlibrary.js
@@ -294,7 +294,7 @@ var ts;
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
/* @internal */
var Comparison;
(function (Comparison) {
@@ -31548,18 +31548,8 @@ var ts;
if (tryParseSemicolon()) {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === 18 /* OpenBraceToken */) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
return;
}
parseErrorForMissingSemicolonAfter(name);
@@ -125585,12 +125575,8 @@ var ts;
}
}
ts.findNextToken = findNextToken;
- /**
- * Finds the rightmost token satisfying `token.end <= position`,
- * excluding `JsxText` tokens containing only whitespace.
- */
function findPrecedingToken(position, sourceFile, startNode, excludeJsdoc) {
- var result = find(startNode || sourceFile);
+ var result = find((startNode || sourceFile));
ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
function find(n) {
@@ -140625,6 +140611,41 @@ var ts;
if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
break;
}
+ if (ts.scanner.getToken() === 15 /* TemplateHead */) {
+ var stack = [ts.scanner.getToken()];
+ var token = ts.scanner.scan();
+ loop: while (ts.length(stack)) {
+ switch (token) {
+ case 1 /* EndOfFileToken */:
+ break loop;
+ case 100 /* ImportKeyword */:
+ tryConsumeImport();
+ break;
+ case 15 /* TemplateHead */:
+ stack.push(token);
+ break;
+ case 18 /* OpenBraceToken */:
+ if (ts.length(stack)) {
+ stack.push(token);
+ }
+ break;
+ case 19 /* CloseBraceToken */:
+ if (ts.length(stack)) {
+ if (ts.lastOrUndefined(stack) === 15 /* TemplateHead */) {
+ if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === 17 /* TemplateTail */) {
+ stack.pop();
+ }
+ }
+ else {
+ stack.pop();
+ }
+ }
+ break;
+ }
+ token = ts.scanner.scan();
+ }
+ nextToken();
+ }
// check if at least one of alternative have moved scanner forward
if (tryConsumeDeclare() ||
tryConsumeImport() ||
@@ -144647,6 +144668,7 @@ var ts;
return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
}
function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
+ var _b;
var options = _a.options, getRules = _a.getRules, host = _a.host;
// formatting context is used by rules provider
var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
@@ -144678,11 +144700,12 @@ var ts;
}
}
if (previousRange && formattingScanner.getStartPos() >= originalRange.end) {
- var token = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
+ var tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token :
undefined;
- if (token) {
- processPair(token, sourceFile.getLineAndCharacterOfPosition(token.pos).line, enclosingNode, previousRange, previousRangeStartLine, previousParent, enclosingNode,
+ if (tokenInfo) {
+ var parent = ((_b = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)) === null || _b === void 0 ? void 0 : _b.parent) || previousParent;
+ processPair(tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, parent, previousRange, previousRangeStartLine, previousParent, parent,
/*dynamicIndentation*/ undefined);
}
}
diff --git a/lib/typescript.js b/lib/typescript.js
index 89cc0ba3ffb18..3be91a8fa92f4 100644
--- a/lib/typescript.js
+++ b/lib/typescript.js
@@ -294,7 +294,7 @@ var ts;
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
/* @internal */
var Comparison;
(function (Comparison) {
@@ -31548,18 +31548,8 @@ var ts;
if (tryParseSemicolon()) {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === 18 /* OpenBraceToken */) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
return;
}
parseErrorForMissingSemicolonAfter(name);
@@ -125585,12 +125575,8 @@ var ts;
}
}
ts.findNextToken = findNextToken;
- /**
- * Finds the rightmost token satisfying `token.end <= position`,
- * excluding `JsxText` tokens containing only whitespace.
- */
function findPrecedingToken(position, sourceFile, startNode, excludeJsdoc) {
- var result = find(startNode || sourceFile);
+ var result = find((startNode || sourceFile));
ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
function find(n) {
@@ -140625,6 +140611,41 @@ var ts;
if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
break;
}
+ if (ts.scanner.getToken() === 15 /* TemplateHead */) {
+ var stack = [ts.scanner.getToken()];
+ var token = ts.scanner.scan();
+ loop: while (ts.length(stack)) {
+ switch (token) {
+ case 1 /* EndOfFileToken */:
+ break loop;
+ case 100 /* ImportKeyword */:
+ tryConsumeImport();
+ break;
+ case 15 /* TemplateHead */:
+ stack.push(token);
+ break;
+ case 18 /* OpenBraceToken */:
+ if (ts.length(stack)) {
+ stack.push(token);
+ }
+ break;
+ case 19 /* CloseBraceToken */:
+ if (ts.length(stack)) {
+ if (ts.lastOrUndefined(stack) === 15 /* TemplateHead */) {
+ if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === 17 /* TemplateTail */) {
+ stack.pop();
+ }
+ }
+ else {
+ stack.pop();
+ }
+ }
+ break;
+ }
+ token = ts.scanner.scan();
+ }
+ nextToken();
+ }
// check if at least one of alternative have moved scanner forward
if (tryConsumeDeclare() ||
tryConsumeImport() ||
@@ -144647,6 +144668,7 @@ var ts;
return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
}
function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
+ var _b;
var options = _a.options, getRules = _a.getRules, host = _a.host;
// formatting context is used by rules provider
var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
@@ -144678,11 +144700,12 @@ var ts;
}
}
if (previousRange && formattingScanner.getStartPos() >= originalRange.end) {
- var token = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
+ var tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token :
undefined;
- if (token) {
- processPair(token, sourceFile.getLineAndCharacterOfPosition(token.pos).line, enclosingNode, previousRange, previousRangeStartLine, previousParent, enclosingNode,
+ if (tokenInfo) {
+ var parent = ((_b = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)) === null || _b === void 0 ? void 0 : _b.parent) || previousParent;
+ processPair(tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, parent, previousRange, previousRangeStartLine, previousParent, parent,
/*dynamicIndentation*/ undefined);
}
}
diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js
index d1d97fe03d60c..e958d4e4d3a2c 100644
--- a/lib/typescriptServices.js
+++ b/lib/typescriptServices.js
@@ -294,7 +294,7 @@ var ts;
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
/* @internal */
var Comparison;
(function (Comparison) {
@@ -31548,18 +31548,8 @@ var ts;
if (tryParseSemicolon()) {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === 18 /* OpenBraceToken */) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
return;
}
parseErrorForMissingSemicolonAfter(name);
@@ -125585,12 +125575,8 @@ var ts;
}
}
ts.findNextToken = findNextToken;
- /**
- * Finds the rightmost token satisfying `token.end <= position`,
- * excluding `JsxText` tokens containing only whitespace.
- */
function findPrecedingToken(position, sourceFile, startNode, excludeJsdoc) {
- var result = find(startNode || sourceFile);
+ var result = find((startNode || sourceFile));
ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
function find(n) {
@@ -140625,6 +140611,41 @@ var ts;
if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
break;
}
+ if (ts.scanner.getToken() === 15 /* TemplateHead */) {
+ var stack = [ts.scanner.getToken()];
+ var token = ts.scanner.scan();
+ loop: while (ts.length(stack)) {
+ switch (token) {
+ case 1 /* EndOfFileToken */:
+ break loop;
+ case 100 /* ImportKeyword */:
+ tryConsumeImport();
+ break;
+ case 15 /* TemplateHead */:
+ stack.push(token);
+ break;
+ case 18 /* OpenBraceToken */:
+ if (ts.length(stack)) {
+ stack.push(token);
+ }
+ break;
+ case 19 /* CloseBraceToken */:
+ if (ts.length(stack)) {
+ if (ts.lastOrUndefined(stack) === 15 /* TemplateHead */) {
+ if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === 17 /* TemplateTail */) {
+ stack.pop();
+ }
+ }
+ else {
+ stack.pop();
+ }
+ }
+ break;
+ }
+ token = ts.scanner.scan();
+ }
+ nextToken();
+ }
// check if at least one of alternative have moved scanner forward
if (tryConsumeDeclare() ||
tryConsumeImport() ||
@@ -144647,6 +144668,7 @@ var ts;
return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
}
function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
+ var _b;
var options = _a.options, getRules = _a.getRules, host = _a.host;
// formatting context is used by rules provider
var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
@@ -144678,11 +144700,12 @@ var ts;
}
}
if (previousRange && formattingScanner.getStartPos() >= originalRange.end) {
- var token = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
+ var tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token :
undefined;
- if (token) {
- processPair(token, sourceFile.getLineAndCharacterOfPosition(token.pos).line, enclosingNode, previousRange, previousRangeStartLine, previousParent, enclosingNode,
+ if (tokenInfo) {
+ var parent = ((_b = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)) === null || _b === void 0 ? void 0 : _b.parent) || previousParent;
+ processPair(tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, parent, previousRange, previousRangeStartLine, previousParent, parent,
/*dynamicIndentation*/ undefined);
}
}
diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js
index 67aa6f7336aa4..715445fffe2bd 100644
--- a/lib/typingsInstaller.js
+++ b/lib/typingsInstaller.js
@@ -89,7 +89,7 @@ var ts;
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- ts.version = "4.6.2";
+ ts.version = "4.6.4";
/* @internal */
var Comparison;
(function (Comparison) {
@@ -31343,18 +31343,8 @@ var ts;
if (tryParseSemicolon()) {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === 18 /* OpenBraceToken */) {
- parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
- }
+ parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(26 /* SemicolonToken */));
return;
}
parseErrorForMissingSemicolonAfter(name);
diff --git a/package.json b/package.json
index 709da71b59b40..30243b6a35587 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "https://www.typescriptlang.org/",
- "version": "4.6.2",
+ "version": "4.6.4",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts
index 2e0d8a0eeff28..e170ec832229e 100644
--- a/src/compiler/corePublic.ts
+++ b/src/compiler/corePublic.ts
@@ -5,7 +5,7 @@ namespace ts {
// The following is baselined as a literal template type without intervention
/** The version of the TypeScript compiler release */
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
- export const version = "4.6.2" as string;
+ export const version = "4.6.4" as string;
/**
* Type of objects whose values are all of the same type.
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index c796e78d45190..0dea81baae43b 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -1680,19 +1680,8 @@ namespace ts {
return;
}
- // If an initializer was parsed but there is still an error in finding the next semicolon,
- // we generally know there was an error already reported in the initializer...
- // class Example { a = new Map([), ) }
- // ~
if (initializer) {
- // ...unless we've found the start of a block after a property declaration, in which
- // case we can know that regardless of the initializer we should complain on the block.
- // class Example { a = 0 {} }
- // ~
- if (token() === SyntaxKind.OpenBraceToken) {
- parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
- }
-
+ parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
return;
}
diff --git a/src/lib/es2022.object.d.ts b/src/lib/es2022.object.d.ts
index 764610213b6ac..7325ef3c343e2 100644
--- a/src/lib/es2022.object.d.ts
+++ b/src/lib/es2022.object.d.ts
@@ -1,4 +1,4 @@
-interface Object {
+interface ObjectConstructor {
/**
* Determines whether an object has a property with the specified name.
* @param o An object.
diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts
index 3b68b44063e62..5a9948cd35f72 100644
--- a/src/services/formatting/formatting.ts
+++ b/src/services/formatting/formatting.ts
@@ -439,20 +439,21 @@ namespace ts.formatting {
}
if (previousRange! && formattingScanner.getStartPos() >= originalRange.end) {
- const token =
+ const tokenInfo =
formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() :
formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token :
undefined;
- if (token) {
+ if (tokenInfo) {
+ const parent = findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)?.parent || previousParent!;
processPair(
- token,
- sourceFile.getLineAndCharacterOfPosition(token.pos).line,
- enclosingNode,
+ tokenInfo,
+ sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line,
+ parent,
previousRange,
previousRangeStartLine!,
previousParent!,
- enclosingNode,
+ parent,
/*dynamicIndentation*/ undefined);
}
}
diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts
index 41845616bbe4b..d5c384e9161cc 100644
--- a/src/services/preProcess.ts
+++ b/src/services/preProcess.ts
@@ -345,6 +345,42 @@ namespace ts {
break;
}
+ if (scanner.getToken() === SyntaxKind.TemplateHead) {
+ const stack = [scanner.getToken()];
+ let token = scanner.scan();
+ loop: while (length(stack)) {
+ switch (token) {
+ case SyntaxKind.EndOfFileToken:
+ break loop;
+ case SyntaxKind.ImportKeyword:
+ tryConsumeImport();
+ break;
+ case SyntaxKind.TemplateHead:
+ stack.push(token);
+ break;
+ case SyntaxKind.OpenBraceToken:
+ if (length(stack)) {
+ stack.push(token);
+ }
+ break;
+ case SyntaxKind.CloseBraceToken:
+ if (length(stack)) {
+ if (lastOrUndefined(stack) === SyntaxKind.TemplateHead) {
+ if (scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === SyntaxKind.TemplateTail) {
+ stack.pop();
+ }
+ }
+ else {
+ stack.pop();
+ }
+ }
+ break;
+ }
+ token = scanner.scan();
+ }
+ nextToken();
+ }
+
// check if at least one of alternative have moved scanner forward
if (tryConsumeDeclare() ||
tryConsumeImport() ||
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index 016eb35227eda..e0465bce94eef 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -1256,8 +1256,10 @@ namespace ts {
* Finds the rightmost token satisfying `token.end <= position`,
* excluding `JsxText` tokens containing only whitespace.
*/
- export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, excludeJsdoc?: boolean): Node | undefined {
- const result = find(startNode || sourceFile);
+ export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode: Node, excludeJsdoc?: boolean): Node | undefined;
+ export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, excludeJsdoc?: boolean): Node | undefined;
+ export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode?: Node, excludeJsdoc?: boolean): Node | undefined {
+ const result = find((startNode || sourceFile) as Node);
Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
@@ -1322,7 +1324,7 @@ namespace ts {
return isToken(n) && !isWhiteSpaceOnlyJsxText(n);
}
- function findRightmostToken(n: Node, sourceFile: SourceFile): Node | undefined {
+ function findRightmostToken(n: Node, sourceFile: SourceFileLike): Node | undefined {
if (isNonWhitespaceToken(n)) {
return n;
}
@@ -1339,7 +1341,7 @@ namespace ts {
/**
* Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens.
*/
- function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number, sourceFile: SourceFile, parentKind: SyntaxKind): Node | undefined {
+ function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number, sourceFile: SourceFileLike, parentKind: SyntaxKind): Node | undefined {
for (let i = exclusiveStartPosition - 1; i >= 0; i--) {
const child = children[i];
diff --git a/src/testRunner/unittests/services/preProcessFile.ts b/src/testRunner/unittests/services/preProcessFile.ts
index fb7a7e62649d4..a6369d6e4d4cf 100644
--- a/src/testRunner/unittests/services/preProcessFile.ts
+++ b/src/testRunner/unittests/services/preProcessFile.ts
@@ -176,6 +176,177 @@ describe("unittests:: services:: PreProcessFile:", () => {
});
});
+ it("Correctly ignore commented imports following template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("/**" + "\n" +
+ " * Before" + "\n" +
+ " * ```" + "\n" +
+ " * import * as a from \"a\";" + "\n" +
+ " * ```" + "\n" +
+ " */" + "\n" +
+ "type Foo = `${string}`;" + "\n" +
+ "/**" + "\n" +
+ " * After" + "\n" +
+ " * ```" + "\n" +
+ " * import { B } from \"b\";" + "\n" +
+ " * import * as c from \"c\";" + "\n" +
+ " * ```" + "\n" +
+ " */",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns imports after a template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("`${foo}`; import \"./foo\";",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "./foo", pos: 17, end: 22 }
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns dynamic imports from template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("`${(
Text `` ${} text {} " + "\n" +
+ "${import(\"a\")} {import(\"b\")} " + "\n" +
+ "${/* A comment */} ${/* import(\"ignored\") */}
)}`",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "a", pos: 39, end: 40 },
+ { fileName: "b", pos: 53, end: 54 }
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns dynamic imports from nested template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("`${foo(`${bar(`${import(\"a\")} ${import(\"b\")}`, `${baz(`${import(\"c\") ${import(\"d\")}`)}`)}`)}`",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "a", pos: 24, end: 25 },
+ { fileName: "b", pos: 39, end: 40 },
+ { fileName: "c", pos: 64, end: 65 },
+ { fileName: "d", pos: 78, end: 79 },
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns dynamic imports from tagged template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("foo`${ fn({ a: 100 }, import(\"a\"), `${import(\"b\")}`, import(\"c\"), `${import(\"d\")} foo`, import(\"e\")) }`",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "a", pos: 29, end: 30 },
+ { fileName: "b", pos: 45, end: 46 },
+ { fileName: "c", pos: 60, end: 61 },
+ { fileName: "d", pos: 76, end: 77 },
+ { fileName: "e", pos: 95, end: 96 },
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns dynamic imports from template expression and imports following it", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("const x = `hello ${await import(\"a\").default}`;" + "\n\n" +
+ "import { y } from \"b\";",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "a", pos: 32, end: 33 },
+ { fileName: "b", pos: 67, end: 68 },
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns dynamic imports from template expressions and other imports", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("const x = `x ${await import(\"a\").default}`;" + "\n\n" +
+ "import { y } from \"b\";" + "\n" +
+ "const y = `y ${import(\"c\")}`;" + "\n\n" +
+ "import { d } from \"d\";",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [
+ { fileName: "a", pos: 28, end: 29 },
+ { fileName: "b", pos: 63, end: 64 },
+ { fileName: "c", pos: 90, end: 91 },
+ { fileName: "d", pos: 117, end: 118 },
+ ],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
+ it("Correctly returns empty importedFiles with incorrect template expression", () => {
+ /* eslint-disable no-template-curly-in-string */
+ test("const foo = `${",
+ /*readImportFile*/ true,
+ /*detectJavaScriptImports*/ true,
+ {
+ referencedFiles: [],
+ typeReferenceDirectives: [],
+ libReferenceDirectives: [],
+ importedFiles: [],
+ ambientExternalModules: undefined,
+ isLibFile: false
+ });
+ /* eslint-enable no-template-curly-in-string */
+ });
+
it("Correctly return ES6 exports", () => {
test("export * from \"m1\";" + "\n" +
"export {a} from \"m2\";" + "\n" +
diff --git a/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols
index cf1ed59e66d6e..be0559bfe5251 100644
--- a/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols
+++ b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols
@@ -297,7 +297,7 @@ export class IterableWeakMap implements WeakMap {
Object.defineProperties(IterableWeakMap.prototype, {
>Object.defineProperties : Symbol(ObjectConstructor.defineProperties, Decl(lib.es5.d.ts, --, --))
->Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.object.d.ts, --, --))
+>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>defineProperties : Symbol(ObjectConstructor.defineProperties, Decl(lib.es5.d.ts, --, --))
>IterableWeakMap.prototype : Symbol(IterableWeakMap.prototype)
>IterableWeakMap : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
@@ -322,7 +322,7 @@ Object.defineProperties(IterableWeakMap.prototype, {
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 89, 23))
>Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value : Symbol(PropertyDescriptor.value, Decl(lib.es5.d.ts, --, --))
>Object.getOwnPropertyDescriptor : Symbol(ObjectConstructor.getOwnPropertyDescriptor, Decl(lib.es5.d.ts, --, --))
->Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.object.d.ts, --, --))
+>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>getOwnPropertyDescriptor : Symbol(ObjectConstructor.getOwnPropertyDescriptor, Decl(lib.es5.d.ts, --, --))
IterableWeakMap.prototype,
diff --git a/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.symbols b/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.symbols
index 72d4478539d77..9874e516a2b75 100644
--- a/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.symbols
+++ b/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.symbols
@@ -72,7 +72,7 @@ const query = Object.entries(obj).map(
>Object.entries(obj).map( ([k, v]) => `${k}=${encodeURIComponent(v)}`).join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --))
>Object.entries(obj).map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
>Object.entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
->Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.object.d.ts, --, --))
+>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>entries : Symbol(ObjectConstructor.entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>obj : Symbol(obj, Decl(inferenceOptionalPropertiesToIndexSignatures.ts, 16, 5))
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
diff --git a/tests/baselines/reference/parser0_004152.errors.txt b/tests/baselines/reference/parser0_004152.errors.txt
index a1790a5f7305c..e0fc3f48e0843 100644
--- a/tests/baselines/reference/parser0_004152.errors.txt
+++ b/tests/baselines/reference/parser0_004152.errors.txt
@@ -1,6 +1,6 @@
tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,28): error TS2304: Cannot find name 'DisplayPosition'.
tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,45): error TS1137: Expression or comma expected.
-tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,46): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
+tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,46): error TS1005: ';' expected.
tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,49): error TS1005: ';' expected.
tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,51): error TS2300: Duplicate identifier '3'.
tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(2,52): error TS1005: ';' expected.
@@ -41,7 +41,7 @@ tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts(3,25): error T
~
!!! error TS1137: Expression or comma expected.
~
-!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
+!!! error TS1005: ';' expected.
~
!!! error TS1005: ';' expected.
~
diff --git a/tests/baselines/reference/unionTypeInference.symbols b/tests/baselines/reference/unionTypeInference.symbols
index a4a24b15ebfcc..11fdc52396485 100644
--- a/tests/baselines/reference/unionTypeInference.symbols
+++ b/tests/baselines/reference/unionTypeInference.symbols
@@ -230,7 +230,7 @@ async function fun(deepPromised: DeepPromised) {
for (const value of Object.values(deepPromisedWithIndexer)) {
>value : Symbol(value, Decl(unionTypeInference.ts, 62, 14))
>Object.values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
->Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.object.d.ts, --, --))
+>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>deepPromisedWithIndexer : Symbol(deepPromisedWithIndexer, Decl(unionTypeInference.ts, 61, 9))
diff --git a/tests/cases/fourslash/formatOnTypeOpenCurlyWithBraceCompletion.ts b/tests/cases/fourslash/formatOnTypeOpenCurlyWithBraceCompletion.ts
new file mode 100644
index 0000000000000..b303b1ea62d6d
--- /dev/null
+++ b/tests/cases/fourslash/formatOnTypeOpenCurlyWithBraceCompletion.ts
@@ -0,0 +1,12 @@
+///
+
+//// if (foo) {
+//// if (bar) {/**/}
+//// }
+
+goTo.marker("");
+format.onType("", "{");
+verify.currentFileContentIs(
+`if (foo) {
+ if (bar) { }
+}`);
diff --git a/tests/cases/fourslash/parserCorruptionAfterMapInClass.ts b/tests/cases/fourslash/parserCorruptionAfterMapInClass.ts
new file mode 100644
index 0000000000000..65bc6c5b1ad70
--- /dev/null
+++ b/tests/cases/fourslash/parserCorruptionAfterMapInClass.ts
@@ -0,0 +1,17 @@
+///
+
+// @target: esnext
+// @lib: es2015
+// @strict: true
+
+//// class C {
+//// map = new Set/*$*/
+////
+//// foo() {
+////
+//// }
+//// }
+
+goTo.marker('$');
+edit.insert('()');
+verify.getSyntacticDiagnostics([]);