Moved non-exposed functions to utilities; fix up emitted .d.ts in Jakefile.

Conflicts:
	src/compiler/parser.ts
This commit is contained in:
Daniel Rosenwasser 2014-12-10 16:42:41 -08:00
parent a173017aa6
commit 0ce3861602
6 changed files with 1004 additions and 927 deletions

111
Jakefile
View File

@ -35,6 +35,7 @@ var compilerSources = [
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts",
"emitter.ts",
@ -47,26 +48,53 @@ var compilerSources = [
var servicesSources = [
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts",
"emitter.ts"
"emitter.ts",
"diagnosticInformationMap.generated.ts"
].map(function (f) {
return path.join(compilerDirectory, f);
}).concat([
"breakpoints.ts",
"navigationBar.ts",
"outliningElementsCollector.ts",
"services.ts",
"shims.ts",
"signatureHelp.ts",
"utilities.ts",
"navigationBar.ts",
"outliningElementsCollector.ts"
"formatting/formatting.ts",
"formatting/formattingContext.ts",
"formatting/formattingRequestKind.ts",
"formatting/formattingScanner.ts",
"formatting/references.ts",
"formatting/rule.ts",
"formatting/ruleAction.ts",
"formatting/ruleDescriptor.ts",
"formatting/ruleFlag.ts",
"formatting/ruleOperation.ts",
"formatting/ruleOperationContext.ts",
"formatting/rules.ts",
"formatting/rulesMap.ts",
"formatting/rulesProvider.ts",
"formatting/smartIndenter.ts",
"formatting/tokenRange.ts"
].map(function (f) {
return path.join(servicesDirectory, f);
}));
var definitionsRoots = [
"compiler/types.d.ts",
"compiler/scanner.d.ts",
"compiler/parser.d.ts",
"compiler/checker.d.ts",
"services/services.d.ts",
];
var harnessSources = [
"harness.ts",
"sourceMapRecorder.ts",
@ -149,25 +177,48 @@ var compilerFilename = "tsc.js";
* @param prefixes: a list of files to prepend to the target file
* @param useBuiltCompiler: true to use the built compiler, false to use the LKG
* @param noOutFile: true to compile without using --out
* @param generateDeclarations: true to compile using --declaration
* @param outDir: true to compile using --outDir
* @param keepComments: false to compile using --removeComments
* @param callback: a function to execute after the compilation process ends
*/
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, callback) {
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, keepComments, noResolve, callback) {
file(outFile, prereqs, function() {
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
var options = "-removeComments --module commonjs -noImplicitAny ";
var options = "--module commonjs -noImplicitAny";
if (!keepComments) {
options += " -removeComments";
}
if (generateDeclarations) {
options += "--declaration ";
options += " --declaration";
}
if (useDebugMode) {
options += "--preserveConstEnums ";
options += " --preserveConstEnums";
}
if (outDir) {
options += " --outDir " + outDir;
}
if (!noOutFile) {
options += " --out " + outFile;
}
if(noResolve) {
options += " --noResolve";
}
if (useDebugMode) {
options += " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
}
var cmd = host + " " + dir + compilerFilename + " " + options + " ";
cmd = cmd + sources.join(" ") + (!noOutFile ? " -out " + outFile : "");
if (useDebugMode) {
cmd = cmd + " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
}
cmd = cmd + sources.join(" ");
console.log(cmd + "\n");
var ex = jake.createExec([cmd]);
// Add listeners for output and error
ex.addListener("stdout", function(output) {
@ -260,24 +311,38 @@ var tscFile = path.join(builtLocalDirectory, compilerFilename);
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
var servicesDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources), [copyright], /*useBuiltCompiler*/ true);
compileFile(servicesFile,
servicesSources,
[builtLocalDirectory, copyright].concat(servicesSources),
[copyright],
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
var tempDirPath = path.join(builtLocalDirectory, "temptempdir");
compileFile(nodeDefinitionsFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
/*prefixes*/ undefined,
/*useBuiltCompiler*/ true,
/*noOutFile*/ false,
/*noOutFile*/ true,
/*generateDeclarations*/ true,
/*callback*/ fixDeclarationFile);
/*outDir*/ tempDirPath,
/*keepComments*/ true,
/*noResolve*/ true,
/*callback*/ function () {
concatenateFiles(standaloneDefinitionsFile, definitionsRoots.map(function (f) {
return path.join(tempDirPath, f);
}));
prependFile(copyright, standaloneDefinitionsFile);
function fixDeclarationFile() {
fs.appendFileSync(servicesDefinitionsFile, os.EOL + "export = ts;")
}
// Create the node definition file by replacing 'ts' module with '"typescript"' as a module.
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
definitionFileContents = definitionFileContents.replace(/declare module ts/g, 'declare module "typescript"');
fs.writeFileSync(nodeDefinitionsFile, definitionFileContents);
// Delete the temp dir
jake.rmRf(tempDirPath, {silent: true});
});
// Local target to build the compiler and services
desc("Builds the full compiler and services");
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile]);
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile]);
// Local target to build the compiler and services
desc("Sets release mode flag");
@ -328,7 +393,7 @@ task("generate-spec", [specMd])
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc("Makes a new LKG out of the built js files");
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
var expectedFiles = [tscFile, servicesFile, servicesDefinitionsFile].concat(libraryTargets);
var expectedFiles = [tscFile, servicesFile, nodeDefinitionsFile, standaloneDefinitionsFile].concat(libraryTargets);
var missingFiles = expectedFiles.filter(function (f) {
return !fs.existsSync(f);
});

View File

@ -4,57 +4,12 @@
/// <reference path="parser.ts"/>
/// <reference path="binder.ts"/>
/// <reference path="emitter.ts"/>
/// <reference path="utilities.ts"/>
module ts {
var nextSymbolId = 1;
var nextNodeId = 1;
var nextMergeId = 1;
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
var declarations = symbol.declarations;
for (var i = 0; i < declarations.length; i++) {
var declaration = declarations[i];
if (declaration.kind === kind) {
return declaration;
}
}
return undefined;
}
export interface StringSymbolWriter extends SymbolWriter {
string(): string;
}
// Pool writers to avoid needing to allocate them for every symbol we write.
var stringWriters: StringSymbolWriter[] = [];
export function getSingleLineStringWriter(): StringSymbolWriter {
if (stringWriters.length == 0) {
var str = "";
var writeText: (text: string) => void = text => str += text;
return {
string: () => str,
writeKeyword: writeText,
writeOperator: writeText,
writePunctuation: writeText,
writeSpace: writeText,
writeStringLiteral: writeText,
writeParameter: writeText,
writeSymbol: writeText,
// Completely ignore indentation for string writers. And map newlines to
// a single space.
writeLine: () => str += " ",
increaseIndent: () => { },
decreaseIndent: () => { },
clear: () => str = "",
trackSymbol: () => { }
};
}
return stringWriters.pop();
}
var nextMergeId = 1;
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
@ -1012,11 +967,6 @@ module ts {
};
}
function releaseStringWriter(writer: StringSymbolWriter) {
writer.clear()
stringWriters.push(writer);
}
function writeKeyword(writer: SymbolWriter, kind: SyntaxKind) {
writer.writeKeyword(tokenToString(kind));
}

View File

@ -1,41 +1,11 @@
/// <reference path="types.ts"/>
/// <reference path="core.ts"/>
/// <reference path="scanner.ts"/>
/// <reference path="utilities.ts"/>
module ts {
var nodeConstructors = new Array<new () => Node>(SyntaxKind.Count);
export function getFullWidth(node: Node) {
return node.end - node.pos;
}
function hasFlag(val: number, flag: number): boolean {
return (val & flag) !== 0;
}
// Returns true if this node contains a parse error anywhere underneath it.
export function containsParseError(node: Node): boolean {
if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasPropagatedChildContainsErrorFlag)) {
// A node is considered to contain a parse error if:
// a) the parser explicitly marked that it had an error
// b) any of it's children reported that it had an error.
var val = hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError) ||
forEachChild(node, containsParseError);
// If so, mark ourselves accordingly.
if (val) {
node.parserContextFlags |= ParserContextFlags.ContainsError;
}
// Also mark that we've propogated the child information to this node. This way we can
// always consult the bit directly on this node without needing to check its children
// again.
node.parserContextFlags |= ParserContextFlags.HasPropagatedChildContainsErrorFlag;
}
return hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError);
}
export function getNodeConstructor(kind: SyntaxKind): new () => Node {
return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
}
@ -44,140 +14,6 @@ module ts {
return new (getNodeConstructor(kind))();
}
export function getSourceFileOfNode(node: Node): SourceFile {
while (node && node.kind !== SyntaxKind.SourceFile) node = node.parent;
return <SourceFile>node;
}
// This is a useful function for debugging purposes.
export function nodePosToString(node: Node): string {
var file = getSourceFileOfNode(node);
var loc = file.getLineAndCharacterFromPosition(node.pos);
return file.filename + "(" + loc.line + "," + loc.character + ")";
}
export function getStartPosOfNode(node: Node): number {
return node.pos;
}
export function isMissingNode(node: Node) {
return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken;
}
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
// want to skip trivia because this will launch us forward to the next token.
if (isMissingNode(node)) {
return node.pos;
}
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
}
export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string {
if (isMissingNode(node)) {
return "";
}
var text = sourceFile.text;
return text.substring(skipTrivia(text, node.pos), node.end);
}
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
if (isMissingNode(node)) {
return "";
}
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
}
export function getTextOfNode(node: Node): string {
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
}
// Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
export function escapeIdentifier(identifier: string): string {
return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier;
}
// Remove extra underscore from escaped identifier
export function unescapeIdentifier(identifier: string): string {
return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
}
// Return display name of an identifier
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
// text of the expression in the computed property.
export function declarationNameToString(name: DeclarationName) {
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = getFullWidth(node) === 0 ? node.pos : skipTrivia(file.text, node.pos);
var length = node.end - start;
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
}
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain, newLine: string): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = skipTrivia(file.text, node.pos);
var length = node.end - start;
return flattenDiagnosticChain(file, start, length, messageChain, newLine);
}
export function getErrorSpanForNode(node: Node): Node {
var errorSpan: Node;
switch (node.kind) {
// This list is a work in progress. Add missing node kinds to improve their error
// spans.
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
errorSpan = (<Declaration>node).name;
break;
}
// We now have the ideal error span, but it may be a node that is optional and absent
// (e.g. the name of a function expression), in which case errorSpan will be undefined.
// Alternatively, it might be required and missing (e.g. the name of a module), in which
// case its pos will equal its end (length 0). In either of these cases, we should fall
// back to the original node that the error was issued on.
return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node;
}
export function isExternalModule(file: SourceFile): boolean {
return file.externalModuleIndicator !== undefined;
}
export function isDeclarationFile(file: SourceFile): boolean {
return (file.flags & NodeFlags.DeclarationFile) !== 0;
}
export function isConstEnumDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
}
export function isConst(node: Node): boolean {
return !!(node.flags & NodeFlags.Const);
}
export function isLet(node: Node): boolean {
return !!(node.flags & NodeFlags.Let);
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
function isEvalOrArgumentsIdentifier(node: Node): boolean {
return node.kind === SyntaxKind.Identifier &&
(<Identifier>node).text &&
@ -190,36 +26,6 @@ module ts {
return (<Identifier>(<ExpressionStatement>node).expression).text === "use strict";
}
export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile) {
sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node);
// If parameter/type parameter, the prev token trailing comments are part of this node too
if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) {
// e.g. (/** blah */ a, /** blah */ b);
return concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
// e.g.: (
// /** blah */ a,
// /** blah */ b);
getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
}
else {
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
}
}
export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
function isJsDocComment(comment: CommentRange) {
// True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
}
}
export var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
@ -466,425 +272,6 @@ module ts {
}
}
// Warning: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(<ReturnStatement>node);
case SyntaxKind.Block:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabeledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
export function isAnyFunction(node: Node): boolean {
if (node) {
switch (node.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionDeclaration:
return true;
}
}
return false;
}
export function isFunctionBlock(node: Node) {
return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent);
}
export function isObjectLiteralMethod(node: Node) {
return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
}
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;
if (!node || isAnyFunction(node)) {
return <FunctionLikeDeclaration>node;
}
}
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.ArrowFunction:
if (!includeArrowFunctions) {
continue;
}
// Fall through
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.SourceFile:
return node;
}
}
}
export function getSuperContainer(node: Node): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node;
}
}
}
export function getInvokedExpression(node: CallLikeExpression): Expression {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;
}
// Will either be a CallExpression or NewExpression.
return (<CallExpression>node).expression;
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.VoidExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.TemplateExpression:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.BindingElement:
return (<VariableLikeDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertionExpression:
return node === (<TypeAssertion>parent).expression;
case SyntaxKind.TemplateSpan:
return node === (<TemplateSpan>parent).expression;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
}
export function isExternalModuleImportDeclaration(node: Node) {
return node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
}
export function getExternalModuleImportDeclarationExpression(node: Node) {
Debug.assert(isExternalModuleImportDeclaration(node));
return (<ExternalModuleReference>(<ImportDeclaration>node).moduleReference).expression;
}
export function isInternalModuleImportDeclaration(node: Node) {
return node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}
export function hasDotDotDotToken(node: Node) {
return node && node.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node).dotDotDotToken !== undefined;
}
export function hasQuestionToken(node: Node) {
if (node) {
switch (node.kind) {
case SyntaxKind.Parameter:
return (<ParameterDeclaration>node).questionToken !== undefined;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
return (<MethodDeclaration>node).questionToken !== undefined;
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return (<PropertyDeclaration>node).questionToken !== undefined;
}
}
return false;
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
}
export function isLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
}
export function isBindingPattern(node: Node) {
return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern;
}
export function isInAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
node = node.parent;
}
return false;
}
export function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
return true;
}
return false;
}
export function isStatement(n: Node): boolean {
switch(n.kind) {
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.ThrowKeyword:
case SyntaxKind.TryStatement:
case SyntaxKind.VariableStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.ExportAssignment:
return true;
default:
return false;
}
}
// True if the given identifier, string literal, or number literal is the name of a declaration node
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
return false;
}
var parent = name.parent;
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
return (<Declaration>parent).name === name;
}
if (parent.kind === SyntaxKind.CatchClause) {
return (<CatchClause>parent).name === name;
}
return false;
}
export function getClassBaseTypeNode(node: ClassDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
}
export function getClassImplementedTypeNodes(node: ClassDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
return heritageClause ? heritageClause.types : undefined;
}
export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause ? heritageClause.types : undefined;
}
export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
if (clauses) {
for (var i = 0, n = clauses.length; i < n; i++) {
if (clauses[i].token === kind) {
return clauses[i];
}
}
}
return undefined;
}
export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) {
if (!program.getCompilerOptions().noResolve) {
var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename);
referenceFileName = getNormalizedAbsolutePath(referenceFileName, program.getCompilerHost().getCurrentDirectory());
return program.getSourceFile(referenceFileName);
}
}
export function getAncestor(node: Node, kind: SyntaxKind): Node {
switch (kind) {
// special-cases that can be come first
case SyntaxKind.ClassDeclaration:
while (node) {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return <ClassDeclaration>node;
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
// early exit cases - declarations cannot be nested in classes
return undefined;
default:
node = node.parent;
continue;
}
}
break;
default:
while (node) {
if (node.kind === kind) {
return node;
}
node = node.parent;
}
break;
}
return undefined;
}
const enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
@ -940,68 +327,6 @@ module ts {
}
};
export interface ReferencePathMatchResult {
fileReference?: FileReference
diagnosticMessage?: DiagnosticMessage
isNoDefaultLib?: boolean
}
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.exec(comment)) {
if (isNoDefaultLibRegEx.exec(comment)) {
return {
isNoDefaultLib: true
}
}
else {
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
if (matchResult) {
var start = commentRange.pos;
var end = commentRange.end;
return {
fileReference: {
pos: start,
end: end,
filename: matchResult[3]
},
isNoDefaultLib: false
};
}
else {
return {
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
};
}
}
}
return undefined;
}
export function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
export function isTrivia(token: SyntaxKind) {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
export function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ConstKeyword:
return true;
}
return false;
}
function modifierToFlag(token: SyntaxKind): NodeFlags {
switch (token) {
case SyntaxKind.StaticKeyword: return NodeFlags.Static;

732
src/compiler/utilities.ts Normal file
View File

@ -0,0 +1,732 @@
/// <reference path="types.ts" />
module ts {
export interface ReferencePathMatchResult {
fileReference?: FileReference
diagnosticMessage?: DiagnosticMessage
isNoDefaultLib?: boolean
}
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
var declarations = symbol.declarations;
for (var i = 0; i < declarations.length; i++) {
var declaration = declarations[i];
if (declaration.kind === kind) {
return declaration;
}
}
return undefined;
}
export interface StringSymbolWriter extends SymbolWriter {
string(): string;
}
// Pool writers to avoid needing to allocate them for every symbol we write.
var stringWriters: StringSymbolWriter[] = [];
export function getSingleLineStringWriter(): StringSymbolWriter {
if (stringWriters.length == 0) {
var str = "";
var writeText: (text: string) => void = text => str += text;
return {
string: () => str,
writeKeyword: writeText,
writeOperator: writeText,
writePunctuation: writeText,
writeSpace: writeText,
writeStringLiteral: writeText,
writeParameter: writeText,
writeSymbol: writeText,
// Completely ignore indentation for string writers. And map newlines to
// a single space.
writeLine: () => str += " ",
increaseIndent: () => { },
decreaseIndent: () => { },
clear: () => str = "",
trackSymbol: () => { }
};
}
return stringWriters.pop();
}
export function releaseStringWriter(writer: StringSymbolWriter) {
writer.clear()
stringWriters.push(writer);
}
export function getFullWidth(node: Node) {
return node.end - node.pos;
}
export function hasFlag(val: number, flag: number): boolean {
return (val & flag) !== 0;
}
// Returns true if this node contains a parse error anywhere underneath it.
export function containsParseError(node: Node): boolean {
if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasPropagatedChildContainsErrorFlag)) {
// A node is considered to contain a parse error if:
// a) the parser explicitly marked that it had an error
// b) any of it's children reported that it had an error.
var val = hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError) ||
forEachChild(node, containsParseError);
// If so, mark ourselves accordingly.
if (val) {
node.parserContextFlags |= ParserContextFlags.ContainsError;
}
// Also mark that we've propogated the child information to this node. This way we can
// always consult the bit directly on this node without needing to check its children
// again.
node.parserContextFlags |= ParserContextFlags.HasPropagatedChildContainsErrorFlag;
}
return hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError);
}
export function getSourceFileOfNode(node: Node): SourceFile {
while (node && node.kind !== SyntaxKind.SourceFile) node = node.parent;
return <SourceFile>node;
}
// This is a useful function for debugging purposes.
export function nodePosToString(node: Node): string {
var file = getSourceFileOfNode(node);
var loc = file.getLineAndCharacterFromPosition(node.pos);
return file.filename + "(" + loc.line + "," + loc.character + ")";
}
export function getStartPosOfNode(node: Node): number {
return node.pos;
}
export function isMissingNode(node: Node) {
return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken;
}
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
// want to skip trivia because this will launch us forward to the next token.
if (isMissingNode(node)) {
return node.pos;
}
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
}
export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string {
if (isMissingNode(node)) {
return "";
}
var text = sourceFile.text;
return text.substring(skipTrivia(text, node.pos), node.end);
}
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
if (isMissingNode(node)) {
return "";
}
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
}
export function getTextOfNode(node: Node): string {
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
}
// Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
export function escapeIdentifier(identifier: string): string {
return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier;
}
// Remove extra underscore from escaped identifier
export function unescapeIdentifier(identifier: string): string {
return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
}
// Return display name of an identifier
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
// text of the expression in the computed property.
export function declarationNameToString(name: DeclarationName) {
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = getFullWidth(node) === 0 ? node.pos : skipTrivia(file.text, node.pos);
var length = node.end - start;
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
}
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain, newLine: string): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = skipTrivia(file.text, node.pos);
var length = node.end - start;
return flattenDiagnosticChain(file, start, length, messageChain, newLine);
}
export function getErrorSpanForNode(node: Node): Node {
var errorSpan: Node;
switch (node.kind) {
// This list is a work in progress. Add missing node kinds to improve their error
// spans.
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
errorSpan = (<Declaration>node).name;
break;
}
// We now have the ideal error span, but it may be a node that is optional and absent
// (e.g. the name of a function expression), in which case errorSpan will be undefined.
// Alternatively, it might be required and missing (e.g. the name of a module), in which
// case its pos will equal its end (length 0). In either of these cases, we should fall
// back to the original node that the error was issued on.
return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node;
}
export function isExternalModule(file: SourceFile): boolean {
return file.externalModuleIndicator !== undefined;
}
export function isDeclarationFile(file: SourceFile): boolean {
return (file.flags & NodeFlags.DeclarationFile) !== 0;
}
export function isConstEnumDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
}
export function isConst(node: Node): boolean {
return !!(node.flags & NodeFlags.Const);
}
export function isLet(node: Node): boolean {
return !!(node.flags & NodeFlags.Let);
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile) {
sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node);
// If parameter/type parameter, the prev token trailing comments are part of this node too
if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) {
// e.g. (/** blah */ a, /** blah */ b);
return concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
// e.g.: (
// /** blah */ a,
// /** blah */ b);
getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
}
else {
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
}
}
export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
function isJsDocComment(comment: CommentRange) {
// True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
}
}
export var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/
// Warning: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(<ReturnStatement>node);
case SyntaxKind.Block:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabeledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
export function isAnyFunction(node: Node): boolean {
if (node) {
switch (node.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionDeclaration:
return true;
}
}
return false;
}
export function isFunctionBlock(node: Node) {
return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent);
}
export function isObjectLiteralMethod(node: Node) {
return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
}
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;
if (!node || isAnyFunction(node)) {
return <FunctionLikeDeclaration>node;
}
}
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.ArrowFunction:
if (!includeArrowFunctions) {
continue;
}
// Fall through
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.SourceFile:
return node;
}
}
}
export function getSuperContainer(node: Node): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node;
}
}
}
export function getInvokedExpression(node: CallLikeExpression): Expression {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;
}
// Will either be a CallExpression or NewExpression.
return (<CallExpression>node).expression;
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.VoidExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.TemplateExpression:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.BindingElement:
return (<VariableLikeDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertionExpression:
return node === (<TypeAssertion>parent).expression;
case SyntaxKind.TemplateSpan:
return node === (<TemplateSpan>parent).expression;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
}
export function isExternalModuleImportDeclaration(node: Node) {
return node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
}
export function getExternalModuleImportDeclarationExpression(node: Node) {
Debug.assert(isExternalModuleImportDeclaration(node));
return (<ExternalModuleReference>(<ImportDeclaration>node).moduleReference).expression;
}
export function isInternalModuleImportDeclaration(node: Node) {
return node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}
export function hasDotDotDotToken(node: Node) {
return node && node.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node).dotDotDotToken !== undefined;
}
export function hasQuestionToken(node: Node) {
if (node) {
switch (node.kind) {
case SyntaxKind.Parameter:
return (<ParameterDeclaration>node).questionToken !== undefined;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
return (<MethodDeclaration>node).questionToken !== undefined;
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return (<PropertyDeclaration>node).questionToken !== undefined;
}
}
return false;
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
}
export function isLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
}
export function isBindingPattern(node: Node) {
return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern;
}
export function isInAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
node = node.parent;
}
return false;
}
export function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
return true;
}
return false;
}
export function isStatement(n: Node): boolean {
switch (n.kind) {
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.ThrowKeyword:
case SyntaxKind.TryStatement:
case SyntaxKind.VariableStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.ExportAssignment:
return true;
default:
return false;
}
}
// True if the given identifier, string literal, or number literal is the name of a declaration node
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
return false;
}
var parent = name.parent;
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
return (<Declaration>parent).name === name;
}
if (parent.kind === SyntaxKind.CatchClause) {
return (<CatchClause>parent).name === name;
}
return false;
}
export function getClassBaseTypeNode(node: ClassDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
}
export function getClassImplementedTypeNodes(node: ClassDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
return heritageClause ? heritageClause.types : undefined;
}
export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) {
var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause ? heritageClause.types : undefined;
}
export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
if (clauses) {
for (var i = 0, n = clauses.length; i < n; i++) {
if (clauses[i].token === kind) {
return clauses[i];
}
}
}
return undefined;
}
export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) {
if (!program.getCompilerOptions().noResolve) {
var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename);
referenceFileName = getNormalizedAbsolutePath(referenceFileName, program.getCompilerHost().getCurrentDirectory());
return program.getSourceFile(referenceFileName);
}
}
export function getAncestor(node: Node, kind: SyntaxKind): Node {
switch (kind) {
// special-cases that can be come first
case SyntaxKind.ClassDeclaration:
while (node) {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return <ClassDeclaration>node;
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
// early exit cases - declarations cannot be nested in classes
return undefined;
default:
node = node.parent;
continue;
}
}
break;
default:
while (node) {
if (node.kind === kind) {
return node;
}
node = node.parent;
}
break;
}
return undefined;
}
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.exec(comment)) {
if (isNoDefaultLibRegEx.exec(comment)) {
return {
isNoDefaultLib: true
}
}
else {
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
if (matchResult) {
var start = commentRange.pos;
var end = commentRange.end;
return {
fileReference: {
pos: start,
end: end,
filename: matchResult[3]
},
isNoDefaultLib: false
};
}
else {
return {
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
};
}
}
}
return undefined;
}
export function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
export function isTrivia(token: SyntaxKind) {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
export function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ConstKeyword:
return true;
}
return false;
}
}

View File

@ -1662,6 +1662,10 @@ module ts {
owners: string[];
}
export interface DisplayPartsSymbolWriter extends SymbolWriter {
displayParts(): SymbolDisplayPart[];
}
export function displayPartsToString(displayParts: SymbolDisplayPart[]) {
if (displayParts) {
return map(displayParts, displayPart => displayPart.text).join("");
@ -1670,100 +1674,6 @@ module ts {
return "";
}
export interface DisplayPartsSymbolWriter extends SymbolWriter {
displayParts(): SymbolDisplayPart[];
}
var displayPartWriter = getDisplayPartWriter();
function getDisplayPartWriter(): DisplayPartsSymbolWriter {
var displayParts: SymbolDisplayPart[];
var lineStart: boolean;
var indent: number;
resetWriter();
return {
displayParts: () => displayParts,
writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword),
writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator),
writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation),
writeSpace: text => writeKind(text, SymbolDisplayPartKind.space),
writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral),
writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName),
writeSymbol,
writeLine,
increaseIndent: () => { indent++; },
decreaseIndent: () => { indent--; },
clear: resetWriter,
trackSymbol: () => { }
};
function writeIndent() {
if (lineStart) {
var indentString = getIndentString(indent);
if (indentString) {
displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space));
}
lineStart = false;
}
}
function writeKind(text: string, kind: SymbolDisplayPartKind) {
writeIndent();
displayParts.push(displayPart(text, kind));
}
function writeSymbol(text: string, symbol: Symbol) {
writeIndent();
displayParts.push(symbolPart(text, symbol));
}
function writeLine() {
displayParts.push(lineBreakPart());
lineStart = true;
}
function resetWriter() {
displayParts = []
lineStart = true;
indent = 0;
}
}
function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart {
return <SymbolDisplayPart> {
text: text,
kind: SymbolDisplayPartKind[kind]
};
}
export function spacePart() {
return displayPart(" ", SymbolDisplayPartKind.space);
}
export function keywordPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword);
}
export function punctuationPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation);
}
export function operatorPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator);
}
export function textPart(text: string) {
return displayPart(text, SymbolDisplayPartKind.text);
}
export function lineBreakPart() {
return displayPart("\n", SymbolDisplayPartKind.lineBreak);
}
function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
}
function isLocalVariableOrFunction(symbol: Symbol) {
if (symbol.parent) {
return false; // This is exported symbol
@ -1792,59 +1702,6 @@ module ts {
});
}
export function symbolPart(text: string, symbol: Symbol) {
return displayPart(text, displayPartKind(symbol), symbol);
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
var flags = symbol.flags;
if (flags & SymbolFlags.Variable) {
return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
}
else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; }
else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; }
else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; }
else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.interfaceName; }
else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.enumName; }
else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; }
else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; }
else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; }
else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; }
else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; }
return SymbolDisplayPartKind.text;
}
}
export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
writeDisplayParts(displayPartWriter);
var result = displayPartWriter.displayParts();
displayPartWriter.clear();
return result;
}
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
return mapToDisplayParts(writer => {
typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
});
}
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
return mapToDisplayParts(writer => {
typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
});
}
function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[]{
return mapToDisplayParts(writer => {
typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
});
}
export function getDefaultCompilerOptions(): CompilerOptions {
// Set "ScriptTarget.Latest" target by default for language service
return {
@ -1853,20 +1710,6 @@ module ts {
};
}
export function compareDataObjects(dst: any, src: any): boolean {
for (var e in dst) {
if (typeof dst[e] === "object") {
if (!compareDataObjects(dst[e], src[e]))
return false;
}
else if (typeof dst[e] !== "function") {
if (dst[e] !== src[e])
return false;
}
}
return true;
}
export class OperationCanceledException { }
export class CancellationTokenObject {
@ -2205,20 +2048,6 @@ module ts {
}
/// Helpers
export function getNodeModifiers(node: Node): string {
var flags = node.flags;
var result: string[] = [];
if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier);
return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none;
}
function getTargetLabel(referenceNode: Node, labelName: string): Identifier {
while (referenceNode) {
if (referenceNode.kind === SyntaxKind.LabeledStatement && (<LabeledStatement>referenceNode).label.text === labelName) {

View File

@ -270,7 +270,21 @@ module ts {
return n.getWidth() !== 0;
}
export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node> {
export function getNodeModifiers(node: Node): string {
var flags = node.flags;
var result: string[] = [];
if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier);
return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none;
}
export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node> {
if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) {
return (<CallExpression>node).typeArguments;
}
@ -306,4 +320,166 @@ module ts {
return isTemplateLiteralKind(node.kind)
&& (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
}
export function compareDataObjects(dst: any, src: any): boolean {
for (var e in dst) {
if (typeof dst[e] === "object") {
if (!compareDataObjects(dst[e], src[e])) {
return false;
}
}
else if (typeof dst[e] !== "function") {
if (dst[e] !== src[e]) {
return false;
}
}
}
return true;
}
}
// Display-part writer helpers
module ts {
export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
}
var displayPartWriter = getDisplayPartWriter();
function getDisplayPartWriter(): DisplayPartsSymbolWriter {
var displayParts: SymbolDisplayPart[];
var lineStart: boolean;
var indent: number;
resetWriter();
return {
displayParts: () => displayParts,
writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword),
writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator),
writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation),
writeSpace: text => writeKind(text, SymbolDisplayPartKind.space),
writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral),
writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName),
writeSymbol,
writeLine,
increaseIndent: () => { indent++; },
decreaseIndent: () => { indent--; },
clear: resetWriter,
trackSymbol: () => { }
};
function writeIndent() {
if (lineStart) {
var indentString = getIndentString(indent);
if (indentString) {
displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space));
}
lineStart = false;
}
}
function writeKind(text: string, kind: SymbolDisplayPartKind) {
writeIndent();
displayParts.push(displayPart(text, kind));
}
function writeSymbol(text: string, symbol: Symbol) {
writeIndent();
displayParts.push(symbolPart(text, symbol));
}
function writeLine() {
displayParts.push(lineBreakPart());
lineStart = true;
}
function resetWriter() {
displayParts = []
lineStart = true;
indent = 0;
}
}
export function symbolPart(text: string, symbol: Symbol) {
return displayPart(text, displayPartKind(symbol), symbol);
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
var flags = symbol.flags;
if (flags & SymbolFlags.Variable) {
return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
}
else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; }
else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; }
else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; }
else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; }
else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.interfaceName; }
else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.enumName; }
else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; }
else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; }
else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; }
else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; }
else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; }
return SymbolDisplayPartKind.text;
}
}
export function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart {
return <SymbolDisplayPart> {
text: text,
kind: SymbolDisplayPartKind[kind]
};
}
export function spacePart() {
return displayPart(" ", SymbolDisplayPartKind.space);
}
export function keywordPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword);
}
export function punctuationPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation);
}
export function operatorPart(kind: SyntaxKind) {
return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator);
}
export function textPart(text: string) {
return displayPart(text, SymbolDisplayPartKind.text);
}
export function lineBreakPart() {
return displayPart("\n", SymbolDisplayPartKind.lineBreak);
}
export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
writeDisplayParts(displayPartWriter);
var result = displayPartWriter.displayParts();
displayPartWriter.clear();
return result;
}
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
return mapToDisplayParts(writer => {
typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
});
}
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
return mapToDisplayParts(writer => {
typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
});
}
export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
return mapToDisplayParts(writer => {
typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
});
}
}