add missing method
This commit is contained in:
parent
7adfa8d854
commit
420279b99d
|
@ -3583,7 +3583,11 @@
|
||||||
"category": "Message",
|
"category": "Message",
|
||||||
"code": 90022
|
"code": 90022
|
||||||
},
|
},
|
||||||
|
"Add declaration for missing method '{0}'.": {
|
||||||
|
"category": "Message",
|
||||||
|
"code": 90023
|
||||||
|
},
|
||||||
|
|
||||||
"Convert function to an ES2015 class": {
|
"Convert function to an ES2015 class": {
|
||||||
"category": "Message",
|
"category": "Message",
|
||||||
"code": 95001
|
"code": 95001
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
namespace ts.codefix {
|
namespace ts.codefix {
|
||||||
registerCodeFix({
|
registerCodeFix({
|
||||||
errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code,
|
errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code,
|
||||||
Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code],
|
Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code],
|
||||||
getCodeActions: getActionsForAddMissingMember
|
getCodeActions: getActionsForAddMissingMember
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,20 +79,31 @@ namespace ts.codefix {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined {
|
function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined {
|
||||||
let typeNode: TypeNode;
|
const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile);
|
||||||
|
const tokenName = token.getText(sourceFile);
|
||||||
|
let actions: CodeAction[];
|
||||||
|
|
||||||
|
if (token.parent.parent.kind === SyntaxKind.CallExpression) {
|
||||||
|
const callExpression = <CallExpression>token.parent.parent;
|
||||||
|
const methodDeclaration = createMethodFromCallExpression(callExpression, tokenName);
|
||||||
|
|
||||||
|
const methodDeclarationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||||
|
methodDeclarationChangeTracker.insertNodeAfter(sourceFile, openBrace, methodDeclaration, { suffix: context.newLineCharacter });
|
||||||
|
actions = [{
|
||||||
|
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_method_0), [tokenName]),
|
||||||
|
changes: methodDeclarationChangeTracker.getChanges()
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeNode: TypeNode;
|
||||||
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
||||||
const binaryExpression = token.parent.parent as BinaryExpression;
|
const binaryExpression = token.parent.parent as BinaryExpression;
|
||||||
|
|
||||||
const checker = context.program.getTypeChecker();
|
const checker = context.program.getTypeChecker();
|
||||||
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
|
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
|
||||||
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
|
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
typeNode = typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
typeNode = typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
|
||||||
const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile);
|
|
||||||
|
|
||||||
const property = createProperty(
|
const property = createProperty(
|
||||||
/*decorators*/undefined,
|
/*decorators*/undefined,
|
||||||
/*modifiers*/ isStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
/*modifiers*/ isStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
||||||
|
@ -103,10 +114,10 @@ namespace ts.codefix {
|
||||||
const propertyChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
const propertyChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||||
propertyChangeTracker.insertNodeAfter(sourceFile, openBrace, property, { suffix: context.newLineCharacter });
|
propertyChangeTracker.insertNodeAfter(sourceFile, openBrace, property, { suffix: context.newLineCharacter });
|
||||||
|
|
||||||
const actions = [{
|
(actions || (actions = [])).push({
|
||||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
||||||
changes: propertyChangeTracker.getChanges()
|
changes: propertyChangeTracker.getChanges()
|
||||||
}];
|
});
|
||||||
|
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
|
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
|
||||||
|
|
|
@ -142,6 +142,46 @@ namespace ts.codefix {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createMethodFromCallExpression(callExpression: CallExpression, methodName: string): MethodDeclaration {
|
||||||
|
const argCount = callExpression.arguments.length;
|
||||||
|
const parameters: ParameterDeclaration[] = [];
|
||||||
|
for (let i = 0; i < argCount; i++) {
|
||||||
|
const typeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
const newParameter = createParameter(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
/*dotDotDotToken*/ undefined,
|
||||||
|
`arg${i}`,
|
||||||
|
/*questionToken*/ undefined,
|
||||||
|
typeNode,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
parameters.push(newParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeArgCount = callExpression.typeArguments ? callExpression.typeArguments.length : 0;
|
||||||
|
let typeParameters: TypeParameterDeclaration[];
|
||||||
|
for (let i = 0; i < typeArgCount; i++) {
|
||||||
|
const name = typeArgCount < 8 ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`;
|
||||||
|
const typeParameter = createTypeParameterDeclaration(name, /*constraint*/ undefined, /*defaultType*/ undefined);
|
||||||
|
|
||||||
|
(typeParameters ? typeParameters : typeParameters = []).push(typeParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMethod = createMethod(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
/*asteriskToken*/ undefined,
|
||||||
|
methodName,
|
||||||
|
/*questionToken*/ undefined,
|
||||||
|
typeParameters,
|
||||||
|
parameters,
|
||||||
|
/*type*/ undefined,
|
||||||
|
createStubbedMethodBody()
|
||||||
|
)
|
||||||
|
|
||||||
|
return newMethod;
|
||||||
|
}
|
||||||
|
|
||||||
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
|
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
|
||||||
/** This is *a* signature with the maximal number of arguments,
|
/** This is *a* signature with the maximal number of arguments,
|
||||||
* such that if there is a "maximal" signature without rest arguments,
|
* such that if there is a "maximal" signature without rest arguments,
|
||||||
|
|
Loading…
Reference in a new issue