diff --git a/bin/lib.d.ts b/bin/lib.d.ts index 94d0fc4f062..944b10ac881 100644 --- a/bin/lib.d.ts +++ b/bin/lib.d.ts @@ -7355,6 +7355,8 @@ interface HTMLCanvasElement extends HTMLElement { * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas. * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl"); */ + getContext(contextId: "2d"): CanvasRenderingContext2D; + getContext(contextId: "experimental-webgl"): WebGLRenderingContext; getContext(contextId: string, ...args: any[]): CanvasRenderingContext2D | WebGLRenderingContext; /** * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing. diff --git a/bin/lib.dom.d.ts b/bin/lib.dom.d.ts index 68bd3147a05..422b4b8803c 100644 --- a/bin/lib.dom.d.ts +++ b/bin/lib.dom.d.ts @@ -6185,6 +6185,8 @@ interface HTMLCanvasElement extends HTMLElement { * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas. * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl"); */ + getContext(contextId: "2d"): CanvasRenderingContext2D; + getContext(contextId: "experimental-webgl"): WebGLRenderingContext; getContext(contextId: string, ...args: any[]): CanvasRenderingContext2D | WebGLRenderingContext; /** * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing. diff --git a/bin/lib.es6.d.ts b/bin/lib.es6.d.ts index c6b56dac2e8..8e7793c8dbd 100644 --- a/bin/lib.es6.d.ts +++ b/bin/lib.es6.d.ts @@ -8700,6 +8700,8 @@ interface HTMLCanvasElement extends HTMLElement { * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas. * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl"); */ + getContext(contextId: "2d"): CanvasRenderingContext2D; + getContext(contextId: "experimental-webgl"): WebGLRenderingContext; getContext(contextId: string, ...args: any[]): CanvasRenderingContext2D | WebGLRenderingContext; /** * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing. diff --git a/bin/tsserver.js b/bin/tsserver.js index c126089c1a4..1b935be1ece 100644 --- a/bin/tsserver.js +++ b/bin/tsserver.js @@ -31086,7 +31086,8 @@ var ts; ClassificationTypeNames.interfaceName = "interface name"; ClassificationTypeNames.moduleName = "module name"; ClassificationTypeNames.typeParameterName = "type parameter name"; - ClassificationTypeNames.typeAlias = "type alias name"; + ClassificationTypeNames.typeAliasName = "type alias name"; + ClassificationTypeNames.parameterName = "parameter name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; @@ -34330,35 +34331,43 @@ var ts; return ts.NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName, span) { + return convertClassifications(getEncodedSemanticClassifications(fileName, span)); + } + function getEncodedSemanticClassifications(fileName, span) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var typeChecker = program.getTypeChecker(); var result = []; processNode(sourceFile); - return result; + return { spans: result, endOfLineState: 0 }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifySymbol(symbol, meaningAtPosition) { var flags = symbol.getFlags(); if (flags & 32) { - return ClassificationTypeNames.className; + return 11; } else if (flags & 384) { - return ClassificationTypeNames.enumName; + return 12; } else if (flags & 524288) { - return ClassificationTypeNames.typeAlias; + return 16; } else if (meaningAtPosition & 2) { if (flags & 64) { - return ClassificationTypeNames.interfaceName; + return 13; } else if (flags & 262144) { - return ClassificationTypeNames.typeParameterName; + return 15; } } else if (flags & 1536) { if (meaningAtPosition & 4 || (meaningAtPosition & 1 && hasValueSideModule(symbol))) { - return ClassificationTypeNames.moduleName; + return 14; } } return undefined; @@ -34375,10 +34384,7 @@ var ts; if (symbol) { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { - result.push({ - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - classificationType: type - }); + pushClassification(node.getStart(), node.getWidth(), type); } } } @@ -34386,13 +34392,53 @@ var ts; } } } + function getClassificationTypeName(type) { + switch (type) { + case 1: return ClassificationTypeNames.comment; + case 2: return ClassificationTypeNames.identifier; + case 3: return ClassificationTypeNames.keyword; + case 4: return ClassificationTypeNames.numericLiteral; + case 5: return ClassificationTypeNames.operator; + case 6: return ClassificationTypeNames.stringLiteral; + case 8: return ClassificationTypeNames.whiteSpace; + case 9: return ClassificationTypeNames.text; + case 10: return ClassificationTypeNames.punctuation; + case 11: return ClassificationTypeNames.className; + case 12: return ClassificationTypeNames.enumName; + case 13: return ClassificationTypeNames.interfaceName; + case 14: return ClassificationTypeNames.moduleName; + case 15: return ClassificationTypeNames.typeParameterName; + case 16: return ClassificationTypeNames.typeAliasName; + case 17: return ClassificationTypeNames.parameterName; + } + } + function convertClassifications(classifications) { + ts.Debug.assert(classifications.spans.length % 3 === 0); + var dense = classifications.spans; + var result = []; + for (var i = 0, n = dense.length; i < n; i += 3) { + result.push({ + textSpan: ts.createTextSpan(dense[i], dense[i + 1]), + classificationType: getClassificationTypeName(dense[i + 2]) + }); + } + return result; + } function getSyntacticClassifications(fileName, span) { + return convertClassifications(getEncodedSyntacticClassifications(fileName, span)); + } + function getEncodedSyntacticClassifications(fileName, span) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var triviaScanner = ts.createScanner(2, false, sourceFile.text); var mergeConflictScanner = ts.createScanner(2, false, sourceFile.text); var result = []; processElement(sourceFile); - return result; + return { spans: result, endOfLineState: 0 }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifyLeadingTrivia(token) { var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false); if (tokenStart === token.pos) { @@ -34409,20 +34455,14 @@ var ts; return; } if (ts.isComment(kind)) { - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1); continue; } if (kind === 6) { var text = sourceFile.text; var ch = text.charCodeAt(start); if (ch === 60 || ch === 62) { - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1); continue; } ts.Debug.assert(ch === 61); @@ -34437,10 +34477,7 @@ var ts; break; } } - result.push({ - textSpan: ts.createTextSpanFromBounds(start, i), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, i - start, 1); mergeConflictScanner.setTextPos(i); while (mergeConflictScanner.getTextPos() < end) { classifyDisabledCodeToken(); @@ -34452,10 +34489,7 @@ var ts; var end = mergeConflictScanner.getTextPos(); var type = classifyTokenType(tokenKind); if (type) { - result.push({ - textSpan: ts.createTextSpanFromBounds(start, end), - classificationType: type - }); + pushClassification(start, end - start, type); } } function classifyToken(token) { @@ -34463,20 +34497,17 @@ var ts; if (token.getWidth() > 0) { var type = classifyTokenType(token.kind, token); if (type) { - result.push({ - textSpan: ts.createTextSpan(token.getStart(), token.getWidth()), - classificationType: type - }); + pushClassification(token.getStart(), token.getWidth(), type); } } } function classifyTokenType(tokenKind, token) { if (ts.isKeyword(tokenKind)) { - return ClassificationTypeNames.keyword; + return 3; } if (tokenKind === 24 || tokenKind === 25) { if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return ClassificationTypeNames.punctuation; + return 10; } } if (ts.isPunctuation(tokenKind)) { @@ -34485,61 +34516,66 @@ var ts; if (token.parent.kind === 199 || token.parent.kind === 133 || token.parent.kind === 130) { - return ClassificationTypeNames.operator; + return 5; } } if (token.parent.kind === 170 || token.parent.kind === 168 || token.parent.kind === 169 || token.parent.kind === 171) { - return ClassificationTypeNames.operator; + return 5; } } - return ClassificationTypeNames.punctuation; + return 10; } else if (tokenKind === 7) { - return ClassificationTypeNames.numericLiteral; + return 4; } else if (tokenKind === 8) { - return ClassificationTypeNames.stringLiteral; + return 6; } else if (tokenKind === 9) { - return ClassificationTypeNames.stringLiteral; + return 6; } else if (ts.isTemplateLiteralKind(tokenKind)) { - return ClassificationTypeNames.stringLiteral; + return 6; } else if (tokenKind === 65) { if (token) { switch (token.parent.kind) { case 202: if (token.parent.name === token) { - return ClassificationTypeNames.className; + return 11; } return; case 129: if (token.parent.name === token) { - return ClassificationTypeNames.typeParameterName; + return 15; } return; case 203: if (token.parent.name === token) { - return ClassificationTypeNames.interfaceName; + return 13; } return; case 205: if (token.parent.name === token) { - return ClassificationTypeNames.enumName; + return 12; } return; case 206: if (token.parent.name === token) { - return ClassificationTypeNames.moduleName; + return 14; + } + return; + case 130: + if (token.parent.name === token) { + return 17; } return; } } - return ClassificationTypeNames.text; + return 9; } } function processElement(element) { @@ -34748,6 +34784,8 @@ var ts; getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics, getSyntacticClassifications: getSyntacticClassifications, getSemanticClassifications: getSemanticClassifications, + getEncodedSyntacticClassifications: getEncodedSyntacticClassifications, + getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, getSignatureHelpItems: getSignatureHelpItems, @@ -34839,7 +34877,55 @@ var ts; } return true; } + function convertClassifications(classifications, text) { + var entries = []; + var dense = classifications.spans; + var lastEnd = 0; + for (var i = 0, n = dense.length; i < n; i += 3) { + var start = dense[i]; + var length_1 = dense[i + 1]; + var type = dense[i + 2]; + if (lastEnd >= 0) { + var whitespaceLength_1 = start - lastEnd; + if (whitespaceLength_1 > 0) { + entries.push({ length: whitespaceLength_1, classification: TokenClass.Whitespace }); + } + } + entries.push({ length: length_1, classification: convertClassification(type) }); + lastEnd = start + length_1; + } + var whitespaceLength = text.length - lastEnd; + if (whitespaceLength > 0) { + entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); + } + return { entries: entries, finalLexState: classifications.endOfLineState }; + } + function convertClassification(type) { + switch (type) { + case 1: return TokenClass.Comment; + case 3: return TokenClass.Keyword; + case 4: return TokenClass.NumberLiteral; + case 5: return TokenClass.Operator; + case 6: return TokenClass.StringLiteral; + case 8: return TokenClass.Whitespace; + case 10: return TokenClass.Punctuation; + case 2: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 9: + case 17: + default: + return TokenClass.Identifier; + } + } function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + } + function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { var offset = 0; var token = 0; var lastNonTriviaToken = 0; @@ -34872,8 +34958,8 @@ var ts; } scanner.setText(text); var result = { - finalLexState: 0, - entries: [] + endOfLineState: 0, + spans: [] }; var angleBracketStack = 0; do { @@ -34940,7 +35026,7 @@ var ts; function processToken() { var start = scanner.getTokenPos(); var end = scanner.getTextPos(); - addResult(end - start, classFromKind(token)); + addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === 8) { var tokenText = scanner.getTokenText(); @@ -34952,7 +35038,7 @@ var ts; } if (numBackslashes & 1) { var quoteChar = tokenText.charCodeAt(0); - result.finalLexState = quoteChar === 34 + result.endOfLineState = quoteChar === 34 ? 3 : 2; } @@ -34960,16 +35046,16 @@ var ts; } else if (token === 3) { if (scanner.isUnterminated()) { - result.finalLexState = 1; + result.endOfLineState = 1; } } else if (ts.isTemplateLiteralKind(token)) { if (scanner.isUnterminated()) { if (token === 13) { - result.finalLexState = 5; + result.endOfLineState = 5; } else if (token === 10) { - result.finalLexState = 4; + result.endOfLineState = 4; } else { ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); @@ -34977,16 +35063,24 @@ var ts; } } else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11) { - result.finalLexState = 6; + result.endOfLineState = 6; } } } - function addResult(length, classification) { + function addResult(start, end, classification) { + if (classification === 8) { + return; + } + if (start === 0 && offset > 0) { + start += offset; + } + start -= offset; + end -= offset; + var length = end - start; if (length > 0) { - if (result.entries.length === 0) { - length -= offset; - } - result.entries.push({ length: length, classification: classification }); + result.spans.push(start); + result.spans.push(length); + result.spans.push(classification); } } } @@ -35051,37 +35145,40 @@ var ts; } function classFromKind(token) { if (isKeyword(token)) { - return TokenClass.Keyword; + return 3; } else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return TokenClass.Operator; + return 5; } else if (token >= 14 && token <= 64) { - return TokenClass.Punctuation; + return 10; } switch (token) { case 7: - return TokenClass.NumberLiteral; + return 4; case 8: - return TokenClass.StringLiteral; + return 6; case 9: - return TokenClass.RegExpLiteral; + return 7; case 6: case 3: case 2: - return TokenClass.Comment; + return 1; case 5: case 4: - return TokenClass.Whitespace; + return 8; case 65: default: if (ts.isTemplateLiteralKind(token)) { - return TokenClass.StringLiteral; + return 6; } - return TokenClass.Identifier; + return 2; } } - return { getClassificationsForLine: getClassificationsForLine }; + return { + getClassificationsForLine: getClassificationsForLine, + getEncodedLexicalClassifications: getEncodedLexicalClassifications + }; } ts.createClassifier = createClassifier; function getDefaultLibFilePath(options) { diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index a053fa52ce1..3ec7b1230ad 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -1361,8 +1361,16 @@ declare module "typescript" { getSyntacticDiagnostics(fileName: string): Diagnostic[]; getSemanticDiagnostics(fileName: string): Diagnostic[]; getCompilerOptionsDiagnostics(): Diagnostic[]; + /** + * @deprecated Use getEncodedSyntacticClassifications instead. + */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + /** + * @deprecated Use getEncodedSemanticClassifications instead. + */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; + getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; @@ -1391,6 +1399,10 @@ declare module "typescript" { getSourceFile(fileName: string): SourceFile; dispose(): void; } + interface Classifications { + spans: number[]; + endOfLineState: EndOfLineState; + } interface ClassifiedSpan { textSpan: TextSpan; classificationType: string; @@ -1602,7 +1614,7 @@ declare module "typescript" { text: string; } const enum EndOfLineState { - Start = 0, + None = 0, InMultiLineCommentTrivia = 1, InSingleQuoteStringLiteral = 2, InDoubleQuoteStringLiteral = 3, @@ -1648,8 +1660,10 @@ declare module "typescript" { * classifications which may be incorrectly categorized will be given * back as Identifiers in order to allow the syntactic classifier to * subsume the classification. + * @deprecated Use getLexicalClassifications instead. */ getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; + getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } /** * The document registry represents a store of SourceFile objects that can be shared between @@ -1760,7 +1774,27 @@ declare module "typescript" { static interfaceName: string; static moduleName: string; static typeParameterName: string; - static typeAlias: string; + static typeAliasName: string; + static parameterName: string; + } + const enum ClassificationType { + comment = 1, + identifier = 2, + keyword = 3, + numericLiteral = 4, + operator = 5, + stringLiteral = 6, + regularExpressionLiteral = 7, + whiteSpace = 8, + text = 9, + punctuation = 10, + className = 11, + enumName = 12, + interfaceName = 13, + moduleName = 14, + typeParameterName = 15, + typeAliasName = 16, + parameterName = 17, } interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; diff --git a/bin/typescript.js b/bin/typescript.js index 1fce4bff0b0..ed6570707e6 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -36218,7 +36218,7 @@ var ts; })(ts.OutputFileType || (ts.OutputFileType = {})); var OutputFileType = ts.OutputFileType; (function (EndOfLineState) { - EndOfLineState[EndOfLineState["Start"] = 0] = "Start"; + EndOfLineState[EndOfLineState["None"] = 0] = "None"; EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia"; EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral"; EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral"; @@ -36320,10 +36320,31 @@ var ts; ClassificationTypeNames.interfaceName = "interface name"; ClassificationTypeNames.moduleName = "module name"; ClassificationTypeNames.typeParameterName = "type parameter name"; - ClassificationTypeNames.typeAlias = "type alias name"; + ClassificationTypeNames.typeAliasName = "type alias name"; + ClassificationTypeNames.parameterName = "parameter name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; + (function (ClassificationType) { + ClassificationType[ClassificationType["comment"] = 1] = "comment"; + ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; + ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; + ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; + ClassificationType[ClassificationType["operator"] = 5] = "operator"; + ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; + ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; + ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; + ClassificationType[ClassificationType["text"] = 9] = "text"; + ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; + ClassificationType[ClassificationType["className"] = 11] = "className"; + ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; + ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; + ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; + ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; + ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; + ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; + })(ts.ClassificationType || (ts.ClassificationType = {})); + var ClassificationType = ts.ClassificationType; function displayPartsToString(displayParts) { if (displayParts) { return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); @@ -40027,29 +40048,37 @@ var ts; return ts.NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName, span) { + return convertClassifications(getEncodedSemanticClassifications(fileName, span)); + } + function getEncodedSemanticClassifications(fileName, span) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var typeChecker = program.getTypeChecker(); var result = []; processNode(sourceFile); - return result; + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifySymbol(symbol, meaningAtPosition) { var flags = symbol.getFlags(); if (flags & 32 /* Class */) { - return ClassificationTypeNames.className; + return 11 /* className */; } else if (flags & 384 /* Enum */) { - return ClassificationTypeNames.enumName; + return 12 /* enumName */; } else if (flags & 524288 /* TypeAlias */) { - return ClassificationTypeNames.typeAlias; + return 16 /* typeAliasName */; } else if (meaningAtPosition & 2 /* Type */) { if (flags & 64 /* Interface */) { - return ClassificationTypeNames.interfaceName; + return 13 /* interfaceName */; } else if (flags & 262144 /* TypeParameter */) { - return ClassificationTypeNames.typeParameterName; + return 15 /* typeParameterName */; } } else if (flags & 1536 /* Module */) { @@ -40058,7 +40087,7 @@ var ts; // - There exists a module declaration which actually impacts the value side. if (meaningAtPosition & 4 /* Namespace */ || (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { - return ClassificationTypeNames.moduleName; + return 14 /* moduleName */; } } return undefined; @@ -40079,10 +40108,7 @@ var ts; if (symbol) { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { - result.push({ - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - classificationType: type - }); + pushClassification(node.getStart(), node.getWidth(), type); } } } @@ -40090,7 +40116,42 @@ var ts; } } } + function getClassificationTypeName(type) { + switch (type) { + case 1 /* comment */: return ClassificationTypeNames.comment; + case 2 /* identifier */: return ClassificationTypeNames.identifier; + case 3 /* keyword */: return ClassificationTypeNames.keyword; + case 4 /* numericLiteral */: return ClassificationTypeNames.numericLiteral; + case 5 /* operator */: return ClassificationTypeNames.operator; + case 6 /* stringLiteral */: return ClassificationTypeNames.stringLiteral; + case 8 /* whiteSpace */: return ClassificationTypeNames.whiteSpace; + case 9 /* text */: return ClassificationTypeNames.text; + case 10 /* punctuation */: return ClassificationTypeNames.punctuation; + case 11 /* className */: return ClassificationTypeNames.className; + case 12 /* enumName */: return ClassificationTypeNames.enumName; + case 13 /* interfaceName */: return ClassificationTypeNames.interfaceName; + case 14 /* moduleName */: return ClassificationTypeNames.moduleName; + case 15 /* typeParameterName */: return ClassificationTypeNames.typeParameterName; + case 16 /* typeAliasName */: return ClassificationTypeNames.typeAliasName; + case 17 /* parameterName */: return ClassificationTypeNames.parameterName; + } + } + function convertClassifications(classifications) { + ts.Debug.assert(classifications.spans.length % 3 === 0); + var dense = classifications.spans; + var result = []; + for (var i = 0, n = dense.length; i < n; i += 3) { + result.push({ + textSpan: ts.createTextSpan(dense[i], dense[i + 1]), + classificationType: getClassificationTypeName(dense[i + 2]) + }); + } + return result; + } function getSyntacticClassifications(fileName, span) { + return convertClassifications(getEncodedSyntacticClassifications(fileName, span)); + } + function getEncodedSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Make a scanner we can get trivia from. @@ -40098,7 +40159,12 @@ var ts; var mergeConflictScanner = ts.createScanner(2 /* Latest */, false, sourceFile.text); var result = []; processElement(sourceFile); - return result; + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifyLeadingTrivia(token) { var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false); if (tokenStart === token.pos) { @@ -40117,10 +40183,7 @@ var ts; } if (ts.isComment(kind)) { // Simple comment. Just add as is. - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1 /* comment */); continue; } if (kind === 6 /* ConflictMarkerTrivia */) { @@ -40129,10 +40192,7 @@ var ts; // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1 /* comment */); continue; } // for the ======== add a comment for the first line, and then lex all @@ -40151,10 +40211,7 @@ var ts; break; } } - result.push({ - textSpan: ts.createTextSpanFromBounds(start, i), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, i - start, 1 /* comment */); mergeConflictScanner.setTextPos(i); while (mergeConflictScanner.getTextPos() < end) { classifyDisabledCodeToken(); @@ -40166,10 +40223,7 @@ var ts; var end = mergeConflictScanner.getTextPos(); var type = classifyTokenType(tokenKind); if (type) { - result.push({ - textSpan: ts.createTextSpanFromBounds(start, end), - classificationType: type - }); + pushClassification(start, end - start, type); } } function classifyToken(token) { @@ -40177,10 +40231,7 @@ var ts; if (token.getWidth() > 0) { var type = classifyTokenType(token.kind, token); if (type) { - result.push({ - textSpan: ts.createTextSpan(token.getStart(), token.getWidth()), - classificationType: type - }); + pushClassification(token.getStart(), token.getWidth(), type); } } } @@ -40189,7 +40240,7 @@ var ts; // classify based on that instead. function classifyTokenType(tokenKind, token) { if (ts.isKeyword(tokenKind)) { - return ClassificationTypeNames.keyword; + return 3 /* keyword */; } // Special case < and > If they appear in a generic context they are punctuation, // not operators. @@ -40197,7 +40248,7 @@ var ts; // If the node owning the token has a type argument list or type parameter list, then // we can effectively assume that a '<' and '>' belong to those lists. if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return ClassificationTypeNames.punctuation; + return 10 /* punctuation */; } } if (ts.isPunctuation(tokenKind)) { @@ -40207,63 +40258,68 @@ var ts; if (token.parent.kind === 199 /* VariableDeclaration */ || token.parent.kind === 133 /* PropertyDeclaration */ || token.parent.kind === 130 /* Parameter */) { - return ClassificationTypeNames.operator; + return 5 /* operator */; } } if (token.parent.kind === 170 /* BinaryExpression */ || token.parent.kind === 168 /* PrefixUnaryExpression */ || token.parent.kind === 169 /* PostfixUnaryExpression */ || token.parent.kind === 171 /* ConditionalExpression */) { - return ClassificationTypeNames.operator; + return 5 /* operator */; } } - return ClassificationTypeNames.punctuation; + return 10 /* punctuation */; } else if (tokenKind === 7 /* NumericLiteral */) { - return ClassificationTypeNames.numericLiteral; + return 4 /* numericLiteral */; } else if (tokenKind === 8 /* StringLiteral */) { - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (tokenKind === 9 /* RegularExpressionLiteral */) { // TODO: we should get another classification type for these literals. - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (ts.isTemplateLiteralKind(tokenKind)) { // TODO (drosen): we should *also* get another classification type for these literals. - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (tokenKind === 65 /* Identifier */) { if (token) { switch (token.parent.kind) { case 202 /* ClassDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.className; + return 11 /* className */; } return; case 129 /* TypeParameter */: if (token.parent.name === token) { - return ClassificationTypeNames.typeParameterName; + return 15 /* typeParameterName */; } return; case 203 /* InterfaceDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.interfaceName; + return 13 /* interfaceName */; } return; case 205 /* EnumDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.enumName; + return 12 /* enumName */; } return; case 206 /* ModuleDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.moduleName; + return 14 /* moduleName */; + } + return; + case 130 /* Parameter */: + if (token.parent.name === token) { + return 17 /* parameterName */; } return; } } - return ClassificationTypeNames.text; + return 9 /* text */; } } function processElement(element) { @@ -40543,6 +40599,8 @@ var ts; getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics, getSyntacticClassifications: getSyntacticClassifications, getSemanticClassifications: getSemanticClassifications, + getEncodedSyntacticClassifications: getEncodedSyntacticClassifications, + getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, getSignatureHelpItems: getSignatureHelpItems, @@ -40671,9 +40729,58 @@ var ts; // if there are more cases we want the classifier to be better at. return true; } + function convertClassifications(classifications, text) { + var entries = []; + var dense = classifications.spans; + var lastEnd = 0; + for (var i = 0, n = dense.length; i < n; i += 3) { + var start = dense[i]; + var length_1 = dense[i + 1]; + var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. + if (lastEnd >= 0) { + var whitespaceLength_1 = start - lastEnd; + if (whitespaceLength_1 > 0) { + entries.push({ length: whitespaceLength_1, classification: TokenClass.Whitespace }); + } + } + entries.push({ length: length_1, classification: convertClassification(type) }); + lastEnd = start + length_1; + } + var whitespaceLength = text.length - lastEnd; + if (whitespaceLength > 0) { + entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); + } + return { entries: entries, finalLexState: classifications.endOfLineState }; + } + function convertClassification(type) { + switch (type) { + case 1 /* comment */: return TokenClass.Comment; + case 3 /* keyword */: return TokenClass.Keyword; + case 4 /* numericLiteral */: return TokenClass.NumberLiteral; + case 5 /* operator */: return TokenClass.Operator; + case 6 /* stringLiteral */: return TokenClass.StringLiteral; + case 8 /* whiteSpace */: return TokenClass.Whitespace; + case 10 /* punctuation */: return TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: + default: + return TokenClass.Identifier; + } + } + function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + } // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), // we will be more conservative in order to avoid conflicting with the syntactic classifier. - function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { var offset = 0; var token = 0 /* Unknown */; var lastNonTriviaToken = 0 /* Unknown */; @@ -40713,8 +40820,8 @@ var ts; } scanner.setText(text); var result = { - finalLexState: 0 /* Start */, - entries: [] + endOfLineState: 0 /* None */, + spans: [] }; // We can run into an unfortunate interaction between the lexical and syntactic classifier // when the user is typing something generic. Consider the case where the user types: @@ -40816,7 +40923,7 @@ var ts; function processToken() { var start = scanner.getTokenPos(); var end = scanner.getTextPos(); - addResult(end - start, classFromKind(token)); + addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === 8 /* StringLiteral */) { // Check to see if we finished up on a multiline string literal. @@ -40830,7 +40937,7 @@ var ts; // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { var quoteChar = tokenText.charCodeAt(0); - result.finalLexState = quoteChar === 34 /* doubleQuote */ + result.endOfLineState = quoteChar === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */; } @@ -40839,16 +40946,16 @@ var ts; else if (token === 3 /* MultiLineCommentTrivia */) { // Check to see if the multiline comment was unclosed. if (scanner.isUnterminated()) { - result.finalLexState = 1 /* InMultiLineCommentTrivia */; + result.endOfLineState = 1 /* InMultiLineCommentTrivia */; } } else if (ts.isTemplateLiteralKind(token)) { if (scanner.isUnterminated()) { if (token === 13 /* TemplateTail */) { - result.finalLexState = 5 /* InTemplateMiddleOrTail */; + result.endOfLineState = 5 /* InTemplateMiddleOrTail */; } else if (token === 10 /* NoSubstitutionTemplateLiteral */) { - result.finalLexState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; + result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; } else { ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); @@ -40856,18 +40963,30 @@ var ts; } } else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11 /* TemplateHead */) { - result.finalLexState = 6 /* InTemplateSubstitutionPosition */; + result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; } } } - function addResult(length, classification) { + function addResult(start, end, classification) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. + return; + } + if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended + // text. We should consider the start of this token to be at the start of + // the original text. + start += offset; + } + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. + start -= offset; + end -= offset; + var length = end - start; if (length > 0) { - // If this is the first classification we're adding to the list, then remove any - // offset we have if we were continuing a construct from the previous line. - if (result.entries.length === 0) { - length -= offset; - } - result.entries.push({ length: length, classification: classification }); + result.spans.push(start); + result.spans.push(length); + result.spans.push(classification); } } } @@ -40932,37 +41051,40 @@ var ts; } function classFromKind(token) { if (isKeyword(token)) { - return TokenClass.Keyword; + return 3 /* keyword */; } else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return TokenClass.Operator; + return 5 /* operator */; } else if (token >= 14 /* FirstPunctuation */ && token <= 64 /* LastPunctuation */) { - return TokenClass.Punctuation; + return 10 /* punctuation */; } switch (token) { case 7 /* NumericLiteral */: - return TokenClass.NumberLiteral; + return 4 /* numericLiteral */; case 8 /* StringLiteral */: - return TokenClass.StringLiteral; + return 6 /* stringLiteral */; case 9 /* RegularExpressionLiteral */: - return TokenClass.RegExpLiteral; + return 7 /* regularExpressionLiteral */; case 6 /* ConflictMarkerTrivia */: case 3 /* MultiLineCommentTrivia */: case 2 /* SingleLineCommentTrivia */: - return TokenClass.Comment; + return 1 /* comment */; case 5 /* WhitespaceTrivia */: case 4 /* NewLineTrivia */: - return TokenClass.Whitespace; + return 8 /* whiteSpace */; case 65 /* Identifier */: default: if (ts.isTemplateLiteralKind(token)) { - return TokenClass.StringLiteral; + return 6 /* stringLiteral */; } - return TokenClass.Identifier; + return 2 /* identifier */; } } - return { getClassificationsForLine: getClassificationsForLine }; + return { + getClassificationsForLine: getClassificationsForLine, + getEncodedLexicalClassifications: getEncodedLexicalClassifications + }; } ts.createClassifier = createClassifier; /** @@ -41461,7 +41583,9 @@ var debugObjectHost = this; var ts; (function (ts) { function logInternalError(logger, err) { - logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); + if (logger) { + logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); + } } var ScriptSnapshotShimAdapter = (function () { function ScriptSnapshotShimAdapter(scriptSnapshotShim) { @@ -41565,24 +41689,28 @@ var ts; return CoreServicesShimHostAdapter; })(); ts.CoreServicesShimHostAdapter = CoreServicesShimHostAdapter; - function simpleForwardCall(logger, actionDescription, action) { - logger.log(actionDescription); - var start = Date.now(); + function simpleForwardCall(logger, actionDescription, action, noPerfLogging) { + if (!noPerfLogging) { + logger.log(actionDescription); + var start = Date.now(); + } var result = action(); - var end = Date.now(); - logger.log(actionDescription + " completed in " + (end - start) + " msec"); - if (typeof (result) === "string") { - var str = result; - if (str.length > 128) { - str = str.substring(0, 128) + "..."; + if (!noPerfLogging) { + var end = Date.now(); + logger.log(actionDescription + " completed in " + (end - start) + " msec"); + if (typeof (result) === "string") { + var str = result; + if (str.length > 128) { + str = str.substring(0, 128) + "..."; + } + logger.log(" result.length=" + str.length + ", result='" + JSON.stringify(str) + "'"); } - logger.log(" result.length=" + str.length + ", result='" + JSON.stringify(str) + "'"); } return result; } - function forwardJSONCall(logger, actionDescription, action) { + function forwardJSONCall(logger, actionDescription, action, noPerfLogging) { try { - var result = simpleForwardCall(logger, actionDescription, action); + var result = simpleForwardCall(logger, actionDescription, action, noPerfLogging); return JSON.stringify({ result: result }); } catch (err) { @@ -41627,7 +41755,7 @@ var ts; this.logger = this.host; } LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) { - return forwardJSONCall(this.logger, actionDescription, action); + return forwardJSONCall(this.logger, actionDescription, action, false); }; /// DISPOSE /** @@ -41680,6 +41808,22 @@ var ts; return classifications; }); }; + LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) { + var _this = this; + return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); + }); + }; + LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) { + var _this = this; + return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); + }); + }; LanguageServiceShimObject.prototype.getNewLine = function () { return this.host.getNewLine ? this.host.getNewLine() : "\r\n"; }; @@ -41899,12 +42043,21 @@ var ts; }; return LanguageServiceShimObject; })(ShimBase); + function convertClassifications(classifications) { + return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; + } var ClassifierShimObject = (function (_super) { __extends(ClassifierShimObject, _super); - function ClassifierShimObject(factory) { + function ClassifierShimObject(factory, logger) { _super.call(this, factory); + this.logger = logger; this.classifier = ts.createClassifier(); } + ClassifierShimObject.prototype.getEncodedLexicalClassifications = function (text, lexState, syntacticClassifierAbsent) { + var _this = this; + return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, + /*noPerfLogging:*/ true); + }; /// COLORIZATION ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) { var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); @@ -41927,7 +42080,7 @@ var ts; this.host = host; } CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) { - return forwardJSONCall(this.logger, actionDescription, action); + return forwardJSONCall(this.logger, actionDescription, action, false); }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { @@ -42005,7 +42158,7 @@ var ts; }; TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) { try { - return new ClassifierShimObject(this); + return new ClassifierShimObject(this, logger); } catch (err) { logInternalError(logger, err); diff --git a/bin/typescriptServices.d.ts b/bin/typescriptServices.d.ts index fe07f9ea4fd..9b5072a058a 100644 --- a/bin/typescriptServices.d.ts +++ b/bin/typescriptServices.d.ts @@ -1361,8 +1361,16 @@ declare module ts { getSyntacticDiagnostics(fileName: string): Diagnostic[]; getSemanticDiagnostics(fileName: string): Diagnostic[]; getCompilerOptionsDiagnostics(): Diagnostic[]; + /** + * @deprecated Use getEncodedSyntacticClassifications instead. + */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + /** + * @deprecated Use getEncodedSemanticClassifications instead. + */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; + getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; @@ -1391,6 +1399,10 @@ declare module ts { getSourceFile(fileName: string): SourceFile; dispose(): void; } + interface Classifications { + spans: number[]; + endOfLineState: EndOfLineState; + } interface ClassifiedSpan { textSpan: TextSpan; classificationType: string; @@ -1602,7 +1614,7 @@ declare module ts { text: string; } const enum EndOfLineState { - Start = 0, + None = 0, InMultiLineCommentTrivia = 1, InSingleQuoteStringLiteral = 2, InDoubleQuoteStringLiteral = 3, @@ -1648,8 +1660,10 @@ declare module ts { * classifications which may be incorrectly categorized will be given * back as Identifiers in order to allow the syntactic classifier to * subsume the classification. + * @deprecated Use getLexicalClassifications instead. */ getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; + getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } /** * The document registry represents a store of SourceFile objects that can be shared between @@ -1760,7 +1774,27 @@ declare module ts { static interfaceName: string; static moduleName: string; static typeParameterName: string; - static typeAlias: string; + static typeAliasName: string; + static parameterName: string; + } + const enum ClassificationType { + comment = 1, + identifier = 2, + keyword = 3, + numericLiteral = 4, + operator = 5, + stringLiteral = 6, + regularExpressionLiteral = 7, + whiteSpace = 8, + text = 9, + punctuation = 10, + className = 11, + enumName = 12, + interfaceName = 13, + moduleName = 14, + typeParameterName = 15, + typeAliasName = 16, + parameterName = 17, } interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; diff --git a/bin/typescriptServices.js b/bin/typescriptServices.js index 1fce4bff0b0..ed6570707e6 100644 --- a/bin/typescriptServices.js +++ b/bin/typescriptServices.js @@ -36218,7 +36218,7 @@ var ts; })(ts.OutputFileType || (ts.OutputFileType = {})); var OutputFileType = ts.OutputFileType; (function (EndOfLineState) { - EndOfLineState[EndOfLineState["Start"] = 0] = "Start"; + EndOfLineState[EndOfLineState["None"] = 0] = "None"; EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia"; EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral"; EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral"; @@ -36320,10 +36320,31 @@ var ts; ClassificationTypeNames.interfaceName = "interface name"; ClassificationTypeNames.moduleName = "module name"; ClassificationTypeNames.typeParameterName = "type parameter name"; - ClassificationTypeNames.typeAlias = "type alias name"; + ClassificationTypeNames.typeAliasName = "type alias name"; + ClassificationTypeNames.parameterName = "parameter name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; + (function (ClassificationType) { + ClassificationType[ClassificationType["comment"] = 1] = "comment"; + ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; + ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; + ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; + ClassificationType[ClassificationType["operator"] = 5] = "operator"; + ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; + ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; + ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; + ClassificationType[ClassificationType["text"] = 9] = "text"; + ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; + ClassificationType[ClassificationType["className"] = 11] = "className"; + ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; + ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; + ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; + ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; + ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; + ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; + })(ts.ClassificationType || (ts.ClassificationType = {})); + var ClassificationType = ts.ClassificationType; function displayPartsToString(displayParts) { if (displayParts) { return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); @@ -40027,29 +40048,37 @@ var ts; return ts.NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName, span) { + return convertClassifications(getEncodedSemanticClassifications(fileName, span)); + } + function getEncodedSemanticClassifications(fileName, span) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var typeChecker = program.getTypeChecker(); var result = []; processNode(sourceFile); - return result; + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifySymbol(symbol, meaningAtPosition) { var flags = symbol.getFlags(); if (flags & 32 /* Class */) { - return ClassificationTypeNames.className; + return 11 /* className */; } else if (flags & 384 /* Enum */) { - return ClassificationTypeNames.enumName; + return 12 /* enumName */; } else if (flags & 524288 /* TypeAlias */) { - return ClassificationTypeNames.typeAlias; + return 16 /* typeAliasName */; } else if (meaningAtPosition & 2 /* Type */) { if (flags & 64 /* Interface */) { - return ClassificationTypeNames.interfaceName; + return 13 /* interfaceName */; } else if (flags & 262144 /* TypeParameter */) { - return ClassificationTypeNames.typeParameterName; + return 15 /* typeParameterName */; } } else if (flags & 1536 /* Module */) { @@ -40058,7 +40087,7 @@ var ts; // - There exists a module declaration which actually impacts the value side. if (meaningAtPosition & 4 /* Namespace */ || (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { - return ClassificationTypeNames.moduleName; + return 14 /* moduleName */; } } return undefined; @@ -40079,10 +40108,7 @@ var ts; if (symbol) { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { - result.push({ - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - classificationType: type - }); + pushClassification(node.getStart(), node.getWidth(), type); } } } @@ -40090,7 +40116,42 @@ var ts; } } } + function getClassificationTypeName(type) { + switch (type) { + case 1 /* comment */: return ClassificationTypeNames.comment; + case 2 /* identifier */: return ClassificationTypeNames.identifier; + case 3 /* keyword */: return ClassificationTypeNames.keyword; + case 4 /* numericLiteral */: return ClassificationTypeNames.numericLiteral; + case 5 /* operator */: return ClassificationTypeNames.operator; + case 6 /* stringLiteral */: return ClassificationTypeNames.stringLiteral; + case 8 /* whiteSpace */: return ClassificationTypeNames.whiteSpace; + case 9 /* text */: return ClassificationTypeNames.text; + case 10 /* punctuation */: return ClassificationTypeNames.punctuation; + case 11 /* className */: return ClassificationTypeNames.className; + case 12 /* enumName */: return ClassificationTypeNames.enumName; + case 13 /* interfaceName */: return ClassificationTypeNames.interfaceName; + case 14 /* moduleName */: return ClassificationTypeNames.moduleName; + case 15 /* typeParameterName */: return ClassificationTypeNames.typeParameterName; + case 16 /* typeAliasName */: return ClassificationTypeNames.typeAliasName; + case 17 /* parameterName */: return ClassificationTypeNames.parameterName; + } + } + function convertClassifications(classifications) { + ts.Debug.assert(classifications.spans.length % 3 === 0); + var dense = classifications.spans; + var result = []; + for (var i = 0, n = dense.length; i < n; i += 3) { + result.push({ + textSpan: ts.createTextSpan(dense[i], dense[i + 1]), + classificationType: getClassificationTypeName(dense[i + 2]) + }); + } + return result; + } function getSyntacticClassifications(fileName, span) { + return convertClassifications(getEncodedSyntacticClassifications(fileName, span)); + } + function getEncodedSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Make a scanner we can get trivia from. @@ -40098,7 +40159,12 @@ var ts; var mergeConflictScanner = ts.createScanner(2 /* Latest */, false, sourceFile.text); var result = []; processElement(sourceFile); - return result; + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } function classifyLeadingTrivia(token) { var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false); if (tokenStart === token.pos) { @@ -40117,10 +40183,7 @@ var ts; } if (ts.isComment(kind)) { // Simple comment. Just add as is. - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1 /* comment */); continue; } if (kind === 6 /* ConflictMarkerTrivia */) { @@ -40129,10 +40192,7 @@ var ts; // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { - result.push({ - textSpan: ts.createTextSpan(start, width), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, width, 1 /* comment */); continue; } // for the ======== add a comment for the first line, and then lex all @@ -40151,10 +40211,7 @@ var ts; break; } } - result.push({ - textSpan: ts.createTextSpanFromBounds(start, i), - classificationType: ClassificationTypeNames.comment - }); + pushClassification(start, i - start, 1 /* comment */); mergeConflictScanner.setTextPos(i); while (mergeConflictScanner.getTextPos() < end) { classifyDisabledCodeToken(); @@ -40166,10 +40223,7 @@ var ts; var end = mergeConflictScanner.getTextPos(); var type = classifyTokenType(tokenKind); if (type) { - result.push({ - textSpan: ts.createTextSpanFromBounds(start, end), - classificationType: type - }); + pushClassification(start, end - start, type); } } function classifyToken(token) { @@ -40177,10 +40231,7 @@ var ts; if (token.getWidth() > 0) { var type = classifyTokenType(token.kind, token); if (type) { - result.push({ - textSpan: ts.createTextSpan(token.getStart(), token.getWidth()), - classificationType: type - }); + pushClassification(token.getStart(), token.getWidth(), type); } } } @@ -40189,7 +40240,7 @@ var ts; // classify based on that instead. function classifyTokenType(tokenKind, token) { if (ts.isKeyword(tokenKind)) { - return ClassificationTypeNames.keyword; + return 3 /* keyword */; } // Special case < and > If they appear in a generic context they are punctuation, // not operators. @@ -40197,7 +40248,7 @@ var ts; // If the node owning the token has a type argument list or type parameter list, then // we can effectively assume that a '<' and '>' belong to those lists. if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return ClassificationTypeNames.punctuation; + return 10 /* punctuation */; } } if (ts.isPunctuation(tokenKind)) { @@ -40207,63 +40258,68 @@ var ts; if (token.parent.kind === 199 /* VariableDeclaration */ || token.parent.kind === 133 /* PropertyDeclaration */ || token.parent.kind === 130 /* Parameter */) { - return ClassificationTypeNames.operator; + return 5 /* operator */; } } if (token.parent.kind === 170 /* BinaryExpression */ || token.parent.kind === 168 /* PrefixUnaryExpression */ || token.parent.kind === 169 /* PostfixUnaryExpression */ || token.parent.kind === 171 /* ConditionalExpression */) { - return ClassificationTypeNames.operator; + return 5 /* operator */; } } - return ClassificationTypeNames.punctuation; + return 10 /* punctuation */; } else if (tokenKind === 7 /* NumericLiteral */) { - return ClassificationTypeNames.numericLiteral; + return 4 /* numericLiteral */; } else if (tokenKind === 8 /* StringLiteral */) { - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (tokenKind === 9 /* RegularExpressionLiteral */) { // TODO: we should get another classification type for these literals. - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (ts.isTemplateLiteralKind(tokenKind)) { // TODO (drosen): we should *also* get another classification type for these literals. - return ClassificationTypeNames.stringLiteral; + return 6 /* stringLiteral */; } else if (tokenKind === 65 /* Identifier */) { if (token) { switch (token.parent.kind) { case 202 /* ClassDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.className; + return 11 /* className */; } return; case 129 /* TypeParameter */: if (token.parent.name === token) { - return ClassificationTypeNames.typeParameterName; + return 15 /* typeParameterName */; } return; case 203 /* InterfaceDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.interfaceName; + return 13 /* interfaceName */; } return; case 205 /* EnumDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.enumName; + return 12 /* enumName */; } return; case 206 /* ModuleDeclaration */: if (token.parent.name === token) { - return ClassificationTypeNames.moduleName; + return 14 /* moduleName */; + } + return; + case 130 /* Parameter */: + if (token.parent.name === token) { + return 17 /* parameterName */; } return; } } - return ClassificationTypeNames.text; + return 9 /* text */; } } function processElement(element) { @@ -40543,6 +40599,8 @@ var ts; getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics, getSyntacticClassifications: getSyntacticClassifications, getSemanticClassifications: getSemanticClassifications, + getEncodedSyntacticClassifications: getEncodedSyntacticClassifications, + getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, getSignatureHelpItems: getSignatureHelpItems, @@ -40671,9 +40729,58 @@ var ts; // if there are more cases we want the classifier to be better at. return true; } + function convertClassifications(classifications, text) { + var entries = []; + var dense = classifications.spans; + var lastEnd = 0; + for (var i = 0, n = dense.length; i < n; i += 3) { + var start = dense[i]; + var length_1 = dense[i + 1]; + var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. + if (lastEnd >= 0) { + var whitespaceLength_1 = start - lastEnd; + if (whitespaceLength_1 > 0) { + entries.push({ length: whitespaceLength_1, classification: TokenClass.Whitespace }); + } + } + entries.push({ length: length_1, classification: convertClassification(type) }); + lastEnd = start + length_1; + } + var whitespaceLength = text.length - lastEnd; + if (whitespaceLength > 0) { + entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); + } + return { entries: entries, finalLexState: classifications.endOfLineState }; + } + function convertClassification(type) { + switch (type) { + case 1 /* comment */: return TokenClass.Comment; + case 3 /* keyword */: return TokenClass.Keyword; + case 4 /* numericLiteral */: return TokenClass.NumberLiteral; + case 5 /* operator */: return TokenClass.Operator; + case 6 /* stringLiteral */: return TokenClass.StringLiteral; + case 8 /* whiteSpace */: return TokenClass.Whitespace; + case 10 /* punctuation */: return TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: + default: + return TokenClass.Identifier; + } + } + function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + } // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), // we will be more conservative in order to avoid conflicting with the syntactic classifier. - function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { var offset = 0; var token = 0 /* Unknown */; var lastNonTriviaToken = 0 /* Unknown */; @@ -40713,8 +40820,8 @@ var ts; } scanner.setText(text); var result = { - finalLexState: 0 /* Start */, - entries: [] + endOfLineState: 0 /* None */, + spans: [] }; // We can run into an unfortunate interaction between the lexical and syntactic classifier // when the user is typing something generic. Consider the case where the user types: @@ -40816,7 +40923,7 @@ var ts; function processToken() { var start = scanner.getTokenPos(); var end = scanner.getTextPos(); - addResult(end - start, classFromKind(token)); + addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === 8 /* StringLiteral */) { // Check to see if we finished up on a multiline string literal. @@ -40830,7 +40937,7 @@ var ts; // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { var quoteChar = tokenText.charCodeAt(0); - result.finalLexState = quoteChar === 34 /* doubleQuote */ + result.endOfLineState = quoteChar === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */; } @@ -40839,16 +40946,16 @@ var ts; else if (token === 3 /* MultiLineCommentTrivia */) { // Check to see if the multiline comment was unclosed. if (scanner.isUnterminated()) { - result.finalLexState = 1 /* InMultiLineCommentTrivia */; + result.endOfLineState = 1 /* InMultiLineCommentTrivia */; } } else if (ts.isTemplateLiteralKind(token)) { if (scanner.isUnterminated()) { if (token === 13 /* TemplateTail */) { - result.finalLexState = 5 /* InTemplateMiddleOrTail */; + result.endOfLineState = 5 /* InTemplateMiddleOrTail */; } else if (token === 10 /* NoSubstitutionTemplateLiteral */) { - result.finalLexState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; + result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; } else { ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); @@ -40856,18 +40963,30 @@ var ts; } } else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11 /* TemplateHead */) { - result.finalLexState = 6 /* InTemplateSubstitutionPosition */; + result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; } } } - function addResult(length, classification) { + function addResult(start, end, classification) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. + return; + } + if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended + // text. We should consider the start of this token to be at the start of + // the original text. + start += offset; + } + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. + start -= offset; + end -= offset; + var length = end - start; if (length > 0) { - // If this is the first classification we're adding to the list, then remove any - // offset we have if we were continuing a construct from the previous line. - if (result.entries.length === 0) { - length -= offset; - } - result.entries.push({ length: length, classification: classification }); + result.spans.push(start); + result.spans.push(length); + result.spans.push(classification); } } } @@ -40932,37 +41051,40 @@ var ts; } function classFromKind(token) { if (isKeyword(token)) { - return TokenClass.Keyword; + return 3 /* keyword */; } else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return TokenClass.Operator; + return 5 /* operator */; } else if (token >= 14 /* FirstPunctuation */ && token <= 64 /* LastPunctuation */) { - return TokenClass.Punctuation; + return 10 /* punctuation */; } switch (token) { case 7 /* NumericLiteral */: - return TokenClass.NumberLiteral; + return 4 /* numericLiteral */; case 8 /* StringLiteral */: - return TokenClass.StringLiteral; + return 6 /* stringLiteral */; case 9 /* RegularExpressionLiteral */: - return TokenClass.RegExpLiteral; + return 7 /* regularExpressionLiteral */; case 6 /* ConflictMarkerTrivia */: case 3 /* MultiLineCommentTrivia */: case 2 /* SingleLineCommentTrivia */: - return TokenClass.Comment; + return 1 /* comment */; case 5 /* WhitespaceTrivia */: case 4 /* NewLineTrivia */: - return TokenClass.Whitespace; + return 8 /* whiteSpace */; case 65 /* Identifier */: default: if (ts.isTemplateLiteralKind(token)) { - return TokenClass.StringLiteral; + return 6 /* stringLiteral */; } - return TokenClass.Identifier; + return 2 /* identifier */; } } - return { getClassificationsForLine: getClassificationsForLine }; + return { + getClassificationsForLine: getClassificationsForLine, + getEncodedLexicalClassifications: getEncodedLexicalClassifications + }; } ts.createClassifier = createClassifier; /** @@ -41461,7 +41583,9 @@ var debugObjectHost = this; var ts; (function (ts) { function logInternalError(logger, err) { - logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); + if (logger) { + logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); + } } var ScriptSnapshotShimAdapter = (function () { function ScriptSnapshotShimAdapter(scriptSnapshotShim) { @@ -41565,24 +41689,28 @@ var ts; return CoreServicesShimHostAdapter; })(); ts.CoreServicesShimHostAdapter = CoreServicesShimHostAdapter; - function simpleForwardCall(logger, actionDescription, action) { - logger.log(actionDescription); - var start = Date.now(); + function simpleForwardCall(logger, actionDescription, action, noPerfLogging) { + if (!noPerfLogging) { + logger.log(actionDescription); + var start = Date.now(); + } var result = action(); - var end = Date.now(); - logger.log(actionDescription + " completed in " + (end - start) + " msec"); - if (typeof (result) === "string") { - var str = result; - if (str.length > 128) { - str = str.substring(0, 128) + "..."; + if (!noPerfLogging) { + var end = Date.now(); + logger.log(actionDescription + " completed in " + (end - start) + " msec"); + if (typeof (result) === "string") { + var str = result; + if (str.length > 128) { + str = str.substring(0, 128) + "..."; + } + logger.log(" result.length=" + str.length + ", result='" + JSON.stringify(str) + "'"); } - logger.log(" result.length=" + str.length + ", result='" + JSON.stringify(str) + "'"); } return result; } - function forwardJSONCall(logger, actionDescription, action) { + function forwardJSONCall(logger, actionDescription, action, noPerfLogging) { try { - var result = simpleForwardCall(logger, actionDescription, action); + var result = simpleForwardCall(logger, actionDescription, action, noPerfLogging); return JSON.stringify({ result: result }); } catch (err) { @@ -41627,7 +41755,7 @@ var ts; this.logger = this.host; } LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) { - return forwardJSONCall(this.logger, actionDescription, action); + return forwardJSONCall(this.logger, actionDescription, action, false); }; /// DISPOSE /** @@ -41680,6 +41808,22 @@ var ts; return classifications; }); }; + LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) { + var _this = this; + return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); + }); + }; + LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) { + var _this = this; + return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); + }); + }; LanguageServiceShimObject.prototype.getNewLine = function () { return this.host.getNewLine ? this.host.getNewLine() : "\r\n"; }; @@ -41899,12 +42043,21 @@ var ts; }; return LanguageServiceShimObject; })(ShimBase); + function convertClassifications(classifications) { + return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; + } var ClassifierShimObject = (function (_super) { __extends(ClassifierShimObject, _super); - function ClassifierShimObject(factory) { + function ClassifierShimObject(factory, logger) { _super.call(this, factory); + this.logger = logger; this.classifier = ts.createClassifier(); } + ClassifierShimObject.prototype.getEncodedLexicalClassifications = function (text, lexState, syntacticClassifierAbsent) { + var _this = this; + return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, + /*noPerfLogging:*/ true); + }; /// COLORIZATION ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) { var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); @@ -41927,7 +42080,7 @@ var ts; this.host = host; } CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) { - return forwardJSONCall(this.logger, actionDescription, action); + return forwardJSONCall(this.logger, actionDescription, action, false); }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { @@ -42005,7 +42158,7 @@ var ts; }; TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) { try { - return new ClassifierShimObject(this); + return new ClassifierShimObject(this, logger); } catch (err) { logInternalError(logger, err);