Skip to content

Commit 44d5c44

Browse files
author
Andy
authored
Document highlights for a JSX tag should just be the matching tag, not all references (#16453)
1 parent fd1edd2 commit 44d5c44

File tree

5 files changed

+71
-11
lines changed

5 files changed

+71
-11
lines changed

src/harness/fourslash.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,16 @@ namespace FourSlash {
536536
Harness.IO.log("Unexpected error(s) found. Error list is:");
537537
}
538538

539-
for (const { start, length, messageText } of errors) {
540-
Harness.IO.log(" minChar: " + start +
541-
", limChar: " + (start + length) +
539+
for (const { start, length, messageText, file } of errors) {
540+
Harness.IO.log(" from: " + showPosition(file, start) +
541+
", to: " + showPosition(file, start + length) +
542542
", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n");
543543
}
544+
545+
function showPosition(file: ts.SourceFile, pos: number) {
546+
const { line, character } = ts.getLineAndCharacterOfPosition(file, pos);
547+
return `${line}:${character}`;
548+
}
544549
}
545550

546551
public verifyNoErrors() {
@@ -2671,6 +2676,13 @@ namespace FourSlash {
26712676
this.rangesByText().forEach(ranges => this.verifyRangesAreDocumentHighlights(ranges));
26722677
}
26732678

2679+
public verifyDocumentHighlightsOf(startRange: Range, ranges: Range[]) {
2680+
ts.Debug.assert(ts.contains(ranges, startRange));
2681+
const fileNames = unique(ranges, range => range.fileName);
2682+
this.goToRangeStart(startRange);
2683+
this.verifyDocumentHighlights(ranges, fileNames);
2684+
}
2685+
26742686
public verifyRangesAreDocumentHighlights(ranges?: Range[]) {
26752687
ranges = ranges || this.getRanges();
26762688
const fileNames = unique(ranges, range => range.fileName);
@@ -3885,6 +3897,10 @@ namespace FourSlashInterface {
38853897
this.state.verifyRangesWithSameTextAreDocumentHighlights();
38863898
}
38873899

3900+
public documentHighlightsOf(startRange: FourSlash.Range, ranges: FourSlash.Range[]) {
3901+
this.state.verifyDocumentHighlightsOf(startRange, ranges);
3902+
}
3903+
38883904
public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) {
38893905
this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind, tags);
38903906
}

src/services/documentHighlights.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
/* @internal */
22
namespace ts.DocumentHighlights {
3-
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
3+
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] | undefined {
44
const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
5-
return node && (getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile));
5+
if (!node) return undefined;
6+
7+
if (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent)) {
8+
// For a JSX element, just highlight the matching tag, not all references.
9+
const { openingElement, closingElement } = node.parent.parent;
10+
const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile));
11+
return [{ fileName: sourceFile.fileName, highlightSpans }];
12+
}
13+
14+
return getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile);
615
}
716

817
function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan {
9-
const start = node.getStart(sourceFile);
10-
const end = node.getEnd();
11-
1218
return {
1319
fileName: sourceFile.fileName,
14-
textSpan: createTextSpanFromBounds(start, end),
20+
textSpan: createTextSpanFromNode(node, sourceFile),
1521
kind: HighlightSpanKind.none
1622
};
1723
}

tests/cases/fourslash/findReferencesJSXTagName.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
////export const [|{| "isWriteAccess": true, "isDefinition": true |}SubmissionComp|] = (submission: SubmissionProps) =>
1212
//// <div style={{ fontFamily: "sans-serif" }}></div>;
1313

14-
const ranges = test.ranges();
15-
const [r0, r1, r2] = ranges;
14+
const [r0, r1, r2] = test.ranges();
1615
const imports = { definition: "import SubmissionComp", ranges: [r0, r1] };
1716
const def = { definition: "const SubmissionComp: (submission: any) => any", ranges: [r2] };
1817
verify.referenceGroups([r0, r1], [imports, def]);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @jsx: preserve
4+
5+
// @Filename: /a.tsx
6+
////namespace JSX {
7+
//// export interface Element { }
8+
//// export interface IntrinsicElements {
9+
//// [|{| "isWriteAccess": true, "isDefinition": true |}div|]: any;
10+
//// }
11+
////}
12+
////
13+
////const [|{| "isWriteAccess": true, "isDefinition": true |}Comp|] = () =>
14+
//// <[|div|]>
15+
//// Some content
16+
//// <[|div|]>More content</[|div|]>
17+
//// </[|div|]>;
18+
////
19+
////const x = <[|Comp|]>
20+
//// Content
21+
////</[|Comp|]>;
22+
23+
const ranges = test.ranges();
24+
const [d0, c0, d1, d2, d3, d4, c1, c2] = test.ranges();
25+
26+
const allD = [d0, d1, d2, d3, d4];
27+
const allC = [c0, c1, c2];
28+
29+
verify.singleReferenceGroup("(property) JSX.IntrinsicElements.div: any", allD);
30+
verify.singleReferenceGroup("const Comp: () => JSX.Element", allC);
31+
32+
// For document highlights, we will just do tag matching if on a tag. Otherwise we find-all-references.
33+
verify.documentHighlightsOf(d0, [d0, d1, d2, d3, d4]);
34+
verify.rangesAreDocumentHighlights([d1, d4]);
35+
verify.rangesAreDocumentHighlights([d2, d3]);
36+
37+
verify.documentHighlightsOf(c0, [c0, c1, c2]);
38+
verify.rangesAreDocumentHighlights([c1, c2]);

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ declare namespace FourSlashInterface {
250250
occurrencesAtPositionCount(expectedCount: number): void;
251251
rangesAreDocumentHighlights(ranges?: Range[]): void;
252252
rangesWithSameTextAreDocumentHighlights(): void;
253+
documentHighlightsOf(startRange: Range, ranges: Range[]): void;
253254
completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string): void;
254255
/**
255256
* This method *requires* a contiguous, complete, and ordered stream of classifications for a file.

0 commit comments

Comments
 (0)