namespace ts . codefix { const fixIdPlain = "fixJSDocTypes_plain" ; const fixIdNullable = "fixJSDocTypes_nullable" ; const errorCodes = [ Diagnostics . JSDoc_types_can_only_be_used_inside_documentation_comments . code ] ; registerCodeFix ( { errorCodes , getCodeActions ( context ) { const { sourceFile } = context ; const checker = context . program . getTypeChecker ( ) ; const info = getInfo ( sourceFile , context . span . start , checker ) ; if ( ! info ) return undefined ; const { typeNode , type } = info ; const original = typeNode . getText ( sourceFile ) ; const actions = [ fix ( type , fixIdPlain , Diagnostics . Change_all_jsdoc_style_types_to_TypeScript ) ] ; if ( typeNode . kind === SyntaxKind . JSDocNullableType ) { actions . push ( fix ( checker . getNullableType ( type , TypeFlags . Undefined ) , fixIdNullable , Diagnostics . Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types ) ) ; } return actions ; function fix ( type , fixId , fixAllDescription ) { const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , sourceFile , typeNode , type , checker ) ) ; return createCodeFixAction ( "jdocTypes" , changes , [ Diagnostics . Change_0_to_1 , original , checker . typeToString ( type ) ] , fixId , fixAllDescription ) ; } } , fixIds : [ fixIdPlain , fixIdNullable ] , getAllCodeActions ( context ) { const { fixId , program , sourceFile } = context ; const checker = program . getTypeChecker ( ) ; return codeFixAll ( context , errorCodes , ( changes , err ) => { const info = getInfo ( err . file , err . start , checker ) ; if ( ! info ) return ; const { typeNode , type } = info ; const fixedType = typeNode . kind === SyntaxKind . JSDocNullableType && fixId === fixIdNullable ? checker . getNullableType ( type , TypeFlags . Undefined ) : type ; doChange ( changes , sourceFile , typeNode , fixedType , checker ) ; } ) ; } } ) ; function doChange ( changes , sourceFile , oldTypeNode , newType , checker ) { changes . replaceNode ( sourceFile , oldTypeNode , checker . typeToTypeNode ( newType , oldTypeNode , undefined ) ! ) ; } function getInfo ( sourceFile , pos , checker ) { const decl = findAncestor ( getTokenAtPosition ( sourceFile , pos ) , isTypeContainer ) ; const typeNode = decl && decl . type ; return typeNode && { typeNode , type : checker . getTypeFromTypeNode ( typeNode ) } ; } type TypeContainer = AsExpression | CallSignatureDeclaration | ConstructSignatureDeclaration | FunctionDeclaration | GetAccessorDeclaration | IndexSignatureDeclaration | MappedTypeNode | MethodDeclaration | MethodSignature | ParameterDeclaration | PropertyDeclaration | PropertySignature | SetAccessorDeclaration | TypeAliasDeclaration | TypeAssertion | VariableDeclaration ; function isTypeContainer ( node ) { switch ( node . kind ) { case SyntaxKind . AsExpression : case SyntaxKind . CallSignature : case SyntaxKind . ConstructSignature : case SyntaxKind . FunctionDeclaration : case SyntaxKind . GetAccessor : case SyntaxKind . IndexSignature : case SyntaxKind . MappedType : case SyntaxKind . MethodDeclaration : case SyntaxKind . MethodSignature : case SyntaxKind . Parameter : case SyntaxKind . PropertyDeclaration : case SyntaxKind . PropertySignature : case SyntaxKind . SetAccessor : case SyntaxKind . TypeAliasDeclaration : case SyntaxKind . TypeAssertionExpression : case SyntaxKind . VariableDeclaration : return true ; default : return false ; } } }