|
| 1 | +/* @internal */ |
| 2 | +namespace ts.codefix { |
| 3 | + const fixId = "convertLiteralTypeToMappedType"; |
| 4 | + const errorCodes = [Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0.code]; |
| 5 | + |
| 6 | + registerCodeFix({ |
| 7 | + errorCodes, |
| 8 | + getCodeActions: context => { |
| 9 | + const { sourceFile, span } = context; |
| 10 | + const info = getInfo(sourceFile, span.start); |
| 11 | + if (!info) { |
| 12 | + return undefined; |
| 13 | + } |
| 14 | + const { name, constraint } = info; |
| 15 | + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); |
| 16 | + return [createCodeFixAction(fixId, changes, [Diagnostics.Convert_0_to_1_in_0, constraint, name], fixId, Diagnostics.Convert_all_type_literals_to_mapped_type)]; |
| 17 | + }, |
| 18 | + fixIds: [fixId], |
| 19 | + getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { |
| 20 | + const info = getInfo(diag.file, diag.start); |
| 21 | + if (info) { |
| 22 | + doChange(changes, diag.file, info); |
| 23 | + } |
| 24 | + }) |
| 25 | + }); |
| 26 | + |
| 27 | + interface Info { |
| 28 | + container: TypeLiteralNode, |
| 29 | + typeNode: TypeNode | undefined; |
| 30 | + constraint: string; |
| 31 | + name: string; |
| 32 | + } |
| 33 | + |
| 34 | + function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { |
| 35 | + const token = getTokenAtPosition(sourceFile, pos); |
| 36 | + if (isIdentifier(token)) { |
| 37 | + const propertySignature = cast(token.parent.parent, isPropertySignature); |
| 38 | + const propertyName = token.getText(sourceFile); |
| 39 | + return { |
| 40 | + container: cast(propertySignature.parent, isTypeLiteralNode), |
| 41 | + typeNode: propertySignature.type, |
| 42 | + constraint: propertyName, |
| 43 | + name: propertyName === "K" ? "P" : "K", |
| 44 | + }; |
| 45 | + } |
| 46 | + return undefined; |
| 47 | + } |
| 48 | + |
| 49 | + function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { container, typeNode, constraint, name }: Info): void { |
| 50 | + changes.replaceNode(sourceFile, container, factory.createMappedTypeNode(/*readonlyToken*/ undefined, |
| 51 | + factory.createTypeParameterDeclaration(name, factory.createTypeReferenceNode(constraint)), /*questionToken*/ undefined, typeNode)); |
| 52 | + } |
| 53 | +} |
0 commit comments