Skip to content

Commit b88a0b1

Browse files
committed
fix(33836): allow readonly modifier for a field with only get accessor
1 parent 52dc9f2 commit b88a0b1

File tree

3 files changed

+36
-19
lines changed

3 files changed

+36
-19
lines changed

src/services/refactors/generateGetAccessorAndSetAccessor.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
4141
const fieldInfo = getConvertibleFieldAtPosition(context);
4242
if (!fieldInfo) return undefined;
4343

44-
const isJS = isSourceFileJS(file);
4544
const changeTracker = textChanges.ChangeTracker.fromContext(context);
4645
const { isStatic, isReadonly, fieldName, accessorName, originalName, type, container, declaration, renameAccessor } = fieldInfo;
4746

@@ -50,15 +49,20 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
5049
suppressLeadingAndTrailingTrivia(declaration);
5150
suppressLeadingAndTrailingTrivia(container);
5251

53-
const isInClassLike = isClassLike(container);
54-
// avoid Readonly modifier because it will convert to get accessor
55-
const modifierFlags = getModifierFlags(declaration) & ~ModifierFlags.Readonly;
56-
const accessorModifiers = isInClassLike
57-
? !modifierFlags || modifierFlags & ModifierFlags.Private
58-
? getModifiers(isJS, isStatic, SyntaxKind.PublicKeyword)
59-
: createNodeArray(createModifiersFromModifierFlags(modifierFlags))
60-
: undefined;
61-
const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined;
52+
let accessorModifiers: ModifiersArray | undefined;
53+
let fieldModifiers: ModifiersArray | undefined;
54+
if (isClassLike(container)) {
55+
const modifierFlags = getModifierFlags(declaration);
56+
if (isSourceFileJS(file)) {
57+
const modifiers = createModifiers(modifierFlags);
58+
accessorModifiers = modifiers;
59+
fieldModifiers = modifiers;
60+
}
61+
else {
62+
accessorModifiers = createModifiers(prepareModifierFlagsForAccessor(modifierFlags));
63+
fieldModifiers = createModifiers(prepareModifierFlagsForField(modifierFlags));
64+
}
65+
}
6266

6367
updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers);
6468

@@ -105,12 +109,26 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
105109
return isIdentifier(fieldName) ? createPropertyAccess(leftHead, fieldName) : createElementAccess(leftHead, createLiteral(fieldName));
106110
}
107111

108-
function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray<Modifier> | undefined {
109-
const modifiers = append<Modifier>(
110-
!isJS ? [createToken(accessModifier) as Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword>] : undefined,
111-
isStatic ? createToken(SyntaxKind.StaticKeyword) : undefined
112-
);
113-
return modifiers && createNodeArray(modifiers);
112+
function createModifiers(modifierFlags: ModifierFlags): ModifiersArray | undefined {
113+
return modifierFlags ? createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined;
114+
}
115+
116+
function prepareModifierFlagsForAccessor(modifierFlags: ModifierFlags): ModifierFlags {
117+
modifierFlags &= ~ModifierFlags.Readonly; // avoid Readonly modifier because it will convert to get accessor
118+
modifierFlags &= ~ModifierFlags.Private;
119+
120+
if (!(modifierFlags & ModifierFlags.Protected)) {
121+
modifierFlags |= ModifierFlags.Public;
122+
}
123+
124+
return modifierFlags;
125+
}
126+
127+
function prepareModifierFlagsForField(modifierFlags: ModifierFlags): ModifierFlags {
128+
modifierFlags &= ~ModifierFlags.Public;
129+
modifierFlags &= ~ModifierFlags.Protected;
130+
modifierFlags |= ModifierFlags.Private;
131+
return modifierFlags;
114132
}
115133

116134
function getConvertibleFieldAtPosition(context: RefactorContext): Info | undefined {

tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess14.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44
//// /*a*/public readonly a: string = "foo";/*b*/
55
//// }
66

7-
goTo.select("a", "b");
87
goTo.select("a", "b");
98
edit.applyRefactor({
109
refactorName: "Generate 'get' and 'set' accessors",
1110
actionName: "Generate 'get' and 'set' accessors",
1211
actionDescription: "Generate 'get' and 'set' accessors",
1312
newContent: `class A {
14-
private /*RENAME*/_a: string = "foo";
13+
private readonly /*RENAME*/_a: string = "foo";
1514
public get a(): string {
1615
return this._a;
1716
}

tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ edit.applyRefactor({
2222
actionName: "Generate 'get' and 'set' accessors",
2323
actionDescription: "Generate 'get' and 'set' accessors",
2424
newContent: `class A {
25-
private /*RENAME*/_a: number;
25+
private readonly /*RENAME*/_a: number;
2626
public get a(): number {
2727
return this._a;
2828
}

0 commit comments

Comments
 (0)