import {
    codeFixAll,
    createCodeFixAction,
    registerCodeFix,
} from "../_namespaces/ts.codefix.js";
import {
    ANONYMOUS,
    Debug,
    DiagnosticOrDiagnosticAndArguments,
    Diagnostics,
    emptyArray,
    factory,
    FindAllReferences,
    findChildOfKind,
    getThisContainer,
    getTokenAtPosition,
    isFunctionDeclaration,
    isFunctionExpression,
    isSourceFile,
    isThis,
    SourceFile,
    SyntaxKind,
    textChanges,
    TypeChecker,
} from "../_namespaces/ts.js";

const fixId = "fixImplicitThis";
const errorCodes = [Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code];
registerCodeFix({
    errorCodes,
    getCodeActions: function getCodeActionsToFixImplicitThis(context) {
        const { sourceFile, program, span } = context;
        let diagnostic: DiagnosticOrDiagnosticAndArguments | undefined;
        const changes = textChanges.ChangeTracker.with(context, t => {
            diagnostic = doChange(t, sourceFile, span.start, program.getTypeChecker());
        });
        return diagnostic ? [createCodeFixAction(fixId, changes, diagnostic, fixId, Diagnostics.Fix_all_implicit_this_errors)] : emptyArray;
    },
    fixIds: [fixId],
    getAllCodeActions: context =>
        codeFixAll(context, errorCodes, (changes, diag) => {
            doChange(changes, diag.file, diag.start, context.program.getTypeChecker());
        }),
});

function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, checker: TypeChecker): DiagnosticOrDiagnosticAndArguments | undefined {
    const token = getTokenAtPosition(sourceFile, pos);
    if (!isThis(token)) return undefined;

    const fn = getThisContainer(token, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false);
