diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f05c9b40df23..a483eae180310 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -51606,6 +51606,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let current: Node = node; while (current) { if (isFunctionLikeOrClassStaticBlockDeclaration(current)) { + if (node.label) { + const functionOrClassLike = current as FunctionLikeDeclaration | ClassStaticBlockDeclaration; + if (functionOrClassLike.body) { + const relatedInfo = forEachChild(functionOrClassLike.body, childNode => { + const labeledStatement = childNode as LabeledStatement; + if (labeledStatement.kind === SyntaxKind.LabeledStatement && labeledStatement.label.escapedText === node.label!.escapedText) { + return createDiagnosticForNode(labeledStatement.label, Diagnostics.Label_defined_here, unescapeLeadingUnderscores(labeledStatement.label.escapedText)); + } + }); + + if (relatedInfo) { + const diagnostic = createDiagnosticForNode(node, Diagnostics.Label_0_used_before_declaration, unescapeLeadingUnderscores(node.label.escapedText)); + diagnostic.relatedInformation = [relatedInfo]; + diagnostics.add(diagnostic); + return true; + } + } + } + return grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 850d5ca1022af..6828778bc3eb3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -8353,5 +8353,13 @@ "String literal import and export names are not supported when the '--module' flag is set to 'es2015' or 'es2020'.": { "category": "Error", "code": 18057 + }, + "Label '{0}' used before declaration.": { + "category": "Error", + "code": 18058 + }, + "Label defined here": { + "category": "Error", + "code": 18059 } } diff --git a/tests/baselines/reference/breakTarget7.errors.txt b/tests/baselines/reference/breakTarget7.errors.txt new file mode 100644 index 0000000000000..07eebeb3c5982 --- /dev/null +++ b/tests/baselines/reference/breakTarget7.errors.txt @@ -0,0 +1,12 @@ +breakTarget7.ts(2,5): error TS18058: Label 'target' used before declaration. + + +==== breakTarget7.ts (1 errors) ==== + function functionContainingBreak() { + break target; + ~~~~~~~~~~~~~ +!!! error TS18058: Label 'target' used before declaration. +!!! related TS18059 breakTarget7.ts:3:5: Label defined here + target:; + } + \ No newline at end of file diff --git a/tests/baselines/reference/breakTarget7.js b/tests/baselines/reference/breakTarget7.js new file mode 100644 index 0000000000000..89d95dac1f4e5 --- /dev/null +++ b/tests/baselines/reference/breakTarget7.js @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/breakTarget7.ts] //// + +//// [breakTarget7.ts] +function functionContainingBreak() { + break target; + target:; +} + + +//// [breakTarget7.js] +function functionContainingBreak() { + break target; + target: ; +} diff --git a/tests/baselines/reference/breakTarget7.symbols b/tests/baselines/reference/breakTarget7.symbols new file mode 100644 index 0000000000000..5e8de2b1939d2 --- /dev/null +++ b/tests/baselines/reference/breakTarget7.symbols @@ -0,0 +1,10 @@ +//// [tests/cases/compiler/breakTarget7.ts] //// + +=== breakTarget7.ts === +function functionContainingBreak() { +>functionContainingBreak : Symbol(functionContainingBreak, Decl(breakTarget7.ts, 0, 0)) + + break target; + target:; +} + diff --git a/tests/baselines/reference/breakTarget7.types b/tests/baselines/reference/breakTarget7.types new file mode 100644 index 0000000000000..aeed0c998d000 --- /dev/null +++ b/tests/baselines/reference/breakTarget7.types @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/breakTarget7.ts] //// + +=== breakTarget7.ts === +function functionContainingBreak() { +>functionContainingBreak : () => void +> : ^^^^^^^^^^ + + break target; +>target : any +> : ^^^ + + target:; +>target : any +> : ^^^ +} + diff --git a/tests/cases/compiler/breakTarget7.ts b/tests/cases/compiler/breakTarget7.ts new file mode 100644 index 0000000000000..c9bd4edc31cdf --- /dev/null +++ b/tests/cases/compiler/breakTarget7.ts @@ -0,0 +1,5 @@ +// @allowUnusedLabels: true +function functionContainingBreak() { + break target; + target:; +}