"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert = __importStar(require("assert"));
const path = __importStar(require("path"));
const compiler_1 = require("svelte/compiler");
const svelte2tsx_1 = require("svelte2tsx");
const typescript_1 = __importDefault(require("typescript"));
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../../../../src/lib/documents");
const ls_config_1 = require("../../../../src/ls-config");
const CodeActionsProvider_1 = require("../../../../src/plugins/typescript/features/CodeActionsProvider");
const CompletionProvider_1 = require("../../../../src/plugins/typescript/features/CompletionProvider");
const DiagnosticsProvider_1 = require("../../../../src/plugins/typescript/features/DiagnosticsProvider");
const LSAndTSDocResolver_1 = require("../../../../src/plugins/typescript/LSAndTSDocResolver");
const service_1 = require("../../../../src/plugins/typescript/service");
const utils_1 = require("../../../../src/utils");
const test_utils_1 = require("../test-utils");
const testDir = path.join(__dirname, '..');
const indent = ' '.repeat(4);
const isSvelte5Plus = +compiler_1.VERSION.split('.')[0] >= 5;
describe('CodeActionsProvider', function () {
    (0, test_utils_1.recursiveServiceWarmup)(this, path.join(testDir, 'testfiles', 'code-actions'), (0, utils_1.pathToUrl)(testDir));
    function getFullPath(filename) {
        return path.join(testDir, 'testfiles', 'code-actions', filename);
    }
    function getUri(filename) {
        return (0, utils_1.pathToUrl)(getFullPath(filename));
    }
    function harmonizeNewLines(input) {
        return input.replace(/\r\n/g, '~:~').replace(/\n/g, '~:~').replace(/~:~/g, '\n');
    }
    function setup(filename) {
        const docManager = new documents_1.DocumentManager((textDocument) => documents_1.Document.createForTest(textDocument.uri, textDocument.text));
        const lsConfigManager = new ls_config_1.LSConfigManager();
        const lsAndTsDocResolver = new LSAndTSDocResolver_1.LSAndTSDocResolver(docManager, [(0, utils_1.pathToUrl)(testDir)], lsConfigManager);
        const completionProvider = new CompletionProvider_1.CompletionsProviderImpl(lsAndTsDocResolver, lsConfigManager);
        const provider = new CodeActionsProvider_1.CodeActionsProviderImpl(lsAndTsDocResolver, completionProvider, lsConfigManager);
        const filePath = getFullPath(filename);
        const document = docManager.openClientDocument({
            uri: (0, utils_1.pathToUrl)(filePath),
            text: typescript_1.default.sys.readFile(filePath) || ''
        });
        return { provider, document, docManager, lsAndTsDocResolver };
    }
    it('provides quickfix', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 4), vscode_languageserver_1.Position.create(6, 5)), {
            diagnostics: [
                {
                    code: 6133,
                    message: "'a' is declared but its value is never read.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 4), vscode_languageserver_1.Position.create(6, 5)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 6
                                        },
                                        end: {
                                            character: 0,
                                            line: 7
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                title: "Remove unused declaration for: 'a'"
            },
            {
                data: {
                    fixId: 'unusedIdentifier_delete',
                    fixName: 'unusedIdentifier',
                    uri: getUri('codeactions.svelte')
                },
                kind: 'quickfix',
                title: 'Delete all unused declarations'
            }
        ]);
    });
    it('provides quickfix for missing function', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 0), vscode_languageserver_1.Position.create(9, 3)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'abc'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 0), vscode_languageserver_1.Position.create(9, 3)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        testFixMissingFunctionQuickFix(codeActions);
    });
    it('provides quickfix for missing function called in the markup', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(11, 1), vscode_languageserver_1.Position.create(11, 4)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'abc'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(11, 1), vscode_languageserver_1.Position.create(11, 4)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        testFixMissingFunctionQuickFix(codeActions);
    });
    it('provides quickfix for missing function called in the element start tag', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(13, 23), vscode_languageserver_1.Position.create(13, 23)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'handleClick'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(13, 23), vscode_languageserver_1.Position.create(13, 34)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: `\n\n${indent}function handleClick(e: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement; }): any {\n` +
                                        `${indent}${indent}throw new Error('Function not implemented.');\n` +
                                        `${indent}}\n`,
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 10
                                        },
                                        end: {
                                            character: 0,
                                            line: 10
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                title: "Add missing function declaration 'handleClick'"
            },
            {
                data: {
                    fixId: 'fixMissingFunctionDeclaration',
                    fixName: 'fixMissingFunctionDeclaration',
                    uri: getUri('codeactions.svelte')
                },
                kind: 'quickfix',
                title: 'Add all missing function declarations'
            }
        ]);
    });
    it('provides quickfix for missing function for element event handler', async () => {
        const { provider, document } = setup('fix-missing-function-element.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 18), vscode_languageserver_1.Position.create(4, 29)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'handleClick'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 18), vscode_languageserver_1.Position.create(4, 29)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: `\n\n${indent}function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement; }) {\n` +
                                        `${indent}${indent}throw new Error("Function not implemented.");\n` +
                                        `${indent}}\n`,
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 2
                                        },
                                        end: {
                                            character: 0,
                                            line: 2
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('fix-missing-function-element.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                title: "Add missing function declaration 'handleClick'"
            }
        ]);
    });
    function testFixMissingFunctionQuickFix(codeActions) {
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: `\n\n${indent}function abc() {\n` +
                                        `${indent}${indent}throw new Error('Function not implemented.');\n` +
                                        `${indent}}\n`,
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 10
                                        },
                                        end: {
                                            character: 0,
                                            line: 10
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                title: "Add missing function declaration 'abc'"
            },
            {
                data: {
                    fixId: 'fixMissingFunctionDeclaration',
                    fixName: 'fixMissingFunctionDeclaration',
                    uri: getUri('codeactions.svelte')
                },
                kind: 'quickfix',
                title: 'Add all missing function declarations'
            }
        ]);
    }
    it('provides quickfix for ts-checked-js', async () => {
        const { provider, document } = setup('codeaction-checkJs.svelte');
        const errorRange = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(2, 21), vscode_languageserver_1.Position.create(2, 26));
        const codeActions = await provider.getCodeActions(document, errorRange, {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'blubb'.",
                    range: errorRange
                }
            ]
        });
        for (const codeAction of codeActions) {
            codeAction.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        }
        const textDocument = {
            uri: getUri('codeaction-checkJs.svelte'),
            version: null
        };
        if (isSvelte5Plus) {
            // Maybe because of the hidden interface declarations? It's harmless anyway
            if (codeActions.length === 4 &&
                codeActions[3].title === "Add '@ts-ignore' to all error messages") {
                codeActions.splice(3, 1);
            }
        }
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: `\n${indent}import { blubb } from "../definitions";\n`,
                                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 8), vscode_languageserver_1.Position.create(0, 8))
                                }
                            ],
                            textDocument
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Add import from "../definitions"'
            },
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '// @ts-ignore\n    ',
                                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(2, 4), vscode_languageserver_1.Position.create(2, 4))
                                }
                            ],
                            textDocument
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Ignore this error message'
            },
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '\n// @ts-nocheck',
                                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 8), vscode_languageserver_1.Position.create(0, 8))
                                }
                            ],
                            textDocument
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Disable checking for this file'
            }
        ]);
    });
    it('provides quickfix for ts-checked-js in context=module', async () => {
        const { provider, document } = setup('codeaction-checkJs-module.svelte');
        const errorRange = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(3, 4), vscode_languageserver_1.Position.create(3, 5));
        const codeActions = await provider.getCodeActions(document, errorRange, {
            diagnostics: [
                {
                    code: 2322,
                    message: "Type 'string' is not assignable to type 'number'.",
                    range: errorRange
                }
            ]
        });
        for (const codeAction of codeActions) {
            codeAction.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        }
        const textDocument = {
            uri: getUri('codeaction-checkJs-module.svelte'),
            version: null
        };
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '// @ts-ignore\n    ',
                                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(3, 4), vscode_languageserver_1.Position.create(3, 4))
                                }
                            ],
                            textDocument
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Ignore this error message'
            },
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '\n// @ts-nocheck',
                                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 25), vscode_languageserver_1.Position.create(0, 25))
                                }
                            ],
                            textDocument
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Disable checking for this file'
            },
            {
                data: {
                    fixId: 'disableJsDiagnostics',
                    fixName: 'disableJsDiagnostics',
                    uri: getUri('codeaction-checkJs-module.svelte')
                },
                kind: 'quickfix',
                title: "Add '@ts-ignore' to all error messages"
            }
        ]);
    });
    it('provide quickfix for adding jsDoc type to props', async () => {
        const { provider, document } = setup('codeaction-add-jsdoc.svelte');
        const errorRange = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(7, 8), vscode_languageserver_1.Position.create(7, 11));
        const codeActions = await provider.getCodeActions(document, errorRange, {
            diagnostics: [
                {
                    code: 7034,
                    message: "Variable 'abc' implicitly has type 'any' in some locations where its type cannot be determined.",
                    range: errorRange
                }
            ]
        });
        const addJsDoc = codeActions.find((fix) => fix.title === "Infer type of 'abc' from usage");
        addJsDoc?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(addJsDoc?.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `/**\n${indent} * @type {any}\n${indent} */\n${indent}`,
                            range: {
                                start: { character: 4, line: 3 },
                                end: { character: 4, line: 3 }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-add-jsdoc.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quickfix for adding jsDoc type to non props when props exist', async () => {
        const { provider, document } = setup('codeaction-add-jsdoc.svelte');
        const errorRange = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 8), vscode_languageserver_1.Position.create(9, 10));
        const codeActions = await provider.getCodeActions(document, errorRange, {
            diagnostics: [
                {
                    code: 7034,
                    message: "Variable 'ab' implicitly has type 'any' in some locations where its type cannot be determined.",
                    range: errorRange
                }
            ]
        });
        const addJsDoc = codeActions.find((fix) => fix.title === "Infer type of 'ab' from usage");
        addJsDoc?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(addJsDoc?.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `/**\n${indent} * @type {any}\n${indent} */\n${indent}`,
                            range: {
                                start: { character: 4, line: 9 },
                                end: { character: 4, line: 9 }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-add-jsdoc.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provides quickfix for component import', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(12, 1), vscode_languageserver_1.Position.create(12, 1)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'Empty'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(12, 1), vscode_languageserver_1.Position.create(12, 6)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: harmonizeNewLines(`${indent}import Empty from '../empty.svelte';\n`),
                                    range: {
                                        end: vscode_languageserver_1.Position.create(5, 0),
                                        start: vscode_languageserver_1.Position.create(5, 0)
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Add import from "../empty.svelte"'
            },
            {
                data: {
                    fixId: 'fixMissingImport',
                    fixName: 'import',
                    uri: getUri('codeactions.svelte')
                },
                kind: 'quickfix',
                title: 'Add all missing imports'
            }
        ]);
    });
    it('provides quickfix for component import with "did you mean" diagnostics', async () => {
        const { provider, document } = setup('codeaction-component-import.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 6)), {
            diagnostics: [
                {
                    code: 2552,
                    message: "Cannot find name 'Empty'. Did you mean 'EMpty'?",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 6)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: harmonizeNewLines(`\n${indent}import Empty from "../empty.svelte";\n`),
                                    range: {
                                        end: vscode_languageserver_1.Position.create(0, 18),
                                        start: vscode_languageserver_1.Position.create(0, 18)
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeaction-component-import.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Add import from "../empty.svelte"'
            },
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: 'EMpty',
                                    range: {
                                        end: vscode_languageserver_1.Position.create(4, 6),
                                        start: vscode_languageserver_1.Position.create(4, 1)
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeaction-component-import.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: "Change spelling to 'EMpty'"
            }
        ]);
    });
    it('remove import inline with script tag', async () => {
        const { provider, document } = setup('remove-imports-inline.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 9), vscode_languageserver_1.Position.create(0, 9)), {
            diagnostics: [
                {
                    code: 6133,
                    message: "'CodeActions' is declared but its value is never read",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 8), vscode_languageserver_1.Position.create(0, 54)),
                    source: 'js'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '',
                                    range: {
                                        end: vscode_languageserver_1.Position.create(0, 54),
                                        start: vscode_languageserver_1.Position.create(0, 8)
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('remove-imports-inline.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: "Remove import from './codeactions.svelte'"
            }
        ]);
    });
    it('provides quickfix for convert const to let', async () => {
        const { provider, document } = setup('codeaction-const-reassign.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(3, 4), vscode_languageserver_1.Position.create(3, 6)), {
            diagnostics: [
                {
                    code: 2588,
                    message: "CCannot assign to 'hi' because it is a constant.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(3, 4), vscode_languageserver_1.Position.create(3, 6)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: 'let',
                                    range: {
                                        start: {
                                            character: 4,
                                            line: 1
                                        },
                                        end: {
                                            character: 9,
                                            line: 1
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeaction-const-reassign.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: "Convert 'const' to 'let'"
            },
            {
                data: {
                    fixId: 'fixConvertConstToLet',
                    fixName: 'fixConvertConstToLet',
                    uri: getUri('codeaction-const-reassign.svelte')
                },
                kind: 'quickfix',
                title: "Convert all 'const' to 'let'"
            }
        ]);
    });
    it("don't provides quickfix for convert const tag to let", async () => {
        const { provider, document } = setup('codeaction-const-reassign.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 28), vscode_languageserver_1.Position.create(9, 35)), {
            diagnostics: [
                {
                    code: 2588,
                    message: "Cannot assign to 'hi2' because it is a constant.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 28), vscode_languageserver_1.Position.create(9, 35)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, []);
    });
    it('provides quickfix to add async to a function', async () => {
        const { provider, document } = setup('fix-add-async.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 8), vscode_languageserver_1.Position.create(6, 9)), {
            diagnostics: [
                {
                    code: 1308,
                    message: "'await' expressions are only allowed within async functions and at the top levels of modules.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 8), vscode_languageserver_1.Position.create(6, 13)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: 'async ',
                                    range: {
                                        end: {
                                            character: 4,
                                            line: 5
                                        },
                                        start: {
                                            character: 4,
                                            line: 5
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('fix-add-async.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'quickfix',
                title: 'Add async modifier to containing function'
            },
            {
                data: {
                    fixId: 'fixAwaitInSyncFunction',
                    fixName: 'fixAwaitInSyncFunction',
                    uri: getUri('fix-add-async.svelte')
                },
                kind: 'quickfix',
                title: "Add all missing 'async' modifiers"
            }
        ]);
    });
    it("don't provides quickfix to add async to the script tag", async () => {
        const { provider, document } = setup('fix-add-async.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(2, 8), vscode_languageserver_1.Position.create(2, 9)), {
            diagnostics: [
                {
                    code: 1308,
                    message: "'await' expressions are only allowed within async functions and at the top levels of modules.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(2, 8), vscode_languageserver_1.Position.create(2, 13)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, []);
    });
    it('provide quick fix to fix all errors when possible', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 0), vscode_languageserver_1.Position.create(9, 3)), {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'abc'.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(9, 0), vscode_languageserver_1.Position.create(9, 3)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n\n${indent}function abc() {\n` +
                                `${indent}${indent}throw new Error('Function not implemented.');\n` +
                                `${indent}}\n`,
                            range: {
                                start: {
                                    character: 0,
                                    line: 10
                                },
                                end: {
                                    character: 0,
                                    line: 10
                                }
                            }
                        },
                        {
                            newText: `\n\n${indent}function handleClick(e: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement; }): any {\n` +
                                `${indent}${indent}throw new Error('Function not implemented.');\n` +
                                `${indent}}\n`,
                            range: {
                                start: {
                                    character: 0,
                                    line: 10
                                },
                                end: {
                                    character: 0,
                                    line: 10
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeactions.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quick fix to fix all missing import component', async () => {
        const { provider, document, docManager, lsAndTsDocResolver } = setup('codeaction-custom-fix-all-component.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 15));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: DiagnosticsProvider_1.DiagnosticCode.CANNOT_FIND_NAME,
                    message: "Cannot find name 'FixAllImported'.",
                    range: range,
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import FixAllImported from \"./importing/FixAllImported.svelte\";\n` +
                                `${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-component.svelte'),
                        version: null
                    }
                }
            ]
        });
        // fix-all has some "creative" workaround. Testing if it won't affect the document synchronization after applying the fix
        docManager.updateDocument(document, resolvedFixAll.edit.documentChanges[0].edits.map((edit) => ({
            range: edit.range,
            text: edit.newText
        })));
        const { lang, tsDoc } = await lsAndTsDocResolver.getLSAndTSDoc(document);
        const cannotFindNameDiagnostics = lang
            .getSemanticDiagnostics(tsDoc.filePath)
            .filter((diagnostic) => diagnostic.code === DiagnosticsProvider_1.DiagnosticCode.CANNOT_FIND_NAME);
        assert.strictEqual(cannotFindNameDiagnostics.length, 0);
    });
    it('provide quick fix to fix all missing import component with "did you mean" diagnostics', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-component4.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 15));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: DiagnosticsProvider_1.DiagnosticCode.CANNOT_FIND_NAME_X_DID_YOU_MEAN_Y,
                    message: "Cannot find name 'FixAllImported'. Did you mean 'FixAllImported3'?",
                    range: range,
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import FixAllImported from \"./importing/FixAllImported.svelte\";\n` +
                                `${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-component4.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quick fix to fix all missing import component without duplicate (script)', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-component2.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(2, 4), vscode_languageserver_1.Position.create(2, 19));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'FixAllImported3'.",
                    range: range,
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import { FixAllImported3 } from \"./importing/c\";\n` +
                                `${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-component2.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quick fix to fix all missing import component without duplicate (template)', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-component3.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 16));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'FixAllImported3'.",
                    range: range,
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import { FixAllImported3 } from \"./importing/c\";` +
                                `\n${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-component3.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quick fix to fix all missing import stores', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-store.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 19));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name '$someOtherStore'.",
                    range: range,
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import { someStore } from \"./importing/a\";\n` +
                                `${indent}import { someOtherStore } from \"./importing/b\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-store.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('provide quick fix to fix all missing import component (without script tag)', async () => {
        const { provider, document } = setup('check-js/codeaction-custom-fix-all-component3.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 1), vscode_languageserver_1.Position.create(0, 15));
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [
                {
                    code: 2304,
                    message: "Cannot find name 'FixAllImported'.",
                    range: range,
                    source: 'js'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        const fixAll = codeActions.find((action) => action.data);
        const resolvedFixAll = await provider.resolveCodeAction(document, fixAll);
        resolvedFixAll?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedFixAll.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: '<script>\n' +
                                `${indent}import FixAllImported from \"./importing/FixAllImported.svelte\";\n` +
                                `${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n\n` +
                                '</script>\n',
                            range: {
                                start: {
                                    character: 0,
                                    line: 0
                                },
                                end: {
                                    character: 0,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('check-js/codeaction-custom-fix-all-component3.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('organizes imports', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { A } from 'bla';\nimport { C } from 'blubb';\n",
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 1
                                        },
                                        end: {
                                            character: 0,
                                            line: 2
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 2
                                        },
                                        end: {
                                            character: 0,
                                            line: 3
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 3
                                        },
                                        end: {
                                            character: 0,
                                            line: 4
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 4
                                        },
                                        end: {
                                            character: 0,
                                            line: 5
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.SourceOrganizeImports,
                title: 'Organize Imports'
            }
        ]);
    });
    it('sort imports', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [CodeActionsProvider_1.SORT_IMPORT_CODE_ACTION_KIND]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { A, B } from 'bla';\n" +
                                        "import { C } from 'blubb';\n" +
                                        "import { D } from 'd';\n",
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 1
                                        },
                                        end: {
                                            character: 0,
                                            line: 2
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 2
                                        },
                                        end: {
                                            character: 0,
                                            line: 3
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 3
                                        },
                                        end: {
                                            character: 0,
                                            line: 4
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 4
                                        },
                                        end: {
                                            character: 0,
                                            line: 5
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: CodeActionsProvider_1.SORT_IMPORT_CODE_ACTION_KIND,
                title: 'Sort Imports'
            }
        ]);
    });
    it('removes unused imports', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [CodeActionsProvider_1.REMOVE_UNUSED_IMPORTS_CODE_ACTION_KIND]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { C } from 'blubb';\n" +
                                        "import { A } from 'bla';\n",
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 1
                                        },
                                        end: {
                                            character: 0,
                                            line: 2
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 2
                                        },
                                        end: {
                                            character: 0,
                                            line: 3
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 3
                                        },
                                        end: {
                                            character: 0,
                                            line: 4
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 4
                                        },
                                        end: {
                                            character: 0,
                                            line: 5
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeactions.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: CodeActionsProvider_1.REMOVE_UNUSED_IMPORTS_CODE_ACTION_KIND,
                title: 'Remove Unused Imports'
            }
        ]);
    });
    it('organizes imports with module script', async () => {
        const { provider, document } = setup('organize-imports-with-module.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { c } from './c';\n",
                                    range: {
                                        start: {
                                            line: 1,
                                            character: 2
                                        },
                                        end: {
                                            line: 2,
                                            character: 0
                                        }
                                    }
                                },
                                {
                                    newText: "import A from './A';\n",
                                    range: {
                                        start: {
                                            line: 6,
                                            character: 2
                                        },
                                        end: {
                                            line: 7,
                                            character: 2
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            line: 7,
                                            character: 2
                                        },
                                        end: {
                                            line: 8,
                                            character: 0
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-with-module.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.SourceOrganizeImports,
                title: 'Organize Imports'
            }
        ]);
    });
    it('organizes imports with module script and store', async () => {
        const { provider, document } = setup('organize-imports-module-store.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { _d } from 'svelte-i18n';\n  import { _e } from 'svelte-i18n1';\n",
                                    range: {
                                        end: {
                                            character: 2,
                                            line: 6
                                        },
                                        start: {
                                            character: 2,
                                            line: 5
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        end: {
                                            character: 2,
                                            line: 7
                                        },
                                        start: {
                                            character: 2,
                                            line: 6
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        start: {
                                            character: 2,
                                            line: 7
                                        },
                                        end: {
                                            character: 0,
                                            line: 8
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-module-store.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: vscode_languageserver_1.CodeActionKind.SourceOrganizeImports,
                title: 'Organize Imports'
            }
        ]);
    });
    it('organizes imports which changes nothing (one import)', async () => {
        const { provider, document } = setup('organize-imports-unchanged1.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { c } from './c';\n",
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 2
                                        },
                                        start: {
                                            character: 2,
                                            line: 1
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-unchanged1.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'source.organizeImports',
                title: 'Organize Imports'
            }
        ]);
    });
    it('organizes imports which changes nothing (two imports)', async () => {
        const { provider, document } = setup('organize-imports-unchanged2.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { c } from './c';\n  import { d } from './d';\n",
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 2
                                        },
                                        start: {
                                            character: 2,
                                            line: 1
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 3
                                        },
                                        start: {
                                            character: 0,
                                            line: 2
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-unchanged2.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'source.organizeImports',
                title: 'Organize Imports'
            }
        ]);
    });
    it('organizes imports and not remove the leading comment', async () => {
        const { provider, document } = setup('organize-imports-leading-comment.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { } from './t.png';\n",
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 2
                                        },
                                        start: {
                                            character: 4,
                                            line: 1
                                        }
                                    }
                                }
                                // Because the generated code adds a ; after the last import, the
                                // second import is not appearing in the edits here
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-leading-comment.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'source.organizeImports',
                title: 'Organize Imports'
            }
        ]);
    });
    it('organize imports should do nothing if there is a parser error', async () => {
        const { provider, document } = setup('organize-imports-error.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        assert.deepStrictEqual(codeActions, []);
    });
    it('organize imports aware of groups', async () => {
        const { provider, document } = setup('organize-imports-group.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: "import { } from 'svelte/transition';\n" +
                                        `${indent}import { } from './codeaction-checkJs.svelte';\n`,
                                    range: {
                                        end: {
                                            character: 4,
                                            line: 4
                                        },
                                        start: {
                                            character: 4,
                                            line: 3
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 5
                                        },
                                        start: {
                                            character: 4,
                                            line: 4
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-group.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'source.organizeImports',
                title: 'Organize Imports'
            }
        ]);
    });
    it('should do extract into const refactor', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const actions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(8, 8), vscode_languageserver_1.Position.create(8, 42)), { diagnostics: [], only: [vscode_languageserver_1.CodeActionKind.Refactor] });
        const action = actions[1];
        assert.deepEqual(action, {
            command: {
                arguments: [
                    getUri('codeactions.svelte'),
                    {
                        type: 'refactor',
                        refactorName: 'Extract Symbol',
                        originalRange: {
                            start: {
                                character: 8,
                                line: 8
                            },
                            end: {
                                character: 42,
                                line: 8
                            }
                        },
                        // is from generated code
                        textRange: {
                            pos: 181,
                            end: 215
                        }
                    }
                ],
                command: 'constant_scope_0',
                title: 'Extract to constant in enclosing scope'
            },
            title: 'Extract to constant in enclosing scope'
        });
        const edit = await provider.executeCommand(document, action.command?.command || '', action.command?.arguments);
        edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: 'const newLocal=Math.random()>0.5? true:false;\n',
                            range: {
                                start: {
                                    character: 0,
                                    line: 8
                                },
                                end: {
                                    character: 0,
                                    line: 8
                                }
                            }
                        },
                        {
                            newText: 'newLocal',
                            range: {
                                start: {
                                    character: 8,
                                    line: 8
                                },
                                end: {
                                    character: 42,
                                    line: 8
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeactions.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('organize imports ignores generated __SvelteComponentTyped__', async () => {
        const { provider, document } = setup('organize-imports-with-generics.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        assert.deepStrictEqual(codeActions, [
            {
                title: 'Organize Imports',
                edit: {
                    documentChanges: [
                        {
                            textDocument: {
                                uri: getUri('organize-imports-with-generics.svelte'),
                                version: null
                            },
                            edits: [
                                {
                                    range: {
                                        start: {
                                            line: 1,
                                            character: 2
                                        },
                                        end: {
                                            line: 2,
                                            character: 2
                                        }
                                    },
                                    newText: "import A from './A';\n"
                                },
                                {
                                    range: {
                                        start: {
                                            line: 2,
                                            character: 2
                                        },
                                        end: {
                                            line: 3,
                                            character: 0
                                        }
                                    },
                                    newText: ''
                                }
                            ]
                        }
                    ]
                },
                kind: 'source.organizeImports'
            }
        ]);
    });
    it('organize imports without leftover indentation', async () => {
        const { provider, document } = setup('organize-import-all-remove.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        assert.deepStrictEqual(codeActions, [
            {
                title: 'Organize Imports',
                edit: {
                    documentChanges: [
                        {
                            textDocument: {
                                uri: getUri('organize-import-all-remove.svelte'),
                                version: null
                            },
                            edits: [
                                {
                                    range: {
                                        start: {
                                            line: 1,
                                            character: 4
                                        },
                                        end: {
                                            line: 2,
                                            character: 4
                                        }
                                    },
                                    newText: ''
                                },
                                {
                                    range: {
                                        start: {
                                            line: 2,
                                            character: 4
                                        },
                                        end: {
                                            line: 3,
                                            character: 0
                                        }
                                    },
                                    newText: ''
                                },
                                {
                                    range: {
                                        start: {
                                            line: 4,
                                            character: 4
                                        },
                                        end: {
                                            line: 5,
                                            character: 4
                                        }
                                    },
                                    newText: ''
                                },
                                {
                                    range: {
                                        start: {
                                            line: 5,
                                            character: 4
                                        },
                                        end: {
                                            line: 6,
                                            character: 0
                                        }
                                    },
                                    newText: ''
                                },
                                {
                                    range: {
                                        start: {
                                            line: 1,
                                            character: 0
                                        },
                                        end: {
                                            line: 1,
                                            character: 4
                                        }
                                    },
                                    newText: ''
                                },
                                {
                                    range: {
                                        start: {
                                            line: 4,
                                            character: 0
                                        },
                                        end: {
                                            line: 4,
                                            character: 4
                                        }
                                    },
                                    newText: ''
                                }
                            ]
                        }
                    ]
                },
                kind: 'source.organizeImports'
            }
        ]);
    });
    it('should do extract into function refactor', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const actions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(8, 8), vscode_languageserver_1.Position.create(8, 42)), { diagnostics: [], only: [vscode_languageserver_1.CodeActionKind.Refactor] });
        const action = actions[0];
        assert.deepStrictEqual(action, {
            command: {
                arguments: [
                    getUri('codeactions.svelte'),
                    {
                        type: 'refactor',
                        refactorName: 'Extract Symbol',
                        originalRange: {
                            start: {
                                character: 8,
                                line: 8
                            },
                            end: {
                                character: 42,
                                line: 8
                            }
                        },
                        // is from generated code
                        textRange: {
                            pos: 181,
                            end: 215
                        }
                    }
                ],
                command: 'function_scope_0',
                title: `Extract to inner function in function '${svelte2tsx_1.internalHelpers.renderName}'`
            },
            title: 'Extract to function'
        });
        const edit = await provider.executeCommand(document, action.command?.command || '', action.command?.arguments);
        edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: 'newFunction()',
                            range: {
                                start: {
                                    character: 8,
                                    line: 8
                                },
                                end: {
                                    character: 42,
                                    line: 8
                                }
                            }
                        },
                        {
                            newText: '\n' +
                                '\n' +
                                'function newFunction() {' +
                                '\n' +
                                'return Math.random()>0.5? true:false;' +
                                '\n' +
                                '}' +
                                '\n',
                            range: {
                                start: {
                                    character: 0,
                                    line: 10
                                },
                                end: {
                                    character: 0,
                                    line: 10
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeactions.svelte'),
                        version: null
                    }
                }
            ]
        });
    });
    it('can cancel quick fix before promise resolved', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const cancellationTokenSource = new vscode_languageserver_1.CancellationTokenSource();
        const codeActionsPromise = provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 4), vscode_languageserver_1.Position.create(6, 5)), {
            diagnostics: [
                {
                    code: 6133,
                    message: "'a' is declared but its value is never read.",
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(6, 4), vscode_languageserver_1.Position.create(6, 5)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        }, cancellationTokenSource.token);
        cancellationTokenSource.cancel();
        assert.deepStrictEqual(await codeActionsPromise, []);
    });
    it('can cancel refactor before promise resolved', async () => {
        const { provider, document } = setup('codeactions.svelte');
        const cancellationTokenSource = new vscode_languageserver_1.CancellationTokenSource();
        const codeActionsPromise = provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(8, 8), vscode_languageserver_1.Position.create(8, 42)), { diagnostics: [], only: [vscode_languageserver_1.CodeActionKind.Refactor] }, cancellationTokenSource.token);
        cancellationTokenSource.cancel();
        assert.deepStrictEqual(await codeActionsPromise, []);
    });
    // Hacky, but it works. Needed due to testing both new and old transformation
    after(() => {
        (0, service_1.__resetCache)();
    });
    it('provides source action for adding all missing imports', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-component5.svelte');
        const range = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 1), vscode_languageserver_1.Position.create(4, 15));
        // Request the specific source action
        const codeActions = await provider.getCodeActions(document, range, {
            diagnostics: [], // Diagnostics might not be needed here if we only want the source action by kind
            only: [CodeActionsProvider_1.ADD_MISSING_IMPORTS_CODE_ACTION_KIND]
        });
        assert.ok(codeActions.length > 0, 'No code actions found');
        // Find the action by its kind
        const addImportsAction = codeActions.find((action) => action.data);
        // Ensure the action was found and has data (as it's now deferred)
        assert.ok(addImportsAction, 'Add missing imports action should be found');
        assert.ok(addImportsAction.data, 'Add missing imports action should have data for resolution');
        // Resolve the action to get the edits
        const resolvedAction = await provider.resolveCodeAction(document, addImportsAction);
        // Assert the edits on the resolved action
        assert.ok(resolvedAction.edit, 'Resolved action should have an edit');
        resolvedAction.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(resolvedAction.edit, {
            documentChanges: [
                {
                    edits: [
                        {
                            newText: `\n${indent}import FixAllImported from \"./importing/FixAllImported.svelte\";\n` +
                                `${indent}import FixAllImported2 from \"./importing/FixAllImported2.svelte\";\n`,
                            range: {
                                start: {
                                    character: 18,
                                    line: 0
                                },
                                end: {
                                    character: 18,
                                    line: 0
                                }
                            }
                        }
                    ],
                    textDocument: {
                        uri: getUri('codeaction-custom-fix-all-component5.svelte'),
                        version: null
                    }
                }
            ]
        });
        // Optional: Verify the kind and title remain correct on the resolved action
        assert.strictEqual(resolvedAction.kind, CodeActionsProvider_1.ADD_MISSING_IMPORTS_CODE_ACTION_KIND);
        assert.strictEqual(resolvedAction.title, 'Add all missing imports');
    });
    it('provides source action for adding all missing imports only when imports are missing', async () => {
        const { provider, document } = setup('codeaction-custom-fix-all-component6.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 4), vscode_languageserver_1.Position.create(1, 5)), {
            diagnostics: [], // No diagnostics = no missing imports
            only: [CodeActionsProvider_1.ADD_MISSING_IMPORTS_CODE_ACTION_KIND]
        });
        assert.deepStrictEqual(codeActions, []);
    });
    it('provides code action for adding lang="ts"', async () => {
        const { provider, document } = setup('codeaction-add-lang-ts.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 0), vscode_languageserver_1.Position.create(0, 1)), {
            diagnostics: [
                {
                    code: 8010,
                    message: 'Type annotations can only be used in TypeScript files.',
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 18), vscode_languageserver_1.Position.create(1, 24)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        assert.deepStrictEqual(codeActions, [
            {
                title: 'Add lang="ts" to <script> tag',
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: ' lang="ts"',
                                    range: {
                                        start: {
                                            character: 7,
                                            line: 0
                                        },
                                        end: {
                                            character: 7,
                                            line: 0
                                        }
                                    }
                                },
                                {
                                    newText: ' lang="ts"',
                                    range: {
                                        start: {
                                            character: 7,
                                            line: 6
                                        },
                                        end: {
                                            character: 7,
                                            line: 6
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeaction-add-lang-ts.svelte'),
                                version: null
                            }
                        }
                    ]
                }
            }
        ]);
    });
    if (!isSvelte5Plus) {
        return;
    }
    it('organizes imports with top-level snippets', async () => {
        const { provider, document } = setup('organize-imports-snippet.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(4, 15), vscode_languageserver_1.Position.create(4, 15)), {
            diagnostics: [],
            only: [vscode_languageserver_1.CodeActionKind.SourceOrganizeImports]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '',
                                    range: {
                                        end: {
                                            character: 0,
                                            line: 5
                                        },
                                        start: {
                                            character: 4,
                                            line: 4
                                        }
                                    }
                                },
                                {
                                    newText: '',
                                    range: {
                                        end: {
                                            character: 4,
                                            line: 4
                                        },
                                        start: {
                                            character: 0,
                                            line: 4
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('organize-imports-snippet.svelte'),
                                version: null
                            }
                        }
                    ]
                },
                kind: 'source.organizeImports',
                title: 'Organize Imports'
            }
        ]);
    });
    it('provides code action for adding <script lang="ts"', async () => {
        const { provider, document } = setup('codeaction-add-lang-ts-no-script.svelte');
        const codeActions = await provider.getCodeActions(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 0), vscode_languageserver_1.Position.create(0, 1)), {
            diagnostics: [
                {
                    code: 8010,
                    message: 'Type annotations can only be used in TypeScript files.',
                    range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(1, 18), vscode_languageserver_1.Position.create(1, 24)),
                    source: 'ts'
                }
            ],
            only: [vscode_languageserver_1.CodeActionKind.QuickFix]
        });
        codeActions[0]?.edit?.documentChanges?.[0]?.edits.forEach((edit) => (edit.newText = harmonizeNewLines(edit.newText)));
        assert.deepStrictEqual(codeActions, [
            {
                title: 'Add <script lang="ts"> tag',
                kind: vscode_languageserver_1.CodeActionKind.QuickFix,
                edit: {
                    documentChanges: [
                        {
                            edits: [
                                {
                                    newText: '<script lang="ts"></script>\n',
                                    range: {
                                        start: {
                                            character: 0,
                                            line: 0
                                        },
                                        end: {
                                            character: 0,
                                            line: 0
                                        }
                                    }
                                }
                            ],
                            textDocument: {
                                uri: getUri('codeaction-add-lang-ts-no-script.svelte'),
                                version: null
                            }
                        }
                    ]
                }
            }
        ]);
    });
});
//# sourceMappingURL=CodeActionsProvider.test.js.map