@@ -102,6 +102,7 @@ import {
102
102
countWhere,
103
103
createBinaryExpressionTrampoline,
104
104
createCompilerDiagnostic,
105
+ createDetachedDiagnostic,
105
106
createDiagnosticCollection,
106
107
createDiagnosticForFileFromMessageChain,
107
108
createDiagnosticForNode,
@@ -123,6 +124,7 @@ import {
123
124
createPrinterWithRemoveCommentsNeverAsciiEscape,
124
125
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
125
126
createPropertyNameNodeForIdentifierOrLiteral,
127
+ createScanner,
126
128
createSymbolTable,
127
129
createSyntacticTypeNodeBuilder,
128
130
createTextWriter,
@@ -937,6 +939,7 @@ import {
937
939
rangeOfTypeParameters,
938
940
ReadonlyKeyword,
939
941
reduceLeft,
942
+ RegularExpressionLiteral,
940
943
RelationComparisonResult,
941
944
relativeComplement,
942
945
removeExtension,
@@ -953,6 +956,7 @@ import {
953
956
ReverseMappedType,
954
957
sameMap,
955
958
SatisfiesExpression,
959
+ Scanner,
956
960
scanTokenAtPosition,
957
961
ScriptKind,
958
962
ScriptTarget,
@@ -1446,6 +1450,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1446
1450
var requestedExternalEmitHelperNames = new Set<string>();
1447
1451
var requestedExternalEmitHelpers: ExternalEmitHelpers;
1448
1452
var externalHelpersModule: Symbol;
1453
+ var scanner: Scanner | undefined;
1449
1454
1450
1455
var Symbol = objectAllocator.getSymbolConstructor();
1451
1456
var Type = objectAllocator.getTypeConstructor();
@@ -6689,7 +6694,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6689
6694
if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) {
6690
6695
return node;
6691
6696
}
6692
- return setTextRange(context, factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes)), node);
6697
+ return setTextRange(context, factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes, deepCloneOrReuseNode )), node);
6693
6698
}
6694
6699
6695
6700
function deepCloneOrReuseNodes(
@@ -31353,6 +31358,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
31353
31358
}
31354
31359
}
31355
31360
31361
+ function checkGrammarRegularExpressionLiteral(node: RegularExpressionLiteral) {
31362
+ const sourceFile = getSourceFileOfNode(node);
31363
+ if (!hasParseDiagnostics(sourceFile)) {
31364
+ let lastError: DiagnosticWithLocation | undefined;
31365
+ scanner ??= createScanner(ScriptTarget.ESNext, /*skipTrivia*/ true);
31366
+ scanner.setScriptTarget(sourceFile.languageVersion);
31367
+ scanner.setLanguageVariant(sourceFile.languageVariant);
31368
+ scanner.setOnError((message, length, arg0) => {
31369
+ // emulate `parseErrorAtPosition` from parser.ts
31370
+ const start = scanner!.getTokenEnd();
31371
+ if (message.category === DiagnosticCategory.Message && lastError && start === lastError.start && length === lastError.length) {
31372
+ const error = createDetachedDiagnostic(sourceFile.fileName, sourceFile.text, start, length, message, arg0);
31373
+ addRelatedInfo(lastError, error);
31374
+ }
31375
+ else if (!lastError || start !== lastError.start) {
31376
+ lastError = createFileDiagnostic(sourceFile, start, length, message, arg0);
31377
+ diagnostics.add(lastError);
31378
+ }
31379
+ });
31380
+ scanner.setText(sourceFile.text, node.pos, node.end - node.pos);
31381
+ try {
31382
+ scanner.scan();
31383
+ Debug.assert(scanner.reScanSlashToken(/*reportErrors*/ true) === SyntaxKind.RegularExpressionLiteral, "Expected scanner to rescan RegularExpressionLiteral");
31384
+ return !!lastError;
31385
+ }
31386
+ finally {
31387
+ scanner.setText("");
31388
+ scanner.setOnError(/*onError*/ undefined);
31389
+ }
31390
+ }
31391
+ return false;
31392
+ }
31393
+
31394
+ function checkRegularExpressionLiteral(node: RegularExpressionLiteral) {
31395
+ const nodeLinks = getNodeLinks(node);
31396
+ if (!(nodeLinks.flags & NodeCheckFlags.TypeChecked)) {
31397
+ nodeLinks.flags |= NodeCheckFlags.TypeChecked;
31398
+ addLazyDiagnostic(() => checkGrammarRegularExpressionLiteral(node));
31399
+ }
31400
+ return globalRegExpType;
31401
+ }
31402
+
31356
31403
function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type {
31357
31404
if (languageVersion < LanguageFeatureMinimumTarget.SpreadElements) {
31358
31405
checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray);
@@ -38493,7 +38540,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
38493
38540
parent = parent.parent;
38494
38541
}
38495
38542
if (operator === SyntaxKind.AmpersandAmpersandToken || isIfStatement(parent)) {
38496
- checkTestingKnownTruthyCallableOrAwaitableType (node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined);
38543
+ checkTestingKnownTruthyCallableOrAwaitableOrEnumMemberType (node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined);
38497
38544
}
38498
38545
checkTruthinessOfType(leftType, node.left);
38499
38546
}
@@ -39127,7 +39174,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
39127
39174
39128
39175
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
39129
39176
const type = checkTruthinessExpression(node.condition, checkMode);
39130
- checkTestingKnownTruthyCallableOrAwaitableType (node.condition, type, node.whenTrue);
39177
+ checkTestingKnownTruthyCallableOrAwaitableOrEnumMemberType (node.condition, type, node.whenTrue);
39131
39178
const type1 = checkExpression(node.whenTrue, checkMode);
39132
39179
const type2 = checkExpression(node.whenFalse, checkMode);
39133
39180
return getUnionType([type1, type2], UnionReduction.Subtype);
@@ -39662,7 +39709,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
39662
39709
case SyntaxKind.TemplateExpression:
39663
39710
return checkTemplateExpression(node as TemplateExpression);
39664
39711
case SyntaxKind.RegularExpressionLiteral:
39665
- return globalRegExpType ;
39712
+ return checkRegularExpressionLiteral(node as RegularExpressionLiteral) ;
39666
39713
case SyntaxKind.ArrayLiteralExpression:
39667
39714
return checkArrayLiteral(node as ArrayLiteralExpression, checkMode, forceTuple);
39668
39715
case SyntaxKind.ObjectLiteralExpression:
@@ -43101,7 +43148,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
43101
43148
// Grammar checking
43102
43149
checkGrammarStatementInAmbientContext(node);
43103
43150
const type = checkTruthinessExpression(node.expression);
43104
- checkTestingKnownTruthyCallableOrAwaitableType (node.expression, type, node.thenStatement);
43151
+ checkTestingKnownTruthyCallableOrAwaitableOrEnumMemberType (node.expression, type, node.thenStatement);
43105
43152
checkSourceElement(node.thenStatement);
43106
43153
43107
43154
if (node.thenStatement.kind === SyntaxKind.EmptyStatement) {
@@ -43111,7 +43158,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
43111
43158
checkSourceElement(node.elseStatement);
43112
43159
}
43113
43160
43114
- function checkTestingKnownTruthyCallableOrAwaitableType (condExpr: Expression, condType: Type, body?: Statement | Expression) {
43161
+ function checkTestingKnownTruthyCallableOrAwaitableOrEnumMemberType (condExpr: Expression, condType: Type, body?: Statement | Expression) {
43115
43162
if (!strictNullChecks) return;
43116
43163
bothHelper(condExpr, body);
43117
43164
@@ -43136,6 +43183,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
43136
43183
return;
43137
43184
}
43138
43185
const type = location === condExpr ? condType : checkTruthinessExpression(location);
43186
+ if (type.flags & TypeFlags.EnumLiteral && isPropertyAccessExpression(location) && (getNodeLinks(location.expression).resolvedSymbol ?? unknownSymbol).flags & SymbolFlags.Enum) {
43187
+ // EnumLiteral type at condition with known value is always truthy or always falsy, likely an error
43188
+ error(location, Diagnostics.This_condition_will_always_return_0, !!(type as LiteralType).value ? "true" : "false");
43189
+ return;
43190
+ }
43139
43191
const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression);
43140
43192
if (!hasTypeFacts(type, TypeFacts.Truthy) || isPropertyExpressionCast) return;
43141
43193
@@ -46279,7 +46331,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
46279
46331
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
46280
46332
return;
46281
46333
}
46282
- if (!checkGrammarModifiers(node) && hasEffectiveModifiers( node) ) {
46334
+ if (!checkGrammarModifiers(node) && node.modifiers ) {
46283
46335
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
46284
46336
}
46285
46337
if (checkExternalImportOrExportDeclaration(node)) {
0 commit comments