mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
fix(29890): wrap variable/method/property to jsx expression
This commit is contained in:
parent
1aaa2ec45e
commit
c75af697af
@ -915,6 +915,9 @@ namespace ts.refactor.extractSymbol {
|
||||
if (range.facts & RangeFacts.IsAsyncFunction) {
|
||||
call = factory.createAwaitExpression(call);
|
||||
}
|
||||
if (isInJSXContent(node)) {
|
||||
call = factory.createJsxExpression(/*dotDotDotToken*/ undefined, call);
|
||||
}
|
||||
|
||||
if (exposedVariableDeclarations.length && !writes) {
|
||||
// No need to mix declarations and writes.
|
||||
@ -1118,12 +1121,16 @@ namespace ts.refactor.extractSymbol {
|
||||
variableType,
|
||||
initializer);
|
||||
|
||||
const localReference = factory.createPropertyAccessExpression(
|
||||
let localReference: Expression = factory.createPropertyAccessExpression(
|
||||
rangeFacts & RangeFacts.InStaticRegion
|
||||
? factory.createIdentifier(scope.name!.getText()) // TODO: GH#18217
|
||||
: factory.createThis(),
|
||||
factory.createIdentifier(localNameText));
|
||||
|
||||
if (isInJSXContent(node)) {
|
||||
localReference = factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference);
|
||||
}
|
||||
|
||||
// Declare
|
||||
const maxInsertionPos = node.pos;
|
||||
const nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope);
|
||||
@ -1194,12 +1201,6 @@ namespace ts.refactor.extractSymbol {
|
||||
const renameLocation = getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true);
|
||||
return { renameFilename, renameLocation, edits };
|
||||
|
||||
function isInJSXContent(node: Node) {
|
||||
if (!isJsxElement(node)) return false;
|
||||
if (isJsxElement(node.parent)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function transformFunctionInitializerAndType(variableType: TypeNode | undefined, initializer: Expression): { variableType: TypeNode | undefined, initializer: Expression } {
|
||||
// If no contextual type exists there is nothing to transfer to the function signature
|
||||
if (variableType === undefined) return { variableType, initializer };
|
||||
@ -1953,4 +1954,8 @@ namespace ts.refactor.extractSymbol {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isInJSXContent(node: Node) {
|
||||
return (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) && isJsxElement(node.parent);
|
||||
}
|
||||
}
|
||||
|
||||
28
tests/cases/fourslash/extract-const_jsxElement1.ts
Normal file
28
tests/cases/fourslash/extract-const_jsxElement1.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to constant in global scope",
|
||||
newContent:
|
||||
`const /*RENAME*/newLocal = <span></span>;
|
||||
function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
28
tests/cases/fourslash/extract-const_jsxElement2.ts
Normal file
28
tests/cases/fourslash/extract-const_jsxElement2.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_0",
|
||||
actionDescription: "Extract to constant in enclosing scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
const /*RENAME*/newLocal = <span></span>;
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
35
tests/cases/fourslash/extract-const_jsxElement3.ts
Normal file
35
tests/cases/fourslash/extract-const_jsxElement3.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to readonly field in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
private readonly newProperty = <span></span>;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newProperty}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}`
|
||||
});
|
||||
28
tests/cases/fourslash/extract-const_jsxFragment1.ts
Normal file
28
tests/cases/fourslash/extract-const_jsxFragment1.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to constant in global scope",
|
||||
newContent:
|
||||
`const /*RENAME*/newLocal = <></>;
|
||||
function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
28
tests/cases/fourslash/extract-const_jsxFragment2.ts
Normal file
28
tests/cases/fourslash/extract-const_jsxFragment2.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_0",
|
||||
actionDescription: "Extract to constant in enclosing scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
const /*RENAME*/newLocal = <></>;
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
35
tests/cases/fourslash/extract-const_jsxFragment3.ts
Normal file
35
tests/cases/fourslash/extract-const_jsxFragment3.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to readonly field in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
private readonly newProperty = <></>;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newProperty}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to constant in global scope",
|
||||
newContent:
|
||||
`const /*RENAME*/newLocal = <br />;
|
||||
function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_0",
|
||||
actionDescription: "Extract to constant in enclosing scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
const /*RENAME*/newLocal = <br />;
|
||||
return (
|
||||
<div>
|
||||
{newLocal}
|
||||
</div>
|
||||
);
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "constant_scope_1",
|
||||
actionDescription: "Extract to readonly field in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
private readonly newProperty = <br />;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newProperty}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}`
|
||||
});
|
||||
32
tests/cases/fourslash/extract-method_jsxElement1.ts
Normal file
32
tests/cases/fourslash/extract-method_jsxElement1.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to function in global scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <span></span>;
|
||||
}
|
||||
`
|
||||
});
|
||||
31
tests/cases/fourslash/extract-method_jsxElement2.ts
Normal file
31
tests/cases/fourslash/extract-method_jsxElement2.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_0",
|
||||
actionDescription: "Extract to inner function in function 'Foo'",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <span></span>;
|
||||
}
|
||||
}`
|
||||
});
|
||||
37
tests/cases/fourslash/extract-method_jsxElement3.ts
Normal file
37
tests/cases/fourslash/extract-method_jsxElement3.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<span></span>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to method in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newMethod()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private newMethod() {
|
||||
return <span></span>;
|
||||
}
|
||||
}`
|
||||
});
|
||||
32
tests/cases/fourslash/extract-method_jsxFragment1.ts
Normal file
32
tests/cases/fourslash/extract-method_jsxFragment1.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to function in global scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <></>;
|
||||
}
|
||||
`
|
||||
});
|
||||
31
tests/cases/fourslash/extract-method_jsxFragment2.ts
Normal file
31
tests/cases/fourslash/extract-method_jsxFragment2.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_0",
|
||||
actionDescription: "Extract to inner function in function 'Foo'",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <></>;
|
||||
}
|
||||
}`
|
||||
});
|
||||
37
tests/cases/fourslash/extract-method_jsxFragment3.ts
Normal file
37
tests/cases/fourslash/extract-method_jsxFragment3.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<></>/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to method in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newMethod()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private newMethod() {
|
||||
return <></>;
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,32 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to function in global scope",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <br />;
|
||||
}
|
||||
`
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////function Foo() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_0",
|
||||
actionDescription: "Extract to inner function in function 'Foo'",
|
||||
newContent:
|
||||
`function Foo() {
|
||||
return (
|
||||
<div>
|
||||
{newFunction()}
|
||||
</div>
|
||||
);
|
||||
|
||||
function /*RENAME*/newFunction() {
|
||||
return <br />;
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,37 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @jsx: preserve
|
||||
// @filename: a.tsx
|
||||
////declare var React: any;
|
||||
////class Foo extends React.Component<{}, {}> {
|
||||
//// render() {
|
||||
//// return (
|
||||
//// <div>
|
||||
//// /*a*/<br />/*b*/
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.file("a.tsx");
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Extract Symbol",
|
||||
actionName: "function_scope_1",
|
||||
actionDescription: "Extract to method in class 'Foo'",
|
||||
newContent:
|
||||
`declare var React: any;
|
||||
class Foo extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this./*RENAME*/newMethod()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private newMethod() {
|
||||
return <br />;
|
||||
}
|
||||
}`
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user