UNPKG

alm

Version:

The best IDE for TypeScript

161 lines (160 loc) 6.1 kB
"use strict"; 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;