alm
Version:
The best IDE for TypeScript
161 lines (160 loc) • 6.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/**
* TODO: THIS ISNT USED YET.
* This is used to provide autocomplete / error handling for config files like
* alm.ts // Planned
* gruntfile.ts // Planned
* gulpfile.js // Planned
* webpack.config.js // Planned
*/
var utils = require("../../../common/utils");
var lsh = require("../../../languageServiceHost/languageServiceHost");
var fuzzaldrin = require("fuzzaldrin");
/**
* A simpler project, wraps LanguageServiceHost and LanguageService
* with default options we need for config purposes
*/
var Project = /** @class */ (function () {
function Project() {
this.isSupportedFile = function (filePath) {
var supportedFileNames = {
'tsconfig.json': {
prelude: 'var prelude: {bar: string, bas: "a" | "b"} = ',
}
};
var fileName = utils.getFileName(filePath);
return supportedFileNames[fileName];
};
this.languageServiceHost = new lsh.LanguageServiceHost(undefined, {
allowNonTsExtensions: true,
allowJs: true,
noLib: true,
});
this.languageService = ts.createLanguageService(this.languageServiceHost, ts.createDocumentRegistry());
}
return Project;
}());
exports.project = new Project();
var fmc = require("../../disk/fileModelCache");
// On open add
// On edit edit
// On save reload
fmc.didOpenFile.on(function (e) {
var config = exports.project.isSupportedFile(e.filePath);
if (config) {
var prelude = config.prelude + '\n';
exports.project.languageServiceHost.addScript(e.filePath, prelude + e.contents);
}
});
fmc.didEdits.on(function (e) {
var config = exports.project.isSupportedFile(e.filePath);
if (config) {
var prelude = config.prelude;
var filePath_1 = e.filePath, codeEdits = e.edits;
codeEdits.forEach(function (codeEdit) {
var from = { line: codeEdit.from.line + 1, ch: codeEdit.from.ch };
var to = { line: codeEdit.to.line + 1, ch: codeEdit.to.ch };
exports.project.languageServiceHost.applyCodeEdit(filePath_1, from, to, codeEdit.newText);
debouncedErrorUpdate(filePath_1);
});
}
});
fmc.savedFileChangedOnDisk.on(function (e) {
var config = exports.project.isSupportedFile(e.filePath);
if (config) {
var prelude = config.prelude + '\n';
exports.project.languageServiceHost.setContents(e.filePath, prelude + e.contents);
}
});
// TODO:
// On edit debounce error update
// Provide autocomplete
var debouncedErrorUpdate = utils.debounce(function (filePath) {
// Unlike the big brother Project this one only does live linting on the current file
}, 500);
/**
* Provide autocomplete
*/
function getCompletionsAtPosition(query) {
/**
* Customizations for json lookup
*/
var config = exports.project.isSupportedFile(query.filePath);
var position = query.position + config.prelude.length;
/** The rest is conventional get completions logic: */
var filePath = query.filePath, prefix = query.prefix;
var service = exports.project.languageService;
var completions = service.getCompletionsAtPosition(filePath, position, undefined);
var completionList = completions ? completions.entries.filter(function (x) { return !!x; }) : [];
var endsInPunctuation = utils.prefixEndsInPunctuation(prefix);
if (prefix.length && prefix.trim().length && !endsInPunctuation) {
// Didn't work good for punctuation
completionList = fuzzaldrin.filter(completionList, prefix.trim(), { key: 'name' });
}
/** Doing too many suggestions is slowing us down in some cases */
var maxSuggestions = 50;
/** Doc comments slow us down tremendously */
var maxDocComments = 10;
// limit to maxSuggestions
if (completionList.length > maxSuggestions)
completionList = completionList.slice(0, maxSuggestions);
// Potentially use it more aggresively at some point
// This queries the langauge service so its a bit slow
function docComment(c) {
var completionDetails = exports.project.languageService.getCompletionEntryDetails(filePath, position, c.name, undefined, undefined);
var comment = ts.displayPartsToString(completionDetails.documentation || []);
// Show the signatures for methods / functions
var display;
if (c.kind == "method" || c.kind == "function" || c.kind == "property") {
var parts = completionDetails.displayParts || [];
// don't show `(method)` or `(function)` as that is taken care of by `kind`
if (parts.length > 3) {
parts = parts.splice(3);
}
display = ts.displayPartsToString(parts);
}
else {
display = '';
}
display = display.trim();
return { display: display, comment: comment };
}
var completionsToReturn = completionList.map(function (c, index) {
if (index < maxDocComments) {
var details = docComment(c);
}
else {
details = {
display: '',
comment: ''
};
}
return {
name: c.name,
kind: c.kind,
comment: details.comment,
display: details.display
};
});
// console.log('here2', completionsToReturn);
/**
* More json customizations
*/
completionsToReturn = completionsToReturn
.filter(function (c) { return c.kind != "keyword"; })
.filter(function (c) { return c.kind != "var"; });
/**
* Make completions json friendly
*/
completionsToReturn.forEach(function (c) {
if (c.name !== "false" && c.name !== "true") {
c.name = "\"" + c.name + "\"";
}
});
return utils.resolve({
completions: completionsToReturn,
endsInPunctuation: endsInPunctuation
});
}
exports.getCompletionsAtPosition = getCompletionsAtPosition;