Skip to content

Commit 533262c

Browse files
author
Arthur Ozga
committed
wip
1 parent 510b384 commit 533262c

File tree

4 files changed

+100
-4
lines changed

4 files changed

+100
-4
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
registerCodeFix({
4+
errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code],
5+
getCodeActions: getActionsForAddMissingMember
6+
});
7+
8+
function getActionsForAddMissingMember(context: CodeFixContext): CodeAction[] | undefined {
9+
10+
const sourceFile = context.sourceFile;
11+
const start = context.span.start;
12+
// This is the identifier in the case of a class declaration
13+
// or the class keyword token in the case of a class expression.
14+
const token = getTokenAtPosition(sourceFile, start);
15+
const checker = context.program.getTypeChecker();
16+
17+
if(!(token.parent && token.parent.kind === SyntaxKind.PropertyAccessExpression)) {
18+
return undefined;
19+
}
20+
21+
if((token.parent as PropertyAccessExpression).expression.kind !== SyntaxKind.ThisKeyword) {
22+
return undefined;
23+
}
24+
1 + 1;
25+
26+
let typeString: string = 'any';
27+
// if binary expression, try to infer type for LHS, else use any
28+
if(token.parent.parent.kind === SyntaxKind.BinaryExpression)
29+
{
30+
const binaryExpression = token.parent.parent as BinaryExpression;
31+
binaryExpression.operatorToken;
32+
33+
const type = checker.getTypeAtLocation(binaryExpression.right);
34+
typeString = checker.typeToString(type);
35+
}
36+
37+
const classDeclaration = getContainingClass(token);
38+
const startPos = classDeclaration.members.pos;
39+
return [{
40+
description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class),
41+
changes: [{
42+
fileName: sourceFile.fileName,
43+
textChanges: [{
44+
span: { start: startPos, length: 0 },
45+
newText: `${token.getFullText(sourceFile)}: ${typeString};`
46+
}]
47+
}]
48+
}];
49+
}
50+
51+
52+
53+
54+
// x needs to be a `this` construct. ie
55+
// this.<thing>.
56+
// Want to infer type of x when possible. ie:
57+
// * assignment,
58+
// * function call argument: foo<T>(this.x) where foo(x: SomeType<T>)
59+
// * expression with a type assertion: this.x as MyFavoriteType
60+
// * access expression: this.x.push("asdf") ... probably an array?
61+
// *
62+
// What if there are multiple usages of this.x? Create intersection over all usages?
63+
64+
// needs to be in a class
65+
// inferred type might be error. then add any.
66+
// either make indexable of the inferred type
67+
// add named member of the inferred type.
68+
}
69+
70+
// // class C {
71+
// // constructor() {
72+
// // this.x = 1;
73+
// // }
74+
// // }

src/services/codefixes/fixes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/// <reference path="fixClassIncorrectlyImplementsInterface.ts" />
2+
/// <reference path="fixAddMissingMember.ts" />
23
/// <reference path="fixClassDoesntImplementInheritedAbstractMember.ts" />
34
/// <reference path="fixClassSuperMustPrecedeThisAccess.ts" />
45
/// <reference path="fixConstructorForDerivedNeedSuperCall.ts" />

src/services/codefixes/helpers.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace ts.codefix {
3232

3333
const declaration = declarations[0] as Declaration;
3434
const name = declaration.name ? declaration.name.getText() : undefined;
35-
const visibility = getVisibilityPrefix(getModifierFlags(declaration));
35+
const visibility = getVisibilityPrefixWithSpace(getModifierFlags(declaration));
3636

3737
switch (declaration.kind) {
3838
case SyntaxKind.GetAccessor:
@@ -138,11 +138,15 @@ namespace ts.codefix {
138138
}
139139
}
140140

141-
function getMethodBodyStub(newLineChar: string) {
142-
return ` {${newLineChar}throw new Error('Method not implemented.');${newLineChar}}${newLineChar}`;
141+
export function getStubbedMethod(visibility: string, name: string, signature: string = '()', newlineChar: string): string {
142+
return `${visibility}${name}${signature}${getMethodBodyStub(newlineChar)}`;
143143
}
144144

145-
function getVisibilityPrefix(flags: ModifierFlags): string {
145+
function getMethodBodyStub(newlineChar: string) {
146+
return ` {${newlineChar}throw new Error('Method not implemented.');${newlineChar}}${newlineChar}`;
147+
}
148+
149+
function getVisibilityPrefixWithSpace(flags: ModifierFlags): string {
146150
if (flags & ModifierFlags.Public) {
147151
return "public ";
148152
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// [|class A {
4+
//// constructor() {
5+
//// this.x = 10;
6+
//// }
7+
//// }|]
8+
9+
verify.rangeAfterCodeFix(`
10+
class A {
11+
x: number;
12+
13+
constructor() {
14+
this.x = 10;
15+
}
16+
}
17+
`);

0 commit comments

Comments
 (0)