From 768c9ed8d7f2faa7c1fcf979e497f17f8442f811 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Jun 2019 10:57:09 -0700 Subject: [PATCH] Handle jsx Opening, Closing and Self closing tags --- src/services/findAllReferences.ts | 10 ++++++++-- src/services/services.ts | 10 ++++++++-- tests/cases/fourslash/findReferencesJSXTagName.ts | 6 +++--- tests/cases/fourslash/findReferencesJSXTagName3.ts | 12 ++++++------ tests/cases/fourslash/tsxFindAllReferences1.ts | 2 +- tests/cases/fourslash/tsxFindAllReferences4.ts | 2 +- tests/cases/fourslash/tsxFindAllReferences5.ts | 10 +++++----- tests/cases/fourslash/tsxFindAllReferences8.ts | 12 ++++++------ .../tsxFindAllReferencesUnionElementType1.ts | 2 +- .../tsxFindAllReferencesUnionElementType2.ts | 2 +- tests/cases/fourslash/tsxRename1.ts | 2 +- tests/cases/fourslash/tsxRename4.ts | 6 +++--- tests/cases/fourslash/tsxRename6.ts | 10 +++++----- tests/cases/fourslash/tsxRename9.ts | 12 ++++++------ 14 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index ae31ab544f3..a2eb4f3ec29 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -48,11 +48,17 @@ namespace ts.FindAllReferences { return getDeclarationForDeclarationSpan(node); } - // TODO(shkamat):: - // JSXOpeningElement or JSXElement for tagName ? if (!node.parent) return undefined; if (!isDeclaration(node.parent) && !isExportAssignment(node.parent)) { + // Jsx Tags + if (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) { + return node.parent.parent; + } + else if (isJsxSelfClosingElement(node.parent)) { + return node.parent; + } + // Special property assignment in javascript if (isInJSFile(node)) { const binaryExpression = isBinaryExpression(node.parent) ? diff --git a/src/services/services.ts b/src/services/services.ts index cae6ce7ac47..032dee4a40c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1577,8 +1577,14 @@ namespace ts { const node = getTouchingPropertyName(sourceFile, position); if (isIdentifier(node) && (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) && isIntrinsicJsxName(node.escapedText)) { const { openingElement, closingElement } = node.parent.parent; - return [openingElement, closingElement].map((node): RenameLocation => - ({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) })); + return [openingElement, closingElement].map(node => { + const result: RenameLocation = { + fileName: sourceFile.fileName, + textSpan: createTextSpanFromNode(node.tagName, sourceFile) + }; + FindAllReferences.setDeclarationSpan(result, sourceFile, node.parent); + return result; + }); } else { return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, isForRename: true }, diff --git a/tests/cases/fourslash/findReferencesJSXTagName.ts b/tests/cases/fourslash/findReferencesJSXTagName.ts index ec011671c9e..cd6675c7c3f 100644 --- a/tests/cases/fourslash/findReferencesJSXTagName.ts +++ b/tests/cases/fourslash/findReferencesJSXTagName.ts @@ -4,14 +4,14 @@ ////[|import { [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 0 |}SubmissionComp|] } from "./RedditSubmission"|] ////function displaySubreddit(subreddit: string) { //// let components = submissions -//// .map((value, index) => <[|SubmissionComp|] key={ index } elementPosition= { index } {...value.data} />); +//// .map((value, index) => [|<[|{| "declarationRangeIndex": 2 |}SubmissionComp|] key={ index } elementPosition= { index } {...value.data} />|]); ////} // @Filename: RedditSubmission.ts -////export const [|[|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 3 |}SubmissionComp|] = (submission: SubmissionProps) => +////export const [|[|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 4 |}SubmissionComp|] = (submission: SubmissionProps) => ////
; -const [r0Def, r0, r1, r2Def, r2] = test.ranges(); +const [r0Def, r0, r1Def, r1, r2Def, r2] = test.ranges(); const imports = { definition: "(alias) const SubmissionComp: (submission: any) => any\nimport SubmissionComp", ranges: [r0, r1] }; const def = { definition: "const SubmissionComp: (submission: any) => any", ranges: [r2] }; verify.referenceGroups([r0, r1], [imports, def]); diff --git a/tests/cases/fourslash/findReferencesJSXTagName3.ts b/tests/cases/fourslash/findReferencesJSXTagName3.ts index afd90562777..b4e87388f99 100644 --- a/tests/cases/fourslash/findReferencesJSXTagName3.ts +++ b/tests/cases/fourslash/findReferencesJSXTagName3.ts @@ -11,16 +11,16 @@ ////} //// ////[|const [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 2 |}Comp|] = () => -//// <[|div|]> +//// [|<[|{| "declarationRangeIndex": 4 |}div|]> //// Some content -//// <[|div|]>More content -//// ;|] +//// [|<[|{| "declarationRangeIndex": 6 |}div|]>More content|] +//// |];|] //// -////const x = <[|Comp|]> +////const x = [|<[|{| "declarationRangeIndex": 10 |}Comp|]> //// Content -////; +////|]; -const [d0Def, d0, c0Def, c0, d1, d2, d3, d4, c1, c2] = test.ranges(); +const [d0Def, d0, c0Def, c0, d1Def, d1, d2Def, d2, d3, d4, c1Def, c1, c2] = test.ranges(); const allD = [d0, d1, d2, d3, d4]; const allC = [c0, c1, c2]; diff --git a/tests/cases/fourslash/tsxFindAllReferences1.ts b/tests/cases/fourslash/tsxFindAllReferences1.ts index e943c4e69bf..f5d0a2e7488 100644 --- a/tests/cases/fourslash/tsxFindAllReferences1.ts +++ b/tests/cases/fourslash/tsxFindAllReferences1.ts @@ -11,7 +11,7 @@ //// span: { n: string; }; //// } //// } -//// var x = <[|div|] />; +//// var x = [|<[|{| "declarationRangeIndex": 2 |}div|] />|]; verify.singleReferenceGroup( `(property) JSX.IntrinsicElements.div: { diff --git a/tests/cases/fourslash/tsxFindAllReferences4.ts b/tests/cases/fourslash/tsxFindAllReferences4.ts index e761be8eb4d..38433bb7f21 100644 --- a/tests/cases/fourslash/tsxFindAllReferences4.ts +++ b/tests/cases/fourslash/tsxFindAllReferences4.ts @@ -14,6 +14,6 @@ //// }|] //// //// -//// var x = <[|MyClass|] name='hello'>; +//// var x = [|<[|{| "declarationRangeIndex" : 2 |}MyClass|] name='hello'>|]; verify.singleReferenceGroup("class MyClass", "MyClass"); diff --git a/tests/cases/fourslash/tsxFindAllReferences5.ts b/tests/cases/fourslash/tsxFindAllReferences5.ts index ee3e0e7e4bd..804943ec85d 100644 --- a/tests/cases/fourslash/tsxFindAllReferences5.ts +++ b/tests/cases/fourslash/tsxFindAllReferences5.ts @@ -16,11 +16,11 @@ //// optional?: boolean //// } //// [|declare function [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 0 |}Opt|](attributes: OptionPropBag): JSX.Element;|] -//// let opt = <[|Opt|] />; -//// let opt1 = <[|Opt|] propx={100} propString />; -//// let opt2 = <[|Opt|] propx={100} optional/>; -//// let opt3 = <[|Opt|] wrong />; -//// let opt4 = <[|Opt|] propx={100} propString="hi" />; +//// let opt = [|<[|{| "declarationRangeIndex": 2 |}Opt|] />|]; +//// let opt1 = [|<[|{| "declarationRangeIndex": 4 |}Opt|] propx={100} propString />|]; +//// let opt2 = [|<[|{| "declarationRangeIndex": 6 |}Opt|] propx={100} optional/>|]; +//// let opt3 = [|<[|{| "declarationRangeIndex": 8 |}Opt|] wrong />|]; +//// let opt4 = [|<[|{| "declarationRangeIndex": 10 |}Opt|] propx={100} propString="hi" />|]; verify.singleReferenceGroup( "function Opt(attributes: OptionPropBag): JSX.Element", diff --git a/tests/cases/fourslash/tsxFindAllReferences8.ts b/tests/cases/fourslash/tsxFindAllReferences8.ts index a5683cfb330..6dcd94e726b 100644 --- a/tests/cases/fourslash/tsxFindAllReferences8.ts +++ b/tests/cases/fourslash/tsxFindAllReferences8.ts @@ -23,12 +23,12 @@ //// [|declare function [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 0 |}MainButton|](buttonProps: ButtonProps): JSX.Element;|] //// [|declare function [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 2 |}MainButton|](linkProps: LinkProps): JSX.Element;|] //// [|declare function [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 4 |}MainButton|](props: ButtonProps | LinkProps): JSX.Element;|] -//// let opt = <[|MainButton|] />; -//// let opt = <[|MainButton|] children="chidlren" />; -//// let opt = <[|MainButton|] onClick={()=>{}} />; -//// let opt = <[|MainButton|] onClick={()=>{}} ignore-prop />; -//// let opt = <[|MainButton|] goTo="goTo" />; -//// let opt = <[|MainButton|] wrong />; +//// let opt = [|<[|{| "declarationRangeIndex": 6 |}MainButton|] />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 8 |}MainButton|] children="chidlren" />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 10 |}MainButton|] onClick={()=>{}} />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 12 |}MainButton|] onClick={()=>{}} ignore-prop />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 14 |}MainButton|] goTo="goTo" />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 16 |}MainButton|] wrong />|]; verify.singleReferenceGroup( "function MainButton(buttonProps: ButtonProps): JSX.Element (+2 overloads)", diff --git a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts index dc85960bb6d..60b95f1b43e 100644 --- a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts +++ b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts @@ -19,7 +19,7 @@ //// } //// [|var [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 0 |}SFCComp|] = SFC1 || SFC2;|] -//// <[|SFCComp|] x={ "hi" } /> +//// [|<[|{| "declarationRangeIndex": 2 |}SFCComp|] x={ "hi" } />|] verify.singleReferenceGroup(`var SFCComp: ((prop: { x: number; diff --git a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts index ffb33919fd4..cb4151aa3c5 100644 --- a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts +++ b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts @@ -18,6 +18,6 @@ //// } //// [|var [|{| "isWriteAccess": true, "isDefinition": true, "declarationRangeIndex": 0 |}RCComp|] = RC1 || RC2;|] -//// <[|RCComp|] /> +//// [|<[|{| "declarationRangeIndex": 2 |}RCComp|] />|] verify.singleReferenceGroup("var RCComp: typeof RC1", "RCComp"); diff --git a/tests/cases/fourslash/tsxRename1.ts b/tests/cases/fourslash/tsxRename1.ts index 047bc391a38..e16c390f4e5 100644 --- a/tests/cases/fourslash/tsxRename1.ts +++ b/tests/cases/fourslash/tsxRename1.ts @@ -11,5 +11,5 @@ //// span: { n: string; }; //// } //// } -//// var x = <[|div|] />; +//// var x = [|<[|{| "declarationRangeIndex": 2 |}div|] />|]; verify.rangesWithSameTextAreRenameLocations("div"); diff --git a/tests/cases/fourslash/tsxRename4.ts b/tests/cases/fourslash/tsxRename4.ts index 0bc9fa10f0c..f9c33972ecd 100644 --- a/tests/cases/fourslash/tsxRename4.ts +++ b/tests/cases/fourslash/tsxRename4.ts @@ -11,10 +11,10 @@ ////} ////[|class [|{| "declarationRangeIndex": 0 |}MyClass|] {}|] //// -////<[|MyClass|]>; -////<[|MyClass|]/>; +////[|<[|{| "declarationRangeIndex": 2 |}MyClass|]>|]; +////[|<[|{| "declarationRangeIndex": 5 |}MyClass|]/>|]; //// -////<[|div|]> +////[|<[|{| "declarationRangeIndex": 7 |}div|]> |] verify.noErrors(); verify.rangesWithSameTextAreRenameLocations("MyClass", "div"); \ No newline at end of file diff --git a/tests/cases/fourslash/tsxRename6.ts b/tests/cases/fourslash/tsxRename6.ts index 1cafd1332b0..320f3e6ac6b 100644 --- a/tests/cases/fourslash/tsxRename6.ts +++ b/tests/cases/fourslash/tsxRename6.ts @@ -16,10 +16,10 @@ //// optional?: boolean //// } //// [|declare function [|{| "declarationRangeIndex": 0 |}Opt|](attributes: OptionPropBag): JSX.Element;|] -//// let opt = <[|Opt|] />; -//// let opt1 = <[|Opt|] propx={100} propString />; -//// let opt2 = <[|Opt|] propx={100} optional/>; -//// let opt3 = <[|Opt|] wrong />; -//// let opt4 = <[|Opt|] propx={100} propString="hi" />; +//// let opt = [|<[|{| "declarationRangeIndex": 2 |}Opt|] />|]; +//// let opt1 = [|<[|{| "declarationRangeIndex": 4 |}Opt|] propx={100} propString />|]; +//// let opt2 = [|<[|{| "declarationRangeIndex": 6 |}Opt|] propx={100} optional/>|]; +//// let opt3 = [|<[|{| "declarationRangeIndex": 8 |}Opt|] wrong />|]; +//// let opt4 = [|<[|{| "declarationRangeIndex": 10 |}Opt|] propx={100} propString="hi" />|]; verify.rangesWithSameTextAreRenameLocations("Opt"); diff --git a/tests/cases/fourslash/tsxRename9.ts b/tests/cases/fourslash/tsxRename9.ts index 29a54d51cae..0aa8ef8345f 100644 --- a/tests/cases/fourslash/tsxRename9.ts +++ b/tests/cases/fourslash/tsxRename9.ts @@ -23,12 +23,12 @@ //// [|declare function [|{| "declarationRangeIndex": 4 |}MainButton|](buttonProps: ButtonProps): JSX.Element;|] //// [|declare function [|{| "declarationRangeIndex": 6 |}MainButton|](linkProps: LinkProps): JSX.Element;|] //// [|declare function [|{| "declarationRangeIndex": 8 |}MainButton|](props: ButtonProps | LinkProps): JSX.Element;|] -//// let opt = <[|MainButton|] />; -//// let opt = <[|MainButton|] children="chidlren" />; -//// let opt = <[|MainButton|] [|[|{| "declarationRangeIndex": 13 |}onClick|]={()=>{}}|] />; -//// let opt = <[|MainButton|] [|[|{| "declarationRangeIndex": 16 |}onClick|]={()=>{}}|] [|ignore-prop|] />; -//// let opt = <[|MainButton|] [|[|{| "declarationRangeIndex": 20 |}goTo|]="goTo"|] />; -//// let opt = <[|MainButton|] [|wrong|] />; +//// let opt = [|<[|{| "declarationRangeIndex": 10 |}MainButton|] />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 12 |}MainButton|] children="chidlren" />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 14 |}MainButton|] [|[|{| "declarationRangeIndex": 16 |}onClick|]={()=>{}}|] />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 18 |}MainButton|] [|[|{| "declarationRangeIndex": 20 |}onClick|]={()=>{}}|] [|ignore-prop|] />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 23 |}MainButton|] [|[|{| "declarationRangeIndex": 25 |}goTo|]="goTo"|] />|]; +//// let opt = [|<[|{| "declarationRangeIndex": 27 |}MainButton|] [|wrong|] />|]; verify.rangesWithSameTextAreRenameLocations( "onClick",