diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 704812b0185..c593fcd6737 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -83,6 +83,7 @@ namespace ts { getSignaturesOfType, getIndexTypeOfType, getBaseTypes, + getWidenedType, getTypeFromTypeNode, getParameterType: getTypeAtPosition, getReturnTypeOfSignature, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ec6067751a2..a01676207be 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3303,6 +3303,14 @@ "category": "Message", "code": 90015 }, + "Add declaration for missing property '{0}'": { + "category": "Message", + "code": 90016 + }, + "Add index accessor for missing property '{0}'": { + "category": "Message", + "code": 90017 + }, "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { "category": "Error", "code": 8017 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bdc4eea98da..2b121627b45 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2382,6 +2382,7 @@ getSignaturesOfType(type: Type, kind: SignatureKind): Signature[]; getIndexTypeOfType(type: Type, kind: IndexKind): Type; getBaseTypes(type: InterfaceType): BaseType[]; + getWidenedType(type: Type): Type; getReturnTypeOfSignature(signature: Signature): Type; /** * Gets the type of a parameter at a given position in a signature. diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index c51c63bdc27..24fc6b16abb 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -12,32 +12,41 @@ namespace ts.codefix { // This is the identifier in the case of a class declaration // or the class keyword token in the case of a class expression. const token = getTokenAtPosition(sourceFile, start); - const checker = context.program.getTypeChecker(); - if(!(token.parent && token.parent.kind === SyntaxKind.PropertyAccessExpression)) { + const classDeclaration = getContainingClass(token); + if (!classDeclaration) { return undefined; } - if((token.parent as PropertyAccessExpression).expression.kind !== SyntaxKind.ThisKeyword) { + const startPos = classDeclaration.members.pos; + + if (!(token.parent && token.parent.kind === SyntaxKind.PropertyAccessExpression)) { return undefined; } - 1 + 1; + + if ((token.parent as PropertyAccessExpression).expression.kind !== SyntaxKind.ThisKeyword) { + return undefined; + } + + // if function call, synthesize function declaration + if(token.parent.parent.kind == SyntaxKind.CallExpression) { + + } let typeString: string = 'any'; + // if binary expression, try to infer type for LHS, else use any - if(token.parent.parent.kind === SyntaxKind.BinaryExpression) - { + if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { const binaryExpression = token.parent.parent as BinaryExpression; binaryExpression.operatorToken; - - const type = checker.getTypeAtLocation(binaryExpression.right); + + const checker = context.program.getTypeChecker(); + const type = checker.getWidenedType(checker.getTypeAtLocation(binaryExpression.right)); typeString = checker.typeToString(type); } - const classDeclaration = getContainingClass(token); - const startPos = classDeclaration.members.pos; return [{ - description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class), + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]), changes: [{ fileName: sourceFile.fileName, textChanges: [{ @@ -45,14 +54,19 @@ namespace ts.codefix { newText: `${token.getFullText(sourceFile)}: ${typeString};` }] }] + }, + { + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_accessor_for_missing_property_0), [token.getText()]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: `[name: string]: ${typeString};` + }] + }] }]; } - - - - // x needs to be a `this` construct. ie - // this.. // Want to infer type of x when possible. ie: // * assignment, // * function call argument: foo(this.x) where foo(x: SomeType) @@ -65,10 +79,4 @@ namespace ts.codefix { // inferred type might be error. then add any. // either make indexable of the inferred type // add named member of the inferred type. -} - -// // class C { -// // constructor() { -// // this.x = 1; -// // } -// // } \ No newline at end of file +} \ No newline at end of file