"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const typescript_1 = __importDefault(require("typescript"));
const assert_1 = __importDefault(require("assert"));
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../../../../src/lib/documents");
const ls_config_1 = require("../../../../src/ls-config");
const SemanticTokensProvider_1 = require("../../../../src/plugins/typescript/features/SemanticTokensProvider");
const LSAndTSDocResolver_1 = require("../../../../src/plugins/typescript/LSAndTSDocResolver");
const utils_1 = require("../../../../src/utils");
const test_utils_1 = require("../test-utils");
const compiler_1 = require("svelte/compiler");
const testDir = path_1.default.join(__dirname, '..');
const semanticTokenTestDir = path_1.default.join(testDir, 'testfiles', 'semantic-tokens');
const isSvelte5Plus = +compiler_1.VERSION.split('.')[0] >= 5;
describe('SemanticTokensProvider', function () {
    const tsFile = 'tokens.svelte';
    (0, test_utils_1.serviceWarmup)(this, semanticTokenTestDir, (0, utils_1.pathToUrl)(testDir));
    function setup(filename) {
        const docManager = new documents_1.DocumentManager((textDocument) => new documents_1.Document(textDocument.uri, textDocument.text));
        const filePath = path_1.default.join(semanticTokenTestDir, filename);
        const lsAndTsDocResolver = new LSAndTSDocResolver_1.LSAndTSDocResolver(docManager, [(0, utils_1.pathToUrl)(testDir)], new ls_config_1.LSConfigManager());
        const provider = new SemanticTokensProvider_1.SemanticTokensProviderImpl(lsAndTsDocResolver);
        const document = docManager.openClientDocument({
            uri: (0, utils_1.pathToUrl)(filePath),
            text: typescript_1.default.sys.readFile(filePath)
        });
        return { provider, document };
    }
    it('provides semantic token', async () => {
        const { provider, document } = setup(tsFile);
        const { data } = (await provider.getSemanticTokens(document)) ?? {
            data: []
        };
        assertResult(data, getTsExpected(/* isFull */ true));
    });
    it('provides partial semantic token', async () => {
        const { provider, document } = setup(tsFile);
        const { data } = (await provider.getSemanticTokens(document, vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 0), vscode_languageserver_1.Position.create(9, 0)))) ?? {
            data: []
        };
        assertResult(data, getTsExpected(/* isFull */ false));
    });
    it('provides semantic token for js', async () => {
        const { provider, document } = setup('jsToken.svelte');
        const { data } = (await provider.getSemanticTokens(document)) ?? {
            data: []
        };
        assertResult(data, buildExpected([
            {
                character: 4,
                line: 1,
                length: 'console'.length,
                modifiers: [4 /* TokenModifier.defaultLibrary */],
                type: 7 /* TokenType.variable */
            },
            {
                character: 12,
                line: 1,
                length: 'log'.length,
                modifiers: [4 /* TokenModifier.defaultLibrary */],
                type: 11 /* TokenType.member */
            }
        ]));
    });
    it('can cancel semantic token before promise resolved', async () => {
        const { provider, document } = setup(tsFile);
        const cancellationTokenSource = new vscode_languageserver_1.CancellationTokenSource();
        const tokenPromise = provider.getSemanticTokens(document, undefined, cancellationTokenSource.token);
        cancellationTokenSource.cancel();
        assert_1.default.deepStrictEqual(await tokenPromise, null);
    });
    function buildExpected(tokenData) {
        const builder = new vscode_languageserver_1.SemanticTokensBuilder();
        for (const token of tokenData) {
            builder.push(token.line, token.character, token.length, token.type, token.modifiers.reduce((pre, next) => pre | (1 << next), 0));
        }
        const data = builder.build().data;
        return data;
    }
    function getTsExpected(full) {
        const tokenDataScript = [
            {
                line: 2,
                character: 14,
                length: 'TextContent'.length,
                type: 2 /* TokenType.interface */,
                modifiers: [0 /* TokenModifier.declaration */]
            },
            {
                line: 3,
                character: 8,
                length: 'text'.length,
                type: 9 /* TokenType.property */,
                modifiers: [0 /* TokenModifier.declaration */]
            },
            {
                line: 6,
                character: 15,
                length: 'textPromise'.length,
                type: 7 /* TokenType.variable */,
                modifiers: [0 /* TokenModifier.declaration */, 5 /* TokenModifier.local */]
            },
            {
                line: 6,
                character: 28,
                length: 'Promise'.length,
                type: 2 /* TokenType.interface */,
                modifiers: [4 /* TokenModifier.defaultLibrary */]
            },
            {
                line: 6,
                character: 36,
                length: 'TextContent'.length,
                type: 2 /* TokenType.interface */,
                modifiers: []
            },
            {
                line: 8,
                character: 19,
                length: 'blurHandler'.length,
                type: 10 /* TokenType.function */,
                modifiers: [2 /* TokenModifier.async */, 0 /* TokenModifier.declaration */, 5 /* TokenModifier.local */]
            }
        ];
        const tokenDataAll = [
            ...tokenDataScript,
            {
                line: 11,
                character: 8,
                length: 'textPromise'.length,
                type: 7 /* TokenType.variable */,
                modifiers: [5 /* TokenModifier.local */]
            },
            {
                line: 11,
                character: 25,
                length: 'text'.length,
                type: 7 /* TokenType.variable */,
                modifiers: [0 /* TokenModifier.declaration */, 5 /* TokenModifier.local */, 3 /* TokenModifier.readonly */]
            },
            {
                line: 12,
                character: 23,
                length: 'blurHandler'.length,
                type: 10 /* TokenType.function */,
                modifiers: [2 /* TokenModifier.async */, 5 /* TokenModifier.local */]
            },
            {
                line: 12,
                character: 43,
                length: 'text'.length,
                type: 7 /* TokenType.variable */,
                modifiers: [5 /* TokenModifier.local */, 3 /* TokenModifier.readonly */]
            },
            {
                line: 12,
                character: 48,
                length: 'text'.length,
                type: 9 /* TokenType.property */,
                modifiers: []
            },
            {
                line: 14,
                character: 16,
                length: 1,
                type: 7 /* TokenType.variable */,
                modifiers: [0 /* TokenModifier.declaration */, 5 /* TokenModifier.local */]
            },
            {
                line: 15,
                character: 5,
                length: 1,
                type: 7 /* TokenType.variable */,
                modifiers: [5 /* TokenModifier.local */]
            }
        ];
        return buildExpected(full ? tokenDataAll : tokenDataScript);
    }
    /**
     *  group result by tokens to better distinguish
     */
    function assertResult(actual, expected) {
        const actualGrouped = group(actual);
        const expectedGrouped = group(expected);
        assert_1.default.deepStrictEqual(actualGrouped, expectedGrouped);
    }
    function group(tokens) {
        const result = [];
        let index = 0;
        while (index < tokens.length) {
            result.push(tokens.slice(index, (index += 5)));
        }
        return result;
    }
});
//# sourceMappingURL=SemanticTokensProvider.test.js.map