alm
Version:
The best IDE for TypeScript
128 lines (127 loc) • 5.55 kB
JavaScript
;
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;