"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;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const assert = __importStar(require("assert"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../../../../src/lib/documents");
const getDiagnostics_1 = require("../../../../src/plugins/svelte/features/getDiagnostics");
const SvelteDocument_1 = require("../../../../src/plugins/svelte/SvelteDocument");
const ls_config_1 = require("../../../../src/ls-config");
const utils_1 = require("../../../../src/utils");
const plugins_1 = require("../../../../src/plugins");
const compiler_1 = require("svelte/compiler");
const isSvelte5Plus = Number(compiler_1.VERSION.split('.')[0]) >= 5;
describe('SveltePlugin#getDiagnostics', () => {
    async function expectDiagnosticsFor({ getTranspiled, getCompiled, config, settings = {}, docText = '<script></script>\n<style></style>' }) {
        const document = new documents_1.Document('', docText);
        const svelteDoc = {
            getTranspiled,
            getCompiled,
            config,
            getSvelteVersion: () => [4, 0]
        };
        const result = await (0, getDiagnostics_1.getDiagnostics)(document, svelteDoc, settings);
        return {
            toEqual: (expected) => assert.deepStrictEqual(result, expected)
        };
    }
    function setupFromFile(filename) {
        const testDir = path.join(__dirname, '..');
        const filePath = path.join(testDir, 'testfiles', filename);
        const document = new documents_1.Document((0, utils_1.pathToUrl)(filePath), fs.readFileSync(filePath, 'utf-8'));
        const pluginManager = new ls_config_1.LSConfigManager();
        const plugin = new plugins_1.SveltePlugin(pluginManager);
        return { plugin, document };
    }
    it('expect svelte.config.js error', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => {
                throw new Error();
            },
            getCompiled: () => '',
            config: { loadConfigError: new Error('svelte.config.js') }
        })).toEqual([
            {
                message: 'Error in svelte.config.js\n\nError: svelte.config.js',
                range: {
                    start: {
                        character: 0,
                        line: 0
                    },
                    end: {
                        character: 5,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte'
            }
        ]);
    });
    it('expect script transpilation error', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => {
                const e = new Error('Script');
                e.__source = SvelteDocument_1.TranspileErrorSource.Script;
                throw e;
            },
            getCompiled: () => '',
            config: {}
        })).toEqual([
            {
                message: 'Script',
                range: {
                    start: {
                        character: 8,
                        line: 0
                    },
                    end: {
                        character: 8,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte(script)'
            }
        ]);
    });
    it('expect style transpilation error', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => {
                const e = new Error('Style');
                e.__source = SvelteDocument_1.TranspileErrorSource.Style;
                throw e;
            },
            getCompiled: () => '',
            config: {}
        })).toEqual([
            {
                message: 'Style',
                range: {
                    start: {
                        character: 7,
                        line: 1
                    },
                    end: {
                        character: 7,
                        line: 1
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte(style)'
            }
        ]);
    });
    it('expect style transpilation error with line/columns', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => {
                const e = new Error('Style');
                e.line = 1;
                e.column = 0;
                e.__source = SvelteDocument_1.TranspileErrorSource.Style;
                throw e;
            },
            getCompiled: () => '',
            config: {}
        })).toEqual([
            {
                message: 'Style',
                range: {
                    start: {
                        character: 0,
                        line: 1
                    },
                    end: {
                        character: 0,
                        line: 1
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte(style)'
            }
        ]);
    });
    it('expect compilation error', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: () => vscode_languageserver_1.Position.create(0, 0)
            }),
            getCompiled: () => {
                const e = new Error('Compilation');
                e.message = 'ERROR';
                e.code = 123;
                throw e;
            },
            config: {}
        })).toEqual([
            {
                code: 123,
                message: 'ERROR',
                range: {
                    start: {
                        character: 0,
                        line: 0
                    },
                    end: {
                        character: 0,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte'
            }
        ]);
    });
    it('expect compilation error with expected', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: () => vscode_languageserver_1.Position.create(0, 8)
            }),
            getCompiled: () => {
                const e = new Error('Compilation');
                e.message = 'expected x to not be here';
                e.code = 123;
                e.start = { line: 1, column: 8 };
                throw e;
            },
            config: {}
        })).toEqual([
            {
                code: 123,
                message: 'expected x to not be here' +
                    '\n\nIf you expect this syntax to work, here are some suggestions: ' +
                    '\nIf you use typescript with `svelte-preprocess`, did you add `lang="ts"` to your `script` tag? ' +
                    '\nDid you setup a `svelte.config.js` or `vite.config.js`? ' +
                    '\nSee https://github.com/sveltejs/language-tools/tree/master/docs#using-with-preprocessors for more info.',
                range: {
                    start: {
                        character: 8,
                        line: 0
                    },
                    end: {
                        character: 8,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte'
            }
        ]);
    });
    it('expect valid position for compilation error', async () => {
        const message = 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)';
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: () => vscode_languageserver_1.Position.create(-1, -1)
            }),
            getCompiled: () => {
                const e = new Error();
                e.message = message;
                e.code = 123;
                e.start = { line: 1, column: 8 };
                throw e;
            },
            config: {}
        })).toEqual([
            {
                code: 123,
                message,
                range: {
                    start: {
                        character: 0,
                        line: 0
                    },
                    end: {
                        character: 0,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte'
            }
        ]);
    });
    it('expect warnings', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: (pos) => {
                    pos.line - 1;
                    return pos;
                }
            }),
            getCompiled: () => Promise.resolve({
                warnings: [
                    {
                        start: { line: 1, column: 0 },
                        end: { line: 1, column: 0 },
                        message: 'warning',
                        code: 123
                    }
                ]
            }),
            config: {
                preprocess: []
            }
        })).toEqual([
            {
                code: 123,
                message: 'warning',
                range: {
                    start: {
                        character: 0,
                        line: 0
                    },
                    end: {
                        character: 0,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Warning,
                source: 'svelte'
            }
        ]);
    });
    it('filter out false positive warning (export enum)', async () => {
        (await expectDiagnosticsFor({
            docText: '<script context="module">export enum A { B }</script>',
            getTranspiled: () => ({
                getOriginalPosition: (pos) => {
                    return pos;
                }
            }),
            getCompiled: () => Promise.resolve({
                stats: {
                    warnings: [
                        {
                            start: { line: 1, column: 32 },
                            end: { line: 1, column: 33 },
                            message: "Component has unused export property 'A'. If it is for external reference only, please consider using `export const A`",
                            code: 'unused-export-let'
                        }
                    ]
                }
            }),
            config: {
                preprocess: []
            }
        })).toEqual([]);
    });
    it('filter out false positive warning (export namespace)', async () => {
        (await expectDiagnosticsFor({
            docText: '<script context="module">export namespace foo { export function bar() {} }</script>',
            getTranspiled: () => ({
                getOriginalPosition: (pos) => {
                    return pos;
                }
            }),
            getCompiled: () => Promise.resolve({
                stats: {
                    warnings: [
                        {
                            start: { line: 1, column: 43 },
                            end: { line: 1, column: 46 },
                            message: "Component has unused export property 'foo'. If it is for external reference only, please consider using `export const foo`",
                            code: 'unused-export-let'
                        }
                    ]
                }
            }),
            config: {
                preprocess: []
            }
        })).toEqual([]);
    });
    it('filter out warnings', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: (pos) => {
                    pos.line - 1;
                    return pos;
                }
            }),
            getCompiled: () => Promise.resolve({
                stats: {
                    warnings: [
                        {
                            start: { line: 1, column: 0 },
                            end: { line: 1, column: 0 },
                            message: 'warning',
                            code: '123'
                        }
                    ]
                }
            }),
            config: {
                preprocess: []
            },
            settings: { 123: 'ignore' }
        })).toEqual([]);
    });
    it('treat warnings as error', async () => {
        (await expectDiagnosticsFor({
            getTranspiled: () => ({
                getOriginalPosition: (pos) => {
                    pos.line - 1;
                    return pos;
                }
            }),
            getCompiled: () => Promise.resolve({
                warnings: [
                    {
                        start: { line: 1, column: 0 },
                        end: { line: 1, column: 0 },
                        message: 'warning',
                        code: '123'
                    }
                ]
            }),
            config: {
                preprocess: []
            },
            settings: { 123: 'error' }
        })).toEqual([
            {
                code: '123',
                message: 'warning',
                range: {
                    start: {
                        character: 0,
                        line: 0
                    },
                    end: {
                        character: 0,
                        line: 0
                    }
                },
                severity: vscode_languageserver_1.DiagnosticSeverity.Error,
                source: 'svelte'
            }
        ]);
    });
    it('should correctly determine diagnostic position', async () => {
        const { plugin, document } = setupFromFile('diagnostics.svelte');
        const diagnostics = await plugin.getDiagnostics(document);
        assert.deepStrictEqual(diagnostics, [
            {
                range: { start: { line: 1, character: 15 }, end: { line: 1, character: 27 } },
                message: (isSvelte5Plus ? 'Component' : 'Diagnostics') +
                    " has unused export property 'name'. If it is for external reference only, please consider using `export const name`" +
                    (isSvelte5Plus ? '\nhttps://svelte.dev/e/export_let_unused' : ''),
                severity: 2,
                source: 'svelte',
                code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let',
                codeDescription: {
                    href: isSvelte5Plus
                        ? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
                        : // doesn't actually exist but at least points to the page
                            'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
                }
            }
        ]);
    });
    it('should correctly determine diagnostic position for context="module"', async () => {
        const { plugin, document } = setupFromFile('diagnostics-module.svelte');
        const diagnostics = await plugin.getDiagnostics(document);
        assert.deepStrictEqual(diagnostics.filter((d) => d.code !== 'script_context_deprecated'), [
            {
                range: { start: { line: 1, character: 4 }, end: { line: 1, character: 26 } },
                message: isSvelte5Plus
                    ? 'Reactive declarations only exist at the top level of the instance script\nhttps://svelte.dev/e/reactive_declaration_invalid_placement'
                    : '$: has no effect in a module script',
                severity: 2,
                source: 'svelte',
                code: isSvelte5Plus
                    ? 'reactive_declaration_invalid_placement'
                    : 'module-script-reactive-declaration',
                codeDescription: {
                    href: isSvelte5Plus
                        ? 'https://svelte.dev/docs/svelte/compiler-warnings#reactive_declaration_invalid_placement'
                        : 'https://svelte.dev/docs/svelte/compiler-warnings#module_script_reactive_declaration'
                }
            }
        ]);
    });
    it('should correctly determine diagnostic position for script when theres also context="module"', async () => {
        const { plugin, document } = setupFromFile('diagnostics-module-and-instance.svelte');
        const diagnostics = await plugin.getDiagnostics(document);
        assert.deepStrictEqual(diagnostics.filter((d) => d.code !== 'script_context_deprecated'), [
            {
                code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let',
                message: (isSvelte5Plus ? 'Component' : 'Diagnostics_module_and_instance') +
                    " has unused export property 'unused1'. If it is for external reference only, please consider using `export const unused1`" +
                    (isSvelte5Plus ? '\nhttps://svelte.dev/e/export_let_unused' : ''),
                range: {
                    start: {
                        line: 5,
                        character: 13
                    },
                    end: {
                        line: 5,
                        character: isSvelte5Plus ? 20 : 27
                    }
                },
                severity: 2,
                source: 'svelte',
                codeDescription: {
                    href: isSvelte5Plus
                        ? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
                        : // doesn't actually exist but at least points to the page
                            'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
                }
            },
            {
                code: isSvelte5Plus ? 'export_let_unused' : 'unused-export-let',
                message: (isSvelte5Plus ? 'Component' : 'Diagnostics_module_and_instance') +
                    " has unused export property 'unused2'. If it is for external reference only, please consider using `export const unused2`" +
                    (isSvelte5Plus ? '\nhttps://svelte.dev/e/export_let_unused' : ''),
                range: {
                    start: {
                        line: 6,
                        character: 13
                    },
                    end: {
                        line: 6,
                        character: isSvelte5Plus ? 20 : 27
                    }
                },
                severity: 2,
                source: 'svelte',
                codeDescription: {
                    href: isSvelte5Plus
                        ? 'https://svelte.dev/docs/svelte/compiler-warnings#export_let_unused'
                        : // doesn't actually exist but at least points to the page
                            'https://svelte.dev/docs/svelte/compiler-warnings#unused_export_let'
                }
            }
        ]);
    });
});
//# sourceMappingURL=getDiagnostics.test.js.map