diff --git a/src/services/services.ts b/src/services/services.ts index 9a88490ac3..81a192fe6c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2148,20 +2148,16 @@ module ts { // Labels if (isLabelName(node)) { - var labelName = (node).text; - - var labelScope: Node; - if (isJumpStatementTarget(node)) { var labelDefinition = getTargetLabel((node.parent), (node).text); - labelScope = labelDefinition ? labelDefinition.parent : getContainerNode(node); + // if we have a label definition, look within its statement for references, if not, then + // the label is undefined, just return a set of one for the current node. + return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : [getReferenceEntry(node)]; } else { - // it is a label definition and not a target, the scope is the labeledStatement - labelScope = node.parent; + // it is a label definition and not a target, search within the parent labeledStatement + return getLabelReferencesInNode(node.parent, node); } - - return getLabelReferencesInNode(labelScope, labelName); } var symbol = typeInfoResolver.getSymbolInfo(node); @@ -2246,16 +2242,23 @@ module ts { return positions; } - function getLabelReferencesInNode(container: Node, labelName: string): ReferenceEntry[] { + function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferenceEntry[] { var result: ReferenceEntry[] = []; var sourceFile = container.getSourceFile(); + var labelName = targetLabel.text; var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); if (possiblePositions && possiblePositions.length > 0) { possiblePositions.forEach(position => { cancellationToken.throwIfCancellationRequested(); var node = getNodeAtPosition(sourceFile, position); - if (node && isLabelName(node) && node.getWidth() === labelName.length) { + if (!node || node.getWidth() !== labelName.length) { + return; + } + + // Only pick labels that are either the target label, or have a target that is the target label + if (node === targetLabel || + (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) { result.push(getReferenceEntry(node)); } }); diff --git a/tests/cases/fourslash/referencesForLabel2.ts b/tests/cases/fourslash/referencesForLabel2.ts index 5919f568cb..96467158cc 100644 --- a/tests/cases/fourslash/referencesForLabel2.ts +++ b/tests/cases/fourslash/referencesForLabel2.ts @@ -9,4 +9,4 @@ ////} goTo.marker("1"); -verify.referencesCountIs(2); +verify.referencesCountIs(1); diff --git a/tests/cases/fourslash/referencesForLabel5.ts b/tests/cases/fourslash/referencesForLabel5.ts new file mode 100644 index 0000000000..0a465a89f2 --- /dev/null +++ b/tests/cases/fourslash/referencesForLabel5.ts @@ -0,0 +1,28 @@ +/// + +// References to shadowed label + +/////*outer1*/label: while (true) { +//// if (false) break /*outer2*/label; +//// function blah() { +/////*inner1*/label: while (true) { +//// if (false) break /*inner2*/label; +//// } +//// } +//// if (false) break /*outer3*/label; +//// } + +goTo.marker("outer1"); +verify.referencesCountIs(3); + +goTo.marker("outer2"); +verify.referencesCountIs(3); + +goTo.marker("outer3"); +verify.referencesCountIs(3); + +goTo.marker("inner1"); +verify.referencesCountIs(2); + +goTo.marker("inner2"); +verify.referencesCountIs(2); diff --git a/tests/cases/fourslash/referencesForLabel6.ts b/tests/cases/fourslash/referencesForLabel6.ts new file mode 100644 index 0000000000..83c3c8a2fc --- /dev/null +++ b/tests/cases/fourslash/referencesForLabel6.ts @@ -0,0 +1,14 @@ +/// + +// References to lable wiht close names + +/////*1*/labela: while (true) { +/////*2*/labelb: while (false) { break labelb; } +//// break labelc; +////} + +goTo.marker("1"); +verify.referencesCountIs(1); + +goTo.marker("2"); +verify.referencesCountIs(2); \ No newline at end of file