Add textChanges methods to insert nodes at the start of multiline bodies (#20445)

* Add textChanges methods to insert nodes at the start of multiline bodies

* Replace constructor body if not already multiline
This commit is contained in:
Andy
2017-12-05 08:33:29 -08:00
committed by GitHub
parent 8153397e91
commit 8f23bf813c
5 changed files with 44 additions and 13 deletions

View File

@@ -2471,7 +2471,7 @@ Actual: ${stringify(fullActual)}`);
}
private verifyNewContent(options: FourSlashInterface.NewContentOptions) {
if (options.newFileContent) {
if (options.newFileContent !== undefined) {
assert(!options.newRangeContent);
this.verifyCurrentFileContent(options.newFileContent);
}

View File

@@ -62,7 +62,6 @@ namespace ts.codefix {
}
const classDeclarationSourceFile = getSourceFileOfNode(classDeclaration);
const classOpenBrace = getOpenBraceOfClassLike(classDeclaration, classDeclarationSourceFile);
return isInJavaScriptFile(classDeclarationSourceFile) ?
getActionsForAddMissingMemberInJavaScriptFile(classDeclaration, makeStatic) :
@@ -154,7 +153,7 @@ namespace ts.codefix {
typeNode,
/*initializer*/ undefined);
const propertyChangeTracker = textChanges.ChangeTracker.fromContext(context);
propertyChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, property, { suffix: context.newLineCharacter });
propertyChangeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, property, context.newLineCharacter);
const diag = makeStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0;
actions = append(actions, {
@@ -180,7 +179,7 @@ namespace ts.codefix {
typeNode);
const indexSignatureChangeTracker = textChanges.ChangeTracker.fromContext(context);
indexSignatureChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, indexSignature, { suffix: context.newLineCharacter });
indexSignatureChangeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, indexSignature, context.newLineCharacter);
actions.push({
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_property_0), [tokenName]),
@@ -197,7 +196,7 @@ namespace ts.codefix {
const methodDeclaration = createMethodFromCallExpression(callExpression, tokenName, includeTypeScriptSyntax, makeStatic);
const methodDeclarationChangeTracker = textChanges.ChangeTracker.fromContext(context);
methodDeclarationChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, methodDeclaration, { suffix: context.newLineCharacter });
methodDeclarationChangeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, methodDeclaration, context.newLineCharacter);
const diag = makeStatic ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0;
return {
description: formatStringFromArgs(getLocaleSpecificMessage(diag), [tokenName]),

View File

@@ -12,7 +12,7 @@ namespace ts.codefix {
const changeTracker = textChanges.ChangeTracker.fromContext(context);
const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>token.parent, sourceFile), superCall, { suffix: context.newLineCharacter });
changeTracker.insertNodeAtConstructorStart(sourceFile, <ConstructorDeclaration>token.parent, superCall, context.newLineCharacter);
return [{
description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call),

View File

@@ -337,8 +337,32 @@ namespace ts.textChanges {
return this.replaceWithSingle(sourceFile, startPosition, startPosition, newNode, options);
}
public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node, options: InsertNodeOptions & ConfigurableEnd = {}) {
if ((isStatementButNotDeclaration(after)) ||
public insertNodeAtConstructorStart(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement, newLineCharacter: string): void {
const firstStatement = firstOrUndefined(ctr.body.statements);
if (!firstStatement || !ctr.body.multiLine) {
this.replaceNode(sourceFile, ctr.body, createBlock([newStatement, ...ctr.body.statements], /*multiLine*/ true), { useNonAdjustedEndPosition: true });
}
else {
this.insertNodeBefore(sourceFile, firstStatement, newStatement, { suffix: newLineCharacter });
}
}
public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration, newElement: ClassElement, newLineCharacter: string): void {
const firstMember = firstOrUndefined(cls.members);
if (!firstMember) {
const members = [newElement];
const newCls = cls.kind === SyntaxKind.ClassDeclaration
? updateClassDeclaration(cls, cls.decorators, cls.modifiers, cls.name, cls.typeParameters, cls.heritageClauses, members)
: updateClassExpression(cls, cls.modifiers, cls.name, cls.typeParameters, cls.heritageClauses, members);
this.replaceNode(sourceFile, cls, newCls, { useNonAdjustedEndPosition: true });
}
else {
this.insertNodeBefore(sourceFile, firstMember, newElement, { suffix: newLineCharacter });
}
}
public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node, options: InsertNodeOptions & ConfigurableEnd = {}): this {
if (isStatementButNotDeclaration(after) ||
after.kind === SyntaxKind.PropertyDeclaration ||
after.kind === SyntaxKind.PropertySignature ||
after.kind === SyntaxKind.MethodSignature) {