UNPKG

alm

Version:

The best IDE for TypeScript

128 lines (127 loc) 5.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = require("path"); var utils = require("../../../../common/utils"); var fsu = require("../../../utils/fsu"); var fuzzaldrin = require("fuzzaldrin"); /** From https://github.com/Microsoft/TypeScript/pull/2173/files */ function getExternalModuleNames(program) { var entries = []; program.getSourceFiles().forEach(function (sourceFile) { // Look for ambient external module declarations ts.forEachChild(sourceFile, function (child) { if (child.kind === ts.SyntaxKind.ModuleDeclaration && child.name.kind === ts.SyntaxKind.StringLiteral) { var name_1 = child.name.text; if (name_1.endsWith('/index')) { name_1 = utils.getDirectory(name_1); } entries.push(name_1); } }); }); return entries; } function isStringLiteralInES6ImportDeclaration(node) { if (node.kind !== ts.SyntaxKind.StringLiteral) return false; while (node.parent.kind !== ts.SyntaxKind.SourceFile && node.parent.kind !== ts.SyntaxKind.ImportDeclaration) { node = node.parent; } return node.parent && node.parent.kind === ts.SyntaxKind.ImportDeclaration; } function isStringLiteralInImportRequireDeclaration(node) { if (node.kind !== ts.SyntaxKind.StringLiteral) return false; while (node.parent.kind !== ts.SyntaxKind.SourceFile && node.parent.kind !== ts.SyntaxKind.ImportEqualsDeclaration) { node = node.parent; } return node.parent && node.parent.kind === ts.SyntaxKind.ImportEqualsDeclaration; } /** Removes the quote characters / `.` and `/` as they cause fuzzaldrin to break */ function sanitizePrefix(prefix) { var result = prefix.replace(/\.|\/|\'|\"|/g, ''); return result; } function getPathCompletionsForImport(query) { var project = query.project; var sourceDir = path.dirname(query.filePath); var filePaths = project.configFile.project.files.filter(function (p) { return p !== query.filePath && !p.endsWith('.json'); }); var files = []; var externalModules = getExternalModuleNames(project.languageService.getProgram()); externalModules.forEach(function (e) { return files.push({ fileName: "" + e, relativePath: e, fullPath: e }); }); filePaths.forEach(function (p) { files.push({ fileName: fsu.removeExt(utils.getFileName(p)), relativePath: fsu.removeExt(fsu.makeRelativePath(sourceDir, p)), fullPath: p }); }); var sanitizedPrefix = sanitizePrefix(query.prefix); var endsInPunctuation = utils.prefixEndsInPunctuation(sanitizedPrefix); if (!endsInPunctuation) files = fuzzaldrin.filter(files, sanitizedPrefix, { key: 'fileName' }); return files; } exports.getPathCompletionsForImport = getPathCompletionsForImport; /** * Very similar to above. But * - aborts if position not valid to autocomplete * - automatically excludes `externalModules` if position is reference tag */ function getPathCompletionsForAutocomplete(query) { var sourceFile = query.project.languageService.getNonBoundSourceFile(query.filePath); var positionNode = ts.getTokenAtPosition(sourceFile, query.position, true); /** Note: in referenceTag is not supported yet */ var inReferenceTagPath = false; var inES6ModuleImportString = isStringLiteralInES6ImportDeclaration(positionNode); var inImportRequireString = isStringLiteralInImportRequireDeclaration(positionNode); if (!inReferenceTagPath && !inES6ModuleImportString && !inImportRequireString) { return []; } /** We have to be in a string literal (as reference tag isn't supproted yet) */ var pathStringText = positionNode.getFullText(); var leadingText = pathStringText.match(/^\s+['|"]/g); var trailingText = pathStringText.match(/['|"]$/g); var from = leadingText ? positionNode.pos + leadingText[0].length : positionNode.pos; var to = trailingText ? positionNode.end - trailingText[0].length : positionNode.end; var pathStringRange = { from: from, to: to }; // console.log({textThatWillBeReplaced:sourceFile.getFullText().substr(from, to-from)}); // DEBUG var project = query.project; var sourceDir = path.dirname(query.filePath); var filePaths = project.configFile.project.files.filter(function (p) { return p !== query.filePath && !p.endsWith('.json'); }); var files = []; if (!inReferenceTagPath) { var externalModules = getExternalModuleNames(project.languageService.getProgram()); externalModules.forEach(function (e) { return files.push({ fileName: "" + e, relativePath: e, fullPath: e, pathStringRange: pathStringRange, }); }); } filePaths.forEach(function (p) { var lowerCaseExtRemoved = fsu.removeExt(p.toLowerCase()); if (lowerCaseExtRemoved.endsWith('/index') || lowerCaseExtRemoved.endsWith('/index.d')) { p = utils.getDirectory(p); } files.push({ fileName: fsu.removeExt(utils.getFileName(p)), relativePath: fsu.removeExt(fsu.makeRelativePath(sourceDir, p)), fullPath: p, pathStringRange: pathStringRange, }); }); var sanitizedPrefix = sanitizePrefix(query.prefix); return files; } exports.getPathCompletionsForAutocomplete = getPathCompletionsForAutocomplete;