Skip to content

Commit

Permalink
add refactor of convert private field to getter and setter
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingwl committed Feb 23, 2018
1 parent e8fb587 commit 38f3153
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3965,5 +3965,9 @@
"Convert to ES6 module": {
"category": "Message",
"code": 95017
},
"Convert to getter and setter": {
"category": "Message",
"code": 95018
}
}
109 changes: 109 additions & 0 deletions src/services/refactors/ConvertToGetterAndSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* @internal */
namespace ts.refactor.ConvertGetterAndSetter {
const actionName = "Convert to getter and setter";
const description = Diagnostics.Convert_to_getter_and_setter.message;
registerRefactor(actionName, { getEditsForAction, getAvailableActions });

function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition } = context;

const fieldInfo = getConvertibleFieldAtPosition(file, startPosition);
if (!fieldInfo) return undefined;

return [
{
name: actionName,
description,
actions: [
{
description,
name: actionName
}
]
}
];

}

function getEditsForAction(context: RefactorContext, _actionName: string): RefactorEditInfo | undefined {
const { file, startPosition } = context;
Debug.assertEqual(actionName, _actionName);

const fieldInfo = getConvertibleFieldAtPosition(file, startPosition);
if (!fieldInfo) return undefined;

const { fieldName, name, type, propertyDeclaration } = fieldInfo;
const changeTracker = textChanges.ChangeTracker.fromContext(context);

const getter = createGetter(fieldName, name, type);
const setter = createSetter(fieldName, name, type);

changeTracker.insertNodeAfter(file, propertyDeclaration, getter);
changeTracker.insertNodeAfter(file, propertyDeclaration, setter);

return {
edits: changeTracker.getChanges(),
renameFilename: undefined,
renameLocation: undefined,
};
}

interface Info { fieldName: string; name: string; type: TypeNode; propertyDeclaration: PropertyDeclaration; }
function getConvertibleFieldAtPosition(file: SourceFile, startPosition: number): Info | undefined {
const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
const propertyDeclaration = findAncestor(node.parent, isPropertyDeclaration);
if (!(propertyDeclaration && propertyDeclaration.name.getText().charAt(0) === "_") && hasModifier(propertyDeclaration, ModifierFlags.Private)) return undefined;

return {
fieldName: propertyDeclaration.name.getText(),
name: propertyDeclaration.name.getText().substring(1),
type: propertyDeclaration.type,
propertyDeclaration
};
}

function createGetter (fieldName: string, name: string, type: TypeNode) {
return createGetAccessor(
/*decorators*/ undefined,
[createToken(SyntaxKind.PublicKeyword)],
name,
/*parameters*/ undefined,
type,
createBlock([
createReturn(
createPropertyAccess(
createThis(),
fieldName
)
)
], /*multiLine*/ true)
);
}

function createSetter (fieldName: string, name: string, type: TypeNode) {
return createSetAccessor(
/*decorators*/ undefined,
[createToken(SyntaxKind.PublicKeyword)],
name,
[createParameter(
/*decorators*/ undefined,
/*modifies*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("value"),
/*questionToken*/ undefined,
type
)],
createBlock([
createStatement(
createAssignment(
createPropertyAccess(
createThis(),
fieldName
),
createIdentifier("value")
)
)
], /*multiLine*/ true)
);
}
}
1 change: 1 addition & 0 deletions src/services/refactors/refactors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/// <reference path="extractSymbol.ts" />
/// <reference path="installTypesForPackage.ts" />
/// <reference path="useDefaultImport.ts" />
/// <reference path="ConvertToGetterAndSetter.ts" />
21 changes: 21 additions & 0 deletions tests/cases/fourslash/refactorConvertToGetterAndSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// <reference path='fourslash.ts' />

//// class A {
//// /*a*/private _a: string;/*b*/
//// }

goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to getter and setter",
actionName: "Convert to getter and setter",
actionDescription: "Convert to getter and setter",
newContent: `class A {
private _a: string;
public get a(): string {
return this._a;
}
public set a(value: string) {
this._a = value;
}
}`,
});

0 comments on commit 38f3153

Please sign in to comment.