UNPKG

alm

Version:

The best IDE for TypeScript

173 lines (172 loc) 8.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var lsh = require("../../../languageServiceHost/languageServiceHost"); var languageServiceHost = new lsh.LanguageServiceHost(undefined); var languageService = ts.createLanguageService(languageServiceHost); /** * ts syntax highlighter doesn't handle bom correctly so fix that */ var BOM_CHAR_CODE = 65279; var hasBom = Object.create(null); function addFile(filePath, contents) { hasBom[filePath] = contents.charCodeAt(0) === BOM_CHAR_CODE; languageServiceHost.addScript(filePath, contents); } exports.addFile = addFile; function removeFile(filePath) { languageServiceHost.removeFile(filePath); } exports.removeFile = removeFile; function editFile(filePath, codeEdit) { languageServiceHost.applyCodeEdit(filePath, codeEdit.from, codeEdit.to, codeEdit.newText); } exports.editFile = editFile; function setContents(filePath, contents) { hasBom[filePath] = contents.charCodeAt(0) === BOM_CHAR_CODE; languageServiceHost.setContents(filePath, contents); } exports.setContents = setContents; function getLineAndCharacterOfPosition(filePath, pos) { return languageServiceHost.getLineAndCharacterOfPosition(filePath, pos); } exports.getLineAndCharacterOfPosition = getLineAndCharacterOfPosition; function getPositionOfLineAndCharacter(filePath, line, ch) { return languageServiceHost.getPositionOfLineAndCharacter(filePath, line, ch); } exports.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter; function getSourceFile(filePath) { return languageService.getNonBoundSourceFile(filePath); } exports.getSourceFile = getSourceFile; function getClassificationsForLine(filePath, lineStart, string) { var offsetForBom = hasBom[filePath] ? -1 : 0; // don't need this for monaco! /** * Protect against code mirror optimized rendering. * If string does not match expected line contents tokenize as whitespace till the precise call is made. */ // const trueLineContents = languageService.getNonBoundSourceFile(filePath).text.substr(lineStart); // if (!trueLineContents.startsWith(string)){ // // console.log({ trueLineContents, string, filePath }); // DEBUG // const cantDoIt = [{ // textSpan: { // start:0, // length: string.length // }, // startInLine: 0, // string, // classificationType: ts.ClassificationType.whiteSpace, // classificationTypeName: ClassificationTypeNames.whiteSpace, // }]; // return cantDoIt; // } var lineLength = string.length; var encodedClassifications = languageService.getEncodedSyntacticClassifications(filePath, { start: lineStart, length: lineLength }); var classifications = unencodeClassifications(encodedClassifications); /** for some reason we have dupes on first token sometimes. this helps remove them */ var lastStartSet = false; var lastStart = 0; // Trim to the query region classifications = classifications .map(function (c, i) { // Compensate each token for bom c.textSpan.start += offsetForBom; // completely outside the range on the left if ((c.textSpan.start + c.textSpan.length) <= lineStart) { return null; } // completely outside the range on the right if (c.textSpan.start > (lineStart + lineLength)) { return null; } // trim the left if (c.textSpan.start < lineStart) { c.textSpan.length = c.textSpan.start + c.textSpan.length - lineStart; c.textSpan.start = lineStart; } // trim the right if ((c.textSpan.start + c.textSpan.length) > (lineStart + lineLength)) { c.textSpan.length = (lineStart + lineLength) - (c.textSpan.start); } // dedupe...first token only if (!lastStartSet) { lastStartSet = true; lastStart = c.textSpan.start; } else { if (c.textSpan.start == lastStart) { return null; } } return c; }) .filter(function (c) { return !!c; }); // Add a string for easier debugging + startInLine for creating a 'map' of positions later on classifications.forEach(function (c) { c.startInLine = c.textSpan.start - lineStart; c.string = string.substr(c.startInLine, c.textSpan.length); }); return classifications; } exports.getClassificationsForLine = getClassificationsForLine; function getIndentationAtPosition(filePath, lineStart, options) { return languageService.getIndentationAtPosition(filePath, lineStart, options); } exports.getIndentationAtPosition = getIndentationAtPosition; function getFormattingEditsAfterKeystroke(filePath, position, key, options) { return languageService.getFormattingEditsAfterKeystroke(filePath, position, key, options); } exports.getFormattingEditsAfterKeystroke = getFormattingEditsAfterKeystroke; /** * ported from services.ts convertClassifications * encoding is [[start,lenght,type]......] * also added whitespace support */ function unencodeClassifications(classifications) { var dense = classifications.spans; var result = []; var expectedStart = 0; // used for whitespace for (var i = 0, n = dense.length; i < n; i += 3) { if (dense[i] > expectedStart) { result.push({ textSpan: ts.createTextSpan(expectedStart, dense[i] - expectedStart), classificationType: ts.ClassificationType.whiteSpace, classificationTypeName: ts.ClassificationTypeNames.whiteSpace, }); } result.push({ textSpan: ts.createTextSpan(dense[i], dense[i + 1]), classificationType: dense[i + 2], classificationTypeName: getClassificationTypeName(dense[i + 2]), }); expectedStart = dense[i] + dense[i + 1]; } return result; } /** brought in as it is */ var ClassificationType = ts.ClassificationType; var ClassificationTypeNames = ts.ClassificationTypeNames; function getClassificationTypeName(type) { switch (type) { case ClassificationType.comment: return ClassificationTypeNames.comment; case ClassificationType.identifier: return ClassificationTypeNames.identifier; case ClassificationType.keyword: return ClassificationTypeNames.keyword; case ClassificationType.numericLiteral: return ClassificationTypeNames.numericLiteral; case ClassificationType.operator: return ClassificationTypeNames.operator; case ClassificationType.stringLiteral: return ClassificationTypeNames.stringLiteral; case ClassificationType.whiteSpace: return ClassificationTypeNames.whiteSpace; case ClassificationType.text: return ClassificationTypeNames.text; case ClassificationType.punctuation: return ClassificationTypeNames.punctuation; case ClassificationType.className: return ClassificationTypeNames.className; case ClassificationType.enumName: return ClassificationTypeNames.enumName; case ClassificationType.interfaceName: return ClassificationTypeNames.interfaceName; case ClassificationType.moduleName: return ClassificationTypeNames.moduleName; case ClassificationType.typeParameterName: return ClassificationTypeNames.typeParameterName; case ClassificationType.typeAliasName: return ClassificationTypeNames.typeAliasName; case ClassificationType.parameterName: return ClassificationTypeNames.parameterName; case ClassificationType.docCommentTagName: return ClassificationTypeNames.docCommentTagName; case ClassificationType.jsxOpenTagName: return ClassificationTypeNames.jsxOpenTagName; case ClassificationType.jsxCloseTagName: return ClassificationTypeNames.jsxCloseTagName; case ClassificationType.jsxSelfClosingTagName: return ClassificationTypeNames.jsxSelfClosingTagName; } }