Skip to content

Commit

Permalink
fixAddMissingMember: Support interface and don't crash on type parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Hanson committed Jul 27, 2018
1 parent 0227997 commit c0e3731
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 65 deletions.
116 changes: 59 additions & 57 deletions src/services/codefixes/fixAddMissingMember.ts

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/services/codefixes/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ namespace ts.codefix {
inJs: boolean,
makeStatic: boolean,
preferences: UserPreferences,
body: boolean,
): MethodDeclaration {
const checker = context.program.getTypeChecker();
const types = map(args,
Expand All @@ -142,7 +143,7 @@ namespace ts.codefix {
createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)),
/*parameters*/ createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, inJs),
/*type*/ inJs ? undefined : createKeywordTypeNode(SyntaxKind.AnyKeyword),
createStubbedMethodBody(preferences));
body ? createStubbedMethodBody(preferences) : undefined);
}

function createDummyParameters(argCount: number, names: (string | undefined)[] | undefined, types: (TypeNode | undefined)[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] {
Expand Down
6 changes: 3 additions & 3 deletions src/services/textChanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,14 @@ namespace ts.textChanges {
});
}

public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration, newElement: ClassElement): void {
public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void {
const clsStart = cls.getStart(sourceFile);
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options)
+ this.formatContext.options.indentSize!;
this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) });
}

private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration): { prefix: string, suffix: string } {
private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration): { prefix: string, suffix: string } {
if (cls.members.length === 0) {
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) {
// For `class C {\n}`, don't add the trailing "\n"
Expand Down Expand Up @@ -703,7 +703,7 @@ namespace ts.textChanges {
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
}

function getClassBraceEnds(cls: ClassLikeDeclaration, sourceFile: SourceFile): [number, number] {
function getClassBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration, sourceFile: SourceFile): [number, number] {
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end];
}

Expand Down
2 changes: 1 addition & 1 deletion src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ namespace ts {
}

export function skipConstraint(type: Type): Type {
return type.isTypeParameter() ? type.getConstraint()! : type; // TODO: GH#18217
return type.isTypeParameter() ? type.getConstraint() || type : type;
}

export function getNameFromPropertyName(name: PropertyName): string | undefined {
Expand Down
32 changes: 32 additions & 0 deletions tests/cases/fourslash/codeFixAddMissingMember_typeParameter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
////interface I {}
////
////function f<T>(t: T): number {
//// return t.foo;
////}
////
////function g<T extends I>(t: T): number {
//// return t.bar;
////}

// No code fix for "foo"

verify.codeFixAvailable([
{ description: "Declare property 'bar'" }, { description: "Add index signature for property 'bar'" },
])

verify.codeFix({
description: "Declare property 'bar'",
index: 0,
newFileContent:
`interface I {
bar: any;
}
function f<T>(t: T): number {
return t.foo;
}
function g<T extends I>(t: T): number {
return t.bar;
}`,
});
11 changes: 8 additions & 3 deletions tests/cases/fourslash/codeFixUndeclaredPropertyAccesses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
//// let t: T<number>;
//// t.x;

verify.codeFixAvailable([{
description: "Add missing enum member 'c'"
}]);
verify.codeFixAvailable([
"Declare property 'y'",
"Add index signature for property 'y'",
"Declare method 'foo'",
"Declare property 'foo'",
"Add index signature for property 'foo'",
"Add missing enum member 'c'",
].map(description => ({ description })));

0 comments on commit c0e3731

Please sign in to comment.