feat(36249): add quick-fix action to declare a property as private which starts from underscore (#36632)

This commit is contained in:
Alexander T 2020-03-13 19:33:56 +02:00 committed by GitHub
parent f1cc8e4e4e
commit b41eb1bc61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 12 deletions

View file

@ -5113,6 +5113,10 @@
"category": "Message",
"code": 90034
},
"Declare private property '{0}'": {
"category": "Message",
"code": 90035
},
"Declare a private field named '{0}'.": {
"category": "Message",
"code": 90053

View file

@ -74,7 +74,7 @@ namespace ts.codefix {
}
else {
const typeNode = getTypeNode(program.getTypeChecker(), parentDeclaration, token);
addPropertyDeclaration(changes, declSourceFile, parentDeclaration, token.text, typeNode, makeStatic);
addPropertyDeclaration(changes, declSourceFile, parentDeclaration, token.text, typeNode, makeStatic ? ModifierFlags.Static : 0);
}
}
}
@ -211,8 +211,17 @@ namespace ts.codefix {
function getActionsForAddMissingMemberInTypeScriptFile(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, token: Identifier | PrivateIdentifier, makeStatic: boolean): CodeFixAction[] | undefined {
const typeNode = getTypeNode(context.program.getTypeChecker(), classDeclaration, token);
const addProp = createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, makeStatic, token.text, typeNode);
return makeStatic || isPrivateIdentifier(token) ? [addProp] : [addProp, createAddIndexSignatureAction(context, declSourceFile, classDeclaration, token.text, typeNode)];
const actions: CodeFixAction[] = [createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, token.text, typeNode, makeStatic ? ModifierFlags.Static : 0)];
if (makeStatic || isPrivateIdentifier(token)) {
return actions;
}
if (startsWithUnderscore(token.text)) {
actions.unshift(createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, token.text, typeNode, ModifierFlags.Private));
}
actions.push(createAddIndexSignatureAction(context, declSourceFile, classDeclaration, token.text, typeNode));
return actions;
}
function getTypeNode(checker: TypeChecker, classDeclaration: ClassOrInterface, token: Node) {
@ -230,15 +239,18 @@ namespace ts.codefix {
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
function createAddPropertyDeclarationAction(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, makeStatic: boolean, tokenName: string, typeNode: TypeNode): CodeFixAction {
const changes = textChanges.ChangeTracker.with(context, t => addPropertyDeclaration(t, declSourceFile, classDeclaration, tokenName, typeNode, makeStatic));
return createCodeFixAction(fixName, changes, [makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, tokenName], fixId, Diagnostics.Add_all_missing_members);
function createAddPropertyDeclarationAction(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode, modifierFlags: ModifierFlags): CodeFixAction {
const changes = textChanges.ChangeTracker.with(context, t => addPropertyDeclaration(t, declSourceFile, classDeclaration, tokenName, typeNode, modifierFlags));
if (modifierFlags & ModifierFlags.Private) {
return createCodeFixActionWithoutFixAll(fixName, changes, [Diagnostics.Declare_private_property_0, tokenName]);
}
return createCodeFixAction(fixName, changes, [modifierFlags & ModifierFlags.Static ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, tokenName], fixId, Diagnostics.Add_all_missing_members);
}
function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode, makeStatic: boolean): void {
function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode, modifierFlags: ModifierFlags): void {
const property = createProperty(
/*decorators*/ undefined,
/*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
/*modifiers*/ modifierFlags ? createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined,
tokenName,
/*questionToken*/ undefined,
typeNode,

View file

@ -112,10 +112,6 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
return modifiers && createNodeArray(modifiers);
}
function startsWithUnderscore(name: string): boolean {
return name.charCodeAt(0) === CharacterCodes._;
}
function getConvertibleFieldAtPosition(context: RefactorContext): Info | undefined {
const { file, startPosition, endPosition } = context;

View file

@ -2760,5 +2760,9 @@ namespace ts {
return symbol.name;
}
export function startsWithUnderscore(name: string): boolean {
return name.charCodeAt(0) === CharacterCodes._;
}
// #endregion
}

View file

@ -0,0 +1,25 @@
/// <reference path='fourslash.ts' />
////class A {
//// constructor() {
//// this._x = 10;
//// }
////}
verify.codeFixAvailable([
{ description: "Declare private property '_x'" },
{ description: "Declare property '_x'" },
{ description: "Add index signature for property '_x'" }
])
verify.codeFix({
description: [ts.Diagnostics.Declare_private_property_0.message, "_x"],
index: 0,
newFileContent:
`class A {
private _x: number;
constructor() {
this._x = 10;
}
}`
});