"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 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 CallHierarchyProvider_1 = require("../../../../src/plugins/typescript/features/CallHierarchyProvider");
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 compiler_1 = require("svelte/compiler");
const testDir = path.join(__dirname, '..');
const isSvelte5Plus = +compiler_1.VERSION.split('.')[0] >= 5;
describe('CallHierarchyProvider', function () {
    const callHierarchyTestDirRelative = path.join('testfiles', 'call-hierarchy');
    (0, test_utils_1.serviceWarmup)(this, path.join(testDir, callHierarchyTestDirRelative), (0, utils_1.pathToUrl)(testDir));
    function getFullPath(filename) {
        return path.join(testDir, 'testfiles', 'call-hierarchy', 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) => new documents_1.Document(textDocument.uri, textDocument.text));
        const lsConfigManager = new ls_config_1.LSConfigManager();
        const workspaceUris = [(0, utils_1.pathToUrl)(testDir)];
        const lsAndTsDocResolver = new LSAndTSDocResolver_1.LSAndTSDocResolver(docManager, workspaceUris, lsConfigManager);
        const provider = new CallHierarchyProvider_1.CallHierarchyProviderImpl(lsAndTsDocResolver, workspaceUris);
        const filePath = getFullPath(filename);
        const document = docManager.openClientDocument({
            uri: (0, utils_1.pathToUrl)(filePath),
            text: harmonizeNewLines(typescript_1.default.sys.readFile(filePath) || '')
        });
        return { provider, document, docManager };
    }
    const callHierarchyImportFileName = 'call-hierarchy-import.svelte';
    const fooInImportItem = {
        kind: vscode_languageserver_1.SymbolKind.Function,
        name: 'foo',
        range: {
            start: {
                line: 5,
                character: 4
            },
            end: {
                line: 7,
                character: 5
            }
        },
        selectionRange: {
            start: {
                line: 5,
                character: 13
            },
            end: {
                line: 5,
                character: 16
            }
        },
        detail: undefined,
        tags: undefined,
        uri: getUri(callHierarchyImportFileName)
    };
    it('can prepare call hierarchy', async () => {
        const { provider, document } = setup(callHierarchyImportFileName);
        const item = await provider.prepareCallHierarchy(document, { line: 9, character: 4 });
        assert.deepStrictEqual(item, [fooInImportItem]);
    });
    const formatDateCallHierarchyItem = {
        kind: vscode_languageserver_1.SymbolKind.Function,
        name: 'formatDate',
        range: {
            start: {
                line: 0,
                character: 0
            },
            end: {
                line: 0,
                character: 41
            }
        },
        selectionRange: {
            start: {
                line: 0,
                character: 16
            },
            end: {
                line: 0,
                character: 26
            }
        },
        detail: undefined,
        tags: undefined,
        uri: getUri('util.ts')
    };
    it('can prepare call hierarchy for imported file', async () => {
        const { provider, document } = setup(callHierarchyImportFileName);
        const item = await provider.prepareCallHierarchy(document, { line: 6, character: 8 });
        assert.deepStrictEqual(item, [formatDateCallHierarchyItem]);
    });
    it('can provide incoming calls', async () => {
        const { provider, document } = setup(callHierarchyImportFileName);
        const items = await provider.prepareCallHierarchy(document, { line: 6, character: 8 });
        const incoming = await provider.getIncomingCalls(items[0]);
        assert.deepStrictEqual(incoming, [
            {
                from: {
                    kind: vscode_languageserver_1.SymbolKind.Function,
                    name: 'formatDate2',
                    range: {
                        start: {
                            line: 2,
                            character: 0
                        },
                        end: {
                            line: 4,
                            character: 1
                        }
                    },
                    selectionRange: {
                        start: {
                            line: 2,
                            character: 16
                        },
                        end: {
                            line: 2,
                            character: 27
                        }
                    },
                    detail: undefined,
                    tags: undefined,
                    uri: getUri('util.ts')
                },
                fromRanges: [
                    {
                        end: {
                            character: 14,
                            line: 3
                        },
                        start: {
                            character: 4,
                            line: 3
                        }
                    }
                ]
            },
            {
                from: {
                    name: 'another-ref-format-date.svelte',
                    range: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 4,
                            character: 9
                        }
                    },
                    selectionRange: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 0,
                            character: 0
                        }
                    },
                    kind: vscode_languageserver_1.SymbolKind.Module,
                    uri: getUri('another-ref-format-date.svelte'),
                    detail: callHierarchyTestDirRelative
                },
                fromRanges: [
                    {
                        start: {
                            line: 3,
                            character: 4
                        },
                        end: {
                            line: 3,
                            character: 14
                        }
                    }
                ]
            },
            {
                from: {
                    name: callHierarchyImportFileName,
                    kind: vscode_languageserver_1.SymbolKind.Module,
                    range: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 12,
                            character: 24
                        }
                    },
                    selectionRange: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 0,
                            character: 0
                        }
                    },
                    detail: callHierarchyTestDirRelative,
                    uri: getUri(callHierarchyImportFileName)
                },
                fromRanges: [
                    {
                        start: {
                            line: 3,
                            character: 4
                        },
                        end: {
                            line: 3,
                            character: 14
                        }
                    },
                    {
                        start: {
                            line: 12,
                            character: 1
                        },
                        end: {
                            line: 12,
                            character: 11
                        }
                    }
                ]
            },
            {
                from: fooInImportItem,
                fromRanges: [
                    {
                        start: {
                            character: 8,
                            line: 6
                        },
                        end: {
                            character: 18,
                            line: 6
                        }
                    }
                ]
            }
        ]);
    });
    const outgoingComponentName = 'outgoing-component.svelte';
    it('can provide incoming calls for component file', async () => {
        const { provider, document } = setup('another-ref-format-date.svelte');
        const items = await provider.prepareCallHierarchy(document, { line: 0, character: 2 });
        const incoming = await provider.getIncomingCalls(items[0]);
        assert.deepStrictEqual(incoming, [
            {
                from: {
                    detail: callHierarchyTestDirRelative,
                    kind: vscode_languageserver_1.SymbolKind.Module,
                    name: outgoingComponentName,
                    range: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 10,
                            character: 24
                        }
                    },
                    selectionRange: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 0,
                            character: 0
                        }
                    },
                    uri: getUri(outgoingComponentName)
                },
                fromRanges: [
                    {
                        start: {
                            character: 1,
                            line: 10
                        },
                        end: {
                            character: 21,
                            line: 10
                        }
                    }
                ]
            }
        ]);
    });
    const outgoingComponentHiFunctionCall = {
        to: {
            kind: vscode_languageserver_1.SymbolKind.Function,
            name: 'log',
            range: {
                start: {
                    line: 7,
                    character: 4
                },
                end: {
                    line: 7,
                    character: 32
                }
            },
            selectionRange: {
                start: {
                    line: 7,
                    character: 13
                },
                end: {
                    line: 7,
                    character: 16
                }
            },
            detail: undefined,
            tags: undefined,
            uri: getUri(outgoingComponentName)
        },
        fromRanges: [
            {
                end: {
                    character: 11,
                    line: 4
                },
                start: {
                    character: 8,
                    line: 4
                }
            }
        ]
    };
    it('can provide outgoing calls', async () => {
        const { provider, document } = setup(outgoingComponentName);
        const items = await provider.prepareCallHierarchy(document, { line: 3, character: 14 });
        const incoming = await provider.getOutgoingCalls(items[0]);
        assert.deepStrictEqual(incoming, [outgoingComponentHiFunctionCall]);
    });
    it('can provide outgoing calls for component file', async () => {
        if (isSvelte5Plus) {
            // Doesn't work due to https://github.com/microsoft/TypeScript/issues/43740 and https://github.com/microsoft/TypeScript/issues/42375
            return;
        }
        const { provider, document } = setup(outgoingComponentName);
        const items = await provider.prepareCallHierarchy(document, { line: 10, character: 1 });
        const outgoing = await provider.getOutgoingCalls(items[0]);
        assert.deepStrictEqual(outgoing, [
            {
                to: formatDateCallHierarchyItem,
                fromRanges: [
                    {
                        end: {
                            character: 14,
                            line: 3
                        },
                        start: {
                            character: 4,
                            line: 3
                        }
                    }
                ]
            }
        ]);
    });
    it('can provide outgoing calls for component tags', async () => {
        if (isSvelte5Plus) {
            // Doesn't work due to https://github.com/microsoft/TypeScript/issues/43740 and https://github.com/microsoft/TypeScript/issues/42375
            return;
        }
        const { provider, document } = setup(outgoingComponentName);
        const items = await provider.prepareCallHierarchy(document, { line: 0, character: 2 });
        const outgoing = await provider.getOutgoingCalls(items[0]);
        assert.deepStrictEqual(outgoing, [
            {
                fromRanges: [
                    {
                        end: {
                            character: 21,
                            line: 10
                        },
                        start: {
                            character: 1,
                            line: 10
                        }
                    }
                ],
                to: {
                    detail: callHierarchyTestDirRelative,
                    kind: vscode_languageserver_1.SymbolKind.Module,
                    name: 'another-ref-format-date.svelte',
                    uri: getUri('another-ref-format-date.svelte'),
                    range: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 4,
                            character: 9
                        }
                    },
                    selectionRange: {
                        start: {
                            line: 0,
                            character: 0
                        },
                        end: {
                            line: 0,
                            character: 0
                        }
                    }
                }
            }
        ]);
    });
    // Hacky, but it works. Needed due to testing both new and old transformation
    after(() => {
        (0, service_1.__resetCache)();
    });
});
//# sourceMappingURL=CallHierarchyProvider.test.js.map