From 76d95248660d1c7bc7f7a64d5113383f4a015712 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 16 Jan 2018 09:53:42 -0800 Subject: [PATCH] Fully deprecate the symbol display builder, reimplement in terms of node builder (#18860) * Remove SymbolWriter, give methods to EmitTextWriter * Unification of writers is done-ish * Make node builder support more flags * Write out mixins like we used to * Accept prototype-free baselines * Use instantiated constraint when building mapped type nodes * Accept better mapped type baselines * Report inaccessible this in node builder * Turns out there was a bug in our codefix, too * Symbol display builder usage falling * Replace signatureToString with a nodeBuilder solution * Replace the last internal usages of the symbol writer * Accept semicolon additions * Accept updated symbol baseline output * Start using node builder for some LS operations * Remove those pesky trailing semicolons on signatures * Get signature printing much closer to old output * Parameter lists should not be indented by default, especially when single-line * Signatures up to snuff * Type quickinfo emit is up to snuff * Start of symbol writer replacement, needs a bit more for full compat * Slightly mor accurate to old behavior * Replicate qualified name type argument output correctly * Bring back the old symbol baselines * Mostly identical to old symbol emit now * Perfectly matches old behavior thus far * Replace another usage of the symbol builder * Another usage removed * Another usage removed * Remove final uses of symbol display builder * Remove implementation and types for unused symbol display builder * Cleanup in the checker * monomorphize new emitter code * Replace emitWithSuffix * Push space character to interface with writer * List emit * Fix lack of usage of emitExpression * writeList, not printList * Remove listy writes and replace with new printer calls * Move ListFormat into types.ts * Remove most new XToString functions in favor of node builder functions * Accept API breaks * Add getSymbolDisplayBuilder polyfill * Accept updated API baseline * Move definition to make diff easier to read * Reinternalize some things * Remove trailign whitespace * Reorder for zero diff * Remove newline * Make shim mor eperfectly imitate old behavior * Style feedback * Rename reset to clear to maintain backcompat with SymbolWriter * Fix quickfix * Keep EmitTextWriter internal * Remove EmitTextWriter from public API * Mimic default name declaration emit fix * Fix tests broken by merge * use isFunctionLike * Cleanup, sync TypeFormat and NodeBuilder flags * Reorder Node initialization so pos and end are first, so a TextRange hidden class is made first to reduce future polymorphism * Use variable instead of ternary * Write helper for emitNodeWithWriter * Emitter cleanup * Cleanup whitespace, comment * Reuse printer * Raise error if display parts writer uses rawWrite * Hide writer parameter through different function instead of overload, rename function in emitter * Make less printer * fix lint --- src/compiler/checker.ts | 1334 ++++++----------- src/compiler/core.ts | 8 +- src/compiler/declarationEmitter.ts | 10 +- src/compiler/emitter.ts | 891 ++++++----- src/compiler/factory.ts | 15 +- src/compiler/sourcemap.ts | 8 +- src/compiler/types.ts | 309 +++- src/compiler/utilities.ts | 37 +- src/compiler/visitor.ts | 4 +- src/services/codefixes/inferFromUsage.ts | 17 +- src/services/services.ts | 3 +- src/services/signatureHelp.ts | 42 +- src/services/symbolDisplay.ts | 18 +- src/services/textChanges.ts | 36 +- src/services/utilities.ts | 20 +- .../reference/api/tsserverlibrary.d.ts | 208 ++- tests/baselines/reference/api/typescript.d.ts | 208 ++- .../reference/commentOnParameter1.js | 12 +- .../reference/commentOnParameter2.js | 10 +- tests/baselines/reference/commentsFunction.js | 6 +- .../reference/declFileConstructors.js | 8 +- .../baselines/reference/declFileFunctions.js | 12 +- tests/baselines/reference/declFileMethods.js | 32 +- .../declarationEmitBindingPatterns.js | 2 +- .../declarationEmitDestructuring2.js | 28 +- .../declarationEmitIndexTypeArray.js | 2 +- ...declarationEmitTypeofDefaultExport.symbols | 4 +- .../reference/deferredLookupTypeResolution.js | 4 +- .../deferredLookupTypeResolution.types | 16 +- .../deferredLookupTypeResolution2.errors.txt | 8 +- .../deferredLookupTypeResolution2.types | 28 +- .../isomorphicMappedTypeInference.js | 4 +- ...ngNamedPropertyOfIllegalCharacters.symbols | 4 +- ...nfoDisplayPartsLiteralLikeNames01.baseline | 6 +- .../reference/recursiveTypeRelations.types | 2 +- .../typeGuardFunctionOfFormThisErrors.js | 2 +- ...odeFixClassImplementInterfaceMappedType.ts | 2 +- 37 files changed, 1750 insertions(+), 1610 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e26b37b61a..7ab50f7be60 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -128,6 +128,11 @@ namespace ts { typeToTypeNode: nodeBuilder.typeToTypeNode, indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration, signatureToSignatureDeclaration: nodeBuilder.signatureToSignatureDeclaration, + symbolToEntityName: nodeBuilder.symbolToEntityName, + symbolToExpression: nodeBuilder.symbolToExpression, + symbolToTypeParameterDeclarations: nodeBuilder.symbolToTypeParameterDeclarations, + symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration, + typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration, getSymbolsInScope: (location, meaning) => { location = getParseTreeNode(location); return location ? getSymbolsInScope(location, meaning) : []; @@ -155,16 +160,31 @@ namespace ts { location = getParseTreeNode(location, isIdentifier); return location ? getPropertySymbolOfDestructuringAssignment(location) : undefined; }, - signatureToString: (signature, enclosingDeclaration?, flags?, kind?) => { + signatureToString: (signature, enclosingDeclaration, flags, kind) => { return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind); }, - typeToString: (type, enclosingDeclaration?, flags?) => { + typeToString: (type, enclosingDeclaration, flags) => { return typeToString(type, getParseTreeNode(enclosingDeclaration), flags); }, - getSymbolDisplayBuilder, - symbolToString: (symbol, enclosingDeclaration?, meaning?) => { - return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning); + symbolToString: (symbol, enclosingDeclaration, meaning, flags) => { + return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags); }, + typePredicateToString: (predicate, enclosingDeclaration, flags) => { + return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags); + }, + writeSignature: (signature, enclosingDeclaration, flags, kind, writer) => { + return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind, writer); + }, + writeType: (type, enclosingDeclaration, flags, writer) => { + return typeToString(type, getParseTreeNode(enclosingDeclaration), flags, writer); + }, + writeSymbol: (symbol, enclosingDeclaration, meaning, flags, writer) => { + return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags, writer); + }, + writeTypePredicate: (predicate, enclosingDeclaration, flags, writer) => { + return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags, writer); + }, + getSymbolDisplayBuilder, // TODO (weswigham): Remove once deprecation process is complete getAugmentedPropertiesOfType, getRootSymbols, getContextualType: node => { @@ -273,6 +293,7 @@ namespace ts { }, getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()), getAccessibleSymbolChain, + getTypePredicateOfSignature, resolveExternalModuleSymbol, }; @@ -520,9 +541,6 @@ namespace ts { const identityRelation = createMap(); const enumRelation = createMap(); - // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. - let _displayBuilder: SymbolDisplayBuilder; - type TypeSystemEntity = Symbol | Type | Signature; const enum TypeSystemPropertyName { @@ -572,6 +590,145 @@ namespace ts { return checker; + /** + * @deprecated + */ + function getSymbolDisplayBuilder(): SymbolDisplayBuilder { + return { + buildTypeDisplay(type, writer, enclosingDeclaration?, flags?) { + typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); + }, + buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags?) { + symbolToString(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); + }, + buildSignatureDisplay(signature, writer, enclosing?, flags?, kind?) { + signatureToString(signature, enclosing, flags, kind, emitTextWriterWrapper(writer)); + }, + buildIndexSignatureDisplay(info, writer, kind, enclosing?, flags?) { + const sig = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, kind, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); + const printer = createPrinter({ removeComments: true }); + printer.writeNode(EmitHint.Unspecified, sig, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildParameterDisplay(symbol, writer, enclosing?, flags?) { + const node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); + const printer = createPrinter({ removeComments: true }); + printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildTypeParameterDisplay(tp, writer, enclosing?, flags?) { + const node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.OmitParameterModifiers, writer); + const printer = createPrinter({ removeComments: true }); + printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildTypePredicateDisplay(predicate, writer, enclosing?, flags?) { + typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); + }, + buildTypeParameterDisplayFromSymbol(symbol, writer, enclosing?, flags?) { + const nodes = nodeBuilder.symbolToTypeParameterDeclarations(symbol, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); + const printer = createPrinter({ removeComments: true }); + printer.writeList(ListFormat.TypeParameters, nodes, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildDisplayForParametersAndDelimiters(thisParameter, parameters, writer, enclosing?, originalFlags?) { + const printer = createPrinter({ removeComments: true }); + const flags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | toNodeBuilderFlags(originalFlags); + const thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; + const params = createNodeArray([...thisParameterArray, ...map(parameters, param => nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags))]); + printer.writeList(ListFormat.CallExpressionArguments, params, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosing?, flags?) { + const printer = createPrinter({ removeComments: true }); + const args = createNodeArray(map(typeParameters, p => nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)))); + printer.writeList(ListFormat.TypeParameters, args, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + }, + buildReturnTypeDisplay(signature, writer, enclosing?, flags?) { + writer.writePunctuation(":"); + writer.writeSpace(" "); + const predicate = getTypePredicateOfSignature(signature); + if (predicate) { + return typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); + } + const node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); + const printer = createPrinter({ removeComments: true }); + printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + } + }; + + function emitTextWriterWrapper(underlying: SymbolWriter): EmitTextWriter { + return { + write: ts.noop, + writeTextOfNode: ts.noop, + writeLine: ts.noop, + increaseIndent() { + return underlying.increaseIndent(); + }, + decreaseIndent() { + return underlying.decreaseIndent(); + }, + getText() { + return ""; + }, + rawWrite: ts.noop, + writeLiteral(s) { + return underlying.writeStringLiteral(s); + }, + getTextPos() { + return 0; + }, + getLine() { + return 0; + }, + getColumn() { + return 0; + }, + getIndent() { + return 0; + }, + isAtStartOfLine() { + return false; + }, + clear() { + return underlying.clear(); + }, + + writeKeyword(text) { + return underlying.writeKeyword(text); + }, + writeOperator(text) { + return underlying.writeOperator(text); + }, + writePunctuation(text) { + return underlying.writePunctuation(text); + }, + writeSpace(text) { + return underlying.writeSpace(text); + }, + writeStringLiteral(text) { + return underlying.writeStringLiteral(text); + }, + writeParameter(text) { + return underlying.writeParameter(text); + }, + writeProperty(text) { + return underlying.writeProperty(text); + }, + writeSymbol(text, symbol) { + return underlying.writeSymbol(text, symbol); + }, + trackSymbol(symbol, enclosing?, meaning?) { + return underlying.trackSymbol && underlying.trackSymbol(symbol, enclosing, meaning); + }, + reportInaccessibleThisError() { + return underlying.reportInaccessibleThisError && underlying.reportInaccessibleThisError(); + }, + reportPrivateInBaseOfClassExpression(name) { + return underlying.reportPrivateInBaseOfClassExpression && underlying.reportPrivateInBaseOfClassExpression(name); + }, + reportInaccessibleUniqueSymbolError() { + return underlying.reportInaccessibleUniqueSymbolError && underlying.reportInaccessibleUniqueSymbolError(); + } + }; + } + } + function getJsxNamespace(): __String { if (!_jsxNamespace) { _jsxNamespace = "React" as __String; @@ -2516,100 +2673,130 @@ namespace ts { }; } - function writeKeyword(writer: SymbolWriter, kind: SyntaxKind) { - writer.writeKeyword(tokenToString(kind)); + function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, writer?: EmitTextWriter): string { + let nodeFlags = NodeBuilderFlags.IgnoreErrors; + if (flags & SymbolFormatFlags.UseOnlyExternalAliasing) { + nodeFlags |= NodeBuilderFlags.UseOnlyExternalAliasing; + } + if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) { + nodeFlags |= NodeBuilderFlags.WriteTypeParametersInQualifiedName; + } + const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; + return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker); + + function symbolToStringWorker(writer: EmitTextWriter) { + const entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); + const printer = createPrinter({ removeComments: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer); + return writer; + } } - function writePunctuation(writer: SymbolWriter, kind: SyntaxKind) { - writer.writePunctuation(tokenToString(kind)); + function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, writer?: EmitTextWriter): string { + return writer ? signatureToStringWorker(writer).getText() : usingSingleLineStringWriter(signatureToStringWorker); + + function signatureToStringWorker(writer: EmitTextWriter) { + let sigOutput: SyntaxKind; + if (flags & TypeFormatFlags.WriteArrowStyleSignature) { + sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType; + } + else { + sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature; + } + const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); + const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, sig, /*sourceFile*/ sourceFile, writer); + return writer; + } } - function writeSpace(writer: SymbolWriter) { - writer.writeSpace(" "); - } - - function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string { - return usingSingleLineStringWriter(writer => { - getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning); - }); - } - - function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string { - return usingSingleLineStringWriter(writer => { - getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, kind); - }); - } - - function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string { - const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); + function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer: EmitTextWriter = createTextWriter("")): string { + const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); Debug.assert(typeNode !== undefined, "should always get typenode"); const options = { removeComments: true }; - const writer = createTextWriter(""); const printer = createPrinter(options); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); const maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100; - if (maxLength && result.length >= maxLength) { + if (maxLength && result && result.length >= maxLength) { return result.substr(0, maxLength - "...".length) + "..."; } return result; + } - function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { - let result = NodeBuilderFlags.None; - if (!flags) { - return result; - } - if (flags & TypeFormatFlags.NoTruncation) { - result |= NodeBuilderFlags.NoTruncation; - } - if (flags & TypeFormatFlags.UseFullyQualifiedType) { - result |= NodeBuilderFlags.UseFullyQualifiedType; - } - if (flags & TypeFormatFlags.SuppressAnyReturnType) { - result |= NodeBuilderFlags.SuppressAnyReturnType; - } - if (flags & TypeFormatFlags.WriteArrayAsGenericType) { - result |= NodeBuilderFlags.WriteArrayAsGenericType; - } - if (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature) { - result |= NodeBuilderFlags.WriteTypeArgumentsOfSignature; - } - - return result; - } + function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { + return flags & TypeFormatFlags.NodeBuilderFlagsMask; } function createNodeBuilder() { return { - typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { + typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); - const context = createNodeBuilderContext(enclosingDeclaration, flags); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); const resultingNode = typeToTypeNodeHelper(type, context); const result = context.encounteredError ? undefined : resultingNode; return result; }, - indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { + indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); - const context = createNodeBuilderContext(enclosingDeclaration, flags); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context); const result = context.encounteredError ? undefined : resultingNode; return result; }, - signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => { + signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); - const context = createNodeBuilderContext(enclosingDeclaration, flags); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); const resultingNode = signatureToSignatureDeclarationHelper(signature, kind, context); const result = context.encounteredError ? undefined : resultingNode; return result; - } + }, + symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); + const resultingNode = symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false); + const result = context.encounteredError ? undefined : resultingNode; + return result; + }, + symbolToExpression: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); + const resultingNode = symbolToExpression(symbol, context, meaning); + const result = context.encounteredError ? undefined : resultingNode; + return result; + }, + symbolToTypeParameterDeclarations: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); + const resultingNode = typeParametersToTypeParameterDeclarations(symbol, context); + const result = context.encounteredError ? undefined : resultingNode; + return result; + }, + symbolToParameterDeclaration: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); + const resultingNode = symbolToParameterDeclaration(symbol, context); + const result = context.encounteredError ? undefined : resultingNode; + return result; + }, + typeParameterToDeclaration: (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); + const resultingNode = typeParameterToDeclaration(parameter, context); + const result = context.encounteredError ? undefined : resultingNode; + return result; + }, }; - function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeBuilderContext { + function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined): NodeBuilderContext { return { enclosingDeclaration, flags, + tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: noop }, encounteredError: false, symbolStack: undefined }; @@ -2656,6 +2843,11 @@ namespace ts { return (type).intrinsicName === "true" ? createTrue() : createFalse(); } if (type.flags & TypeFlags.UniqueESSymbol) { + if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { + if (context.tracker.reportInaccessibleUniqueSymbolError) { + context.tracker.reportInaccessibleUniqueSymbolError(); + } + } return createTypeOperatorNode(SyntaxKind.UniqueKeyword, createKeywordTypeNode(SyntaxKind.SymbolKeyword)); } if (type.flags & TypeFlags.Void) { @@ -2681,6 +2873,9 @@ namespace ts { if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } + if (context.tracker.reportInaccessibleThisError) { + context.tracker.reportInaccessibleThisError(); + } } return createThis(); } @@ -2696,7 +2891,7 @@ namespace ts { // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration)) { + if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { const name = symbolToTypeReferenceName(type.aliasSymbol); const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); return createTypeReferenceNode(name, typeArgumentNodes); @@ -2737,7 +2932,7 @@ namespace ts { Debug.assert(!!(type.flags & TypeFlags.Object)); const readonlyToken = type.declaration && type.declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined; const questionToken = type.declaration && type.declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined; - const typeParameterNode = typeParameterToDeclaration(getTypeParameterFromMappedType(type), context); + const typeParameterNode = typeParameterToDeclaration(getTypeParameterFromMappedType(type), context, getConstraintTypeFromMappedType(type)); const templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); const mappedTypeNode = createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); @@ -2748,7 +2943,7 @@ namespace ts { const symbol = type.symbol; if (symbol) { // Always use 'typeof T' for type of class, enum, and module objects - if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) || + if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return createTypeQueryNodeFromSymbol(symbol, SymbolFlags.Value); @@ -2771,10 +2966,17 @@ namespace ts { if (!context.symbolStack) { context.symbolStack = []; } - context.symbolStack.push(symbol); - const result = createTypeNodeFromObjectType(type); - context.symbolStack.pop(); - return result; + + const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; + if (isConstructorObject) { + return createTypeNodeFromObjectType(type); + } + else { + context.symbolStack.push(symbol); + const result = createTypeNodeFromObjectType(type); + context.symbolStack.pop(); + return result; + } } } else { @@ -2791,7 +2993,7 @@ namespace ts { declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return contains(context.symbolStack, symbol); // it is type of the symbol uses itself recursively + return !!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol); // it is type of the symbol uses itself recursively } } } @@ -2826,7 +3028,7 @@ namespace ts { const members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; const typeLiteralNode = createTypeLiteralNode(members); - return setEmitFlags(typeLiteralNode, EmitFlags.SingleLine); + return setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); } function createTypeQueryNodeFromSymbol(symbol: Symbol, symbolFlags: SymbolFlags) { @@ -2864,6 +3066,11 @@ namespace ts { context.encounteredError = true; return undefined; } + else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && + type.symbol.valueDeclaration && + type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) { + return createAnonymousTypeNode(type); + } else { const outerTypeParameters = type.target.outerTypeParameters; let i = 0; @@ -2965,9 +3172,24 @@ namespace ts { } for (const propertySymbol of properties) { + if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { + if (propertySymbol.flags & SymbolFlags.Prototype) { + continue; + } + if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { + context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); + } + } const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped ? anyType : getTypeOfSymbol(propertySymbol); const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; + if (getCheckFlags(propertySymbol) & CheckFlags.Late) { + const decl = firstOrUndefined(propertySymbol.declarations); + const name = hasLateBindableName(decl) && resolveEntityName(decl.name.expression, SymbolFlags.Value); + if (name && context.tracker.trackSymbol) { + context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value); + } + } const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true); context.enclosingDeclaration = saveEnclosingDeclaration; const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined; @@ -3023,7 +3245,10 @@ namespace ts { /*questionToken*/ undefined, indexerTypeNode, /*initializer*/ undefined); - const typeNode = typeToTypeNodeHelper(indexInfo.type, context); + const typeNode = indexInfo.type ? typeToTypeNodeHelper(indexInfo.type, context) : typeToTypeNodeHelper(anyType, context); + if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { + context.encounteredError = true; + } return createIndexSignature( /*decorators*/ undefined, indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined, @@ -3032,7 +3257,14 @@ namespace ts { } function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { - const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); + let typeParameters: TypeParameterDeclaration[]; + let typeArguments: TypeNode[]; + if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { + typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context)); + } + else { + typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); + } const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter, context)); if (signature.thisParameter) { const thisParameter = symbolToParameterDeclaration(signature.thisParameter, context); @@ -3059,15 +3291,17 @@ namespace ts { else if (!returnTypeNode) { returnTypeNode = createKeywordTypeNode(SyntaxKind.AnyKeyword); } - return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); + return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); } - function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext): TypeParameterDeclaration { + function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintFromTypeParameter(type)): TypeParameterDeclaration { + const savedContextFlags = context.flags; + context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); - const constraint = getConstraintFromTypeParameter(type); const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); + context.flags = savedContextFlags; return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode); } @@ -3081,7 +3315,7 @@ namespace ts { } const parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - const modifiers = parameterDeclaration && parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); + const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && parameterDeclaration && parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); const dotDotDotToken = !parameterDeclaration || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration ? parameterDeclaration.name ? @@ -3114,10 +3348,8 @@ namespace ts { } } - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { - + function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { + context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. let chain: Symbol[]; const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; @@ -3128,42 +3360,11 @@ namespace ts { else { chain = [symbol]; } - - if (expectsIdentifier && chain.length !== 1 - && !context.encounteredError - && !(context.flags & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { - context.encounteredError = true; - } - return createEntityNameFromSymbolChain(chain, chain.length - 1); - - function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName { - Debug.assert(chain && 0 <= index && index < chain.length); - const symbol = chain[index]; - let typeParameterNodes: ReadonlyArray | undefined; - if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index > 0) { - const parentSymbol = chain[index - 1]; - let typeParameters: TypeParameter[]; - if (getCheckFlags(symbol) & CheckFlags.Instantiated) { - typeParameters = getTypeParametersOfClassOrInterface(parentSymbol); - } - else { - const targetSymbol = getTargetSymbol(parentSymbol); - if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { - typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); - } - } - - typeParameterNodes = mapToTypeNodes(typeParameters, context); - } - - const identifier = setEmitFlags(createIdentifier(getNameOfSymbolAsWritten(symbol, context), typeParameterNodes), EmitFlags.NoAsciiEscaping); - - return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; - } + return chain; /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { - let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/ false); + let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); let parentSymbol: Symbol; if (!accessibleSymbolChain || @@ -3195,12 +3396,113 @@ namespace ts { } } } + + function typeParametersToTypeParameterDeclarations(symbol: Symbol, context: NodeBuilderContext) { + let typeParameterNodes: NodeArray | undefined; + const targetSymbol = getTargetSymbol(symbol); + if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { + typeParameterNodes = createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); + } + return typeParameterNodes; + } + + function lookupTypeParameterNodes(chain: Symbol[], index: number, context: NodeBuilderContext) { + Debug.assert(chain && 0 <= index && index < chain.length); + const symbol = chain[index]; + let typeParameterNodes: ReadonlyArray | ReadonlyArray | undefined; + if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { + const parentSymbol = symbol; + const nextSymbol = chain[index + 1]; + if (getCheckFlags(nextSymbol) & CheckFlags.Instantiated) { + const params = getTypeParametersOfClassOrInterface( + parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol + ); + typeParameterNodes = mapToTypeNodes(map(params, (nextSymbol as TransientSymbol).mapper), context); + } + else { + typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context); + } + } + return typeParameterNodes; + } + + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { + const chain = lookupSymbolChain(symbol, context, meaning); + + if (expectsIdentifier && chain.length !== 1 + && !context.encounteredError + && !(context.flags & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { + context.encounteredError = true; + } + return createEntityNameFromSymbolChain(chain, chain.length - 1); + + function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName { + const typeParameterNodes = lookupTypeParameterNodes(chain, index, context); + const symbol = chain[index]; + const symbolName = getNameOfSymbolAsWritten(symbol, context); + const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + identifier.symbol = symbol; + + return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; + } + } + + function symbolToExpression(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { + const chain = lookupSymbolChain(symbol, context, meaning); + + return createExpressionFromSymbolChain(chain, chain.length - 1); + + function createExpressionFromSymbolChain(chain: Symbol[], index: number): Expression { + const typeParameterNodes = lookupTypeParameterNodes(chain, index, context); + const symbol = chain[index]; + + let symbolName = getNameOfSymbolAsWritten(symbol, context); + let firstChar = symbolName.charCodeAt(0); + const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); + if (index === 0 || canUsePropertyAccess) { + const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + identifier.symbol = symbol; + + return index > 0 ? createPropertyAccess(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; + } + else { + if (firstChar === CharacterCodes.openBracket) { + symbolName = symbolName.substring(1, symbolName.length - 1); + firstChar = symbolName.charCodeAt(0); + } + let expression: Expression; + if (isSingleOrDoubleQuote(firstChar)) { + expression = createLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, s => s.substring(1))); + (expression as StringLiteral).singleQuote = firstChar === CharacterCodes.singleQuote; + } + else if (("" + +symbolName) === symbolName) { + expression = createLiteral(+symbolName); + } + if (!expression) { + expression = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + expression.symbol = symbol; + } + return createElementAccess(createExpressionFromSymbolChain(chain, index - 1), expression); + } + } + } } - function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string { - return usingSingleLineStringWriter(writer => { - getSymbolDisplayBuilder().buildTypePredicateDisplay(typePredicate, writer, enclosingDeclaration, flags); - }); + function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer?: EmitTextWriter): string { + return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker); + + function typePredicateToStringWorker(writer: EmitTextWriter) { + const predicate = createTypePredicateNode( + typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier(typePredicate.parameterName) : createThisTypeNode(), + nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName) + ); + const printer = createPrinter({ removeComments: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer); + return writer; + } } function formatUnionTypes(types: Type[]): Type[] { @@ -3262,6 +3564,7 @@ namespace ts { interface NodeBuilderContext { enclosingDeclaration: Node | undefined; flags: NodeBuilderFlags | undefined; + tracker: SymbolTracker | undefined; // State encounteredError: boolean; @@ -3276,6 +3579,9 @@ namespace ts { * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. */ function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string { + if (context && context.flags & NodeBuilderFlags.WriteDefaultSymbolWithoutName && symbol.escapedName === InternalSymbolName.Default) { + return "default"; + } if (symbol.declarations && symbol.declarations.length) { const declaration = symbol.declarations[0]; const name = getNameOfDeclaration(declaration); @@ -3305,781 +3611,6 @@ namespace ts { return symbolName(symbol); } - function getSymbolDisplayBuilder(): SymbolDisplayBuilder { - - /** - * Writes only the name of the symbol out to the writer. Uses the original source text - * for the name of the symbol if it is available to match how the user wrote the name. - */ - function appendSymbolNameOnly(symbol: Symbol, writer: SymbolWriter): void { - writer.writeSymbol(getNameOfSymbolAsWritten(symbol), symbol); - } - - /** - * Writes a property access or element access with the name of the symbol out to the writer. - * Uses the original source text for the name of the symbol if it is available to match how the user wrote the name, - * ensuring that any names written with literals use element accesses. - */ - function appendPropertyOrElementAccessForSymbol(symbol: Symbol, writer: SymbolWriter): void { - const symbolName = symbol.escapedName === InternalSymbolName.Default ? InternalSymbolName.Default : getNameOfSymbolAsWritten(symbol); - const firstChar = symbolName.charCodeAt(0); - const needsElementAccess = !isIdentifierStart(firstChar, languageVersion); - - if (needsElementAccess) { - if (firstChar !== CharacterCodes.openBracket) { - writePunctuation(writer, SyntaxKind.OpenBracketToken); - } - if (isSingleOrDoubleQuote(firstChar)) { - writer.writeStringLiteral(symbolName); - } - else { - writer.writeSymbol(symbolName, symbol); - } - if (firstChar !== CharacterCodes.openBracket) { - writePunctuation(writer, SyntaxKind.CloseBracketToken); - } - } - else { - writePunctuation(writer, SyntaxKind.DotToken); - writer.writeSymbol(symbolName, symbol); - } - } - - /** - * Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope - * Meaning needs to be specified if the enclosing declaration is given - */ - function buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags, typeFlags?: TypeFormatFlags): void { - let parentSymbol: Symbol; - function appendParentTypeArgumentsAndSymbolName(symbol: Symbol): void { - if (parentSymbol) { - // Write type arguments of instantiated class/interface here - if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) { - if (getCheckFlags(symbol) & CheckFlags.Instantiated) { - const params = getTypeParametersOfClassOrInterface(parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol); - buildDisplayForTypeArgumentsAndDelimiters(params, (symbol).mapper, writer, enclosingDeclaration); - } - else { - buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration); - } - } - appendPropertyOrElementAccessForSymbol(symbol, writer); - } - else { - appendSymbolNameOnly(symbol, writer); - } - parentSymbol = symbol; - } - - // Let the writer know we just wrote out a symbol. The declaration emitter writer uses - // this to determine if an import it has previously seen (and not written out) needs - // to be written to the file once the walk of the tree is complete. - // - // NOTE(cyrusn): This approach feels somewhat unfortunate. A simple pass over the tree - // up front (for example, during checking) could determine if we need to emit the imports - // and we could then access that data during declaration emit. - writer.trackSymbol(symbol, enclosingDeclaration, meaning); - /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ - function walkSymbol(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): void { - const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & SymbolFormatFlags.UseOnlyExternalAliasing)); - - if (!accessibleSymbolChain || - needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { - - // Go up and add our parent. - const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); - if (parent) { - walkSymbol(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); - } - } - - if (accessibleSymbolChain) { - for (const accessibleSymbol of accessibleSymbolChain) { - appendParentTypeArgumentsAndSymbolName(accessibleSymbol); - } - } - else if ( - // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. - endOfChain || - // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) - !(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) && - // If a parent symbol is an anonymous type, don't write it. - !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) { - - appendParentTypeArgumentsAndSymbolName(symbol); - } - } - - // Get qualified name if the symbol is not a type parameter - // and there is an enclosing declaration or we specifically - // asked for it - const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; - const typeFormatFlag = TypeFormatFlags.UseFullyQualifiedType & typeFlags; - if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) { - walkSymbol(symbol, meaning, /*endOfChain*/ true); - } - else { - appendParentTypeArgumentsAndSymbolName(symbol); - } - } - - function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { - const globalFlagsToPass = globalFlags & (TypeFormatFlags.WriteOwnNameForAnyLike | TypeFormatFlags.WriteClassExpressionAsTypeLiteral); - let inObjectTypeLiteral = false; - return writeType(type, globalFlags); - - function writeType(type: Type, flags: TypeFormatFlags) { - const nextFlags = flags & ~TypeFormatFlags.InTypeAlias; - // Write undefined/null type as any - if (type.flags & TypeFlags.Intrinsic) { - // Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving - writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type) - ? "any" - : (type).intrinsicName); - } - else if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { - if (inObjectTypeLiteral) { - writer.reportInaccessibleThisError(); - } - writer.writeKeyword("this"); - } - else if (getObjectFlags(type) & ObjectFlags.Reference) { - writeTypeReference(type, nextFlags); - } - else if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { - const parent = getParentOfSymbol(type.symbol); - buildSymbolDisplay(parent, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); - // In a literal enum type with a single member E { A }, E and E.A denote the - // same type. We always display this type simply as E. - if (getDeclaredTypeOfSymbol(parent) !== type) { - writePunctuation(writer, SyntaxKind.DotToken); - appendSymbolNameOnly(type.symbol, writer); - } - } - else if (getObjectFlags(type) & ObjectFlags.ClassOrInterface || type.flags & (TypeFlags.EnumLike | TypeFlags.TypeParameter)) { - // The specified symbol flags need to be reinterpreted as type flags - buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); - } - else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol && - ((flags & TypeFormatFlags.UseAliasDefinedOutsideCurrentScope) || isTypeSymbolAccessible(type.aliasSymbol, enclosingDeclaration))) { - const typeArguments = type.aliasTypeArguments; - writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, length(typeArguments), nextFlags); - } - else if (type.flags & TypeFlags.UnionOrIntersection) { - writeUnionOrIntersectionType(type, nextFlags); - } - else if (getObjectFlags(type) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { - writeAnonymousType(type, nextFlags); - } - else if (type.flags & TypeFlags.UniqueESSymbol) { - if (flags & TypeFormatFlags.AllowUniqueESSymbolType) { - writeKeyword(writer, SyntaxKind.UniqueKeyword); - writeSpace(writer); - } - else { - writer.reportInaccessibleUniqueSymbolError(); - } - writeKeyword(writer, SyntaxKind.SymbolKeyword); - } - else if (type.flags & TypeFlags.StringOrNumberLiteral) { - writer.writeStringLiteral(literalTypeToString(type)); - } - else if (type.flags & TypeFlags.Index) { - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - } - writer.writeKeyword("keyof"); - writeSpace(writer); - writeType((type).type, TypeFormatFlags.InElementType); - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - } - else if (type.flags & TypeFlags.IndexedAccess) { - writeType((type).objectType, TypeFormatFlags.InElementType); - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writeType((type).indexType, TypeFormatFlags.None); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - } - else { - // Should never get here - // { ... } - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writeSpace(writer); - writePunctuation(writer, SyntaxKind.DotDotDotToken); - writeSpace(writer); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - } - } - - - function writeTypeList(types: Type[], delimiter: SyntaxKind) { - for (let i = 0; i < types.length; i++) { - if (i > 0) { - if (delimiter !== SyntaxKind.CommaToken) { - writeSpace(writer); - } - writePunctuation(writer, delimiter); - writeSpace(writer); - } - writeType(types[i], delimiter === SyntaxKind.CommaToken ? TypeFormatFlags.None : TypeFormatFlags.InElementType); - } - } - - function writeSymbolTypeReference(symbol: Symbol, typeArguments: Type[], pos: number, end: number, flags: TypeFormatFlags) { - // Unnamed function expressions and arrow functions have reserved names that we don't want to display - if (symbol.flags & SymbolFlags.Class || !isReservedMemberName(symbol.escapedName)) { - buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags); - } - if (pos < end) { - writePunctuation(writer, SyntaxKind.LessThanToken); - writeType(typeArguments[pos], TypeFormatFlags.InFirstTypeArgument); - pos++; - while (pos < end) { - writePunctuation(writer, SyntaxKind.CommaToken); - writeSpace(writer); - writeType(typeArguments[pos], TypeFormatFlags.None); - pos++; - } - writePunctuation(writer, SyntaxKind.GreaterThanToken); - } - } - - function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) { - const typeArguments = type.typeArguments || emptyArray; - if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) { - writeType(typeArguments[0], TypeFormatFlags.InElementType | TypeFormatFlags.InArrayType); - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - } - else if (type.target.objectFlags & ObjectFlags.Tuple) { - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writeTypeList(type.typeArguments.slice(0, getTypeReferenceArity(type)), SyntaxKind.CommaToken); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - } - else if (flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral && - type.symbol.valueDeclaration && - type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) { - writeAnonymousType(type, flags); - } - else { - // Write the type reference in the format f.g.C where A and B are type arguments - // for outer type parameters, and f and g are the respective declaring containers of those - // type parameters. - const outerTypeParameters = type.target.outerTypeParameters; - let i = 0; - if (outerTypeParameters) { - const length = outerTypeParameters.length; - while (i < length) { - // Find group of type arguments for type parameters with the same declaring container. - const start = i; - const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]); - do { - i++; - } while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); - // When type parameters are their own type arguments for the whole group (i.e. we have - // the default outer type arguments), we don't show the group. - if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) { - writeSymbolTypeReference(parent, typeArguments, start, i, flags); - writePunctuation(writer, SyntaxKind.DotToken); - } - } - } - const typeParameterCount = (type.target.typeParameters || emptyArray).length; - writeSymbolTypeReference(type.symbol, typeArguments, i, typeParameterCount, flags); - } - } - - function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) { - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - } - if (type.flags & TypeFlags.Union) { - writeTypeList(formatUnionTypes(type.types), SyntaxKind.BarToken); - } - else { - writeTypeList(type.types, SyntaxKind.AmpersandToken); - } - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - } - - function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) { - const symbol = type.symbol; - if (symbol) { - // Always use 'typeof T' for type of class, enum, and module objects - if (symbol.flags & SymbolFlags.Class && - !getBaseTypeVariableOfClass(symbol) && - !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral) || - symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule)) { - writeTypeOfSymbol(type.symbol, flags); - } - else if (shouldWriteTypeOfFunctionSymbol()) { - writeTypeOfSymbol(type.symbol, flags); - } - else if (contains(symbolStack, symbol)) { - // If type is an anonymous type literal in a type alias declaration, use type alias name - const typeAlias = getTypeAliasForTypeLiteral(type); - if (typeAlias) { - // The specified symbol flags need to be reinterpreted as type flags - buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags); - } - else { - // Recursive usage, use any - writeKeyword(writer, SyntaxKind.AnyKeyword); - } - } - else { - // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead - // of types allows us to catch circular references to instantiations of the same anonymous type - // However, in case of class expressions, we want to write both the static side and the instance side. - // We skip adding the static side so that the instance side has a chance to be written - // before checking for circular references. - if (!symbolStack) { - symbolStack = []; - } - const isConstructorObject = type.objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; - if (isConstructorObject) { - writeLiteralType(type, flags); - } - else { - symbolStack.push(symbol); - writeLiteralType(type, flags); - symbolStack.pop(); - } - } - } - else { - // Anonymous types with no symbol are never circular - writeLiteralType(type, flags); - } - - function shouldWriteTypeOfFunctionSymbol() { - const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) && // typeof static method - some(symbol.declarations, declaration => hasModifier(declaration, ModifierFlags.Static)); - const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && - (symbol.parent || // is exported function symbol - some(symbol.declarations, declaration => - declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); - if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { - // typeof is allowed only for static/non local functions - return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it - contains(symbolStack, symbol); // it is type of the symbol uses itself recursively - } - } - } - - function writeTypeOfSymbol(symbol: Symbol, typeFormatFlags?: TypeFormatFlags) { - if (typeFormatFlags & TypeFormatFlags.InArrayType) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - } - writeKeyword(writer, SyntaxKind.TypeOfKeyword); - writeSpace(writer); - buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags); - if (typeFormatFlags & TypeFormatFlags.InArrayType) { - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - } - - function writePropertyWithModifiers(prop: Symbol) { - if (isReadonlySymbol(prop)) { - writeKeyword(writer, SyntaxKind.ReadonlyKeyword); - writeSpace(writer); - } - if (getCheckFlags(prop) & CheckFlags.Late) { - const decl = firstOrUndefined(prop.declarations); - const name = hasLateBindableName(decl) && resolveEntityName(decl.name.expression, SymbolFlags.Value); - if (name) { - writer.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value); - } - } - buildSymbolDisplay(prop, writer); - if (prop.flags & SymbolFlags.Optional) { - writePunctuation(writer, SyntaxKind.QuestionToken); - } - } - - function shouldAddParenthesisAroundFunctionType(callSignature: Signature, flags: TypeFormatFlags) { - if (flags & TypeFormatFlags.InElementType) { - return true; - } - else if (flags & TypeFormatFlags.InFirstTypeArgument) { - // Add parenthesis around function type for the first type argument to avoid ambiguity - const typeParameters = callSignature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature) ? - callSignature.target.typeParameters : callSignature.typeParameters; - return typeParameters && typeParameters.length !== 0; - } - return false; - } - - function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) { - if (isGenericMappedType(type)) { - writeMappedType(type); - return; - } - - const resolved = resolveStructuredTypeMembers(type); - if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { - if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - return; - } - - if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { - const parenthesizeSignature = shouldAddParenthesisAroundFunctionType(resolved.callSignatures[0], flags); - if (parenthesizeSignature) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - } - buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack); - if (parenthesizeSignature) { - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - return; - } - if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - } - writeKeyword(writer, SyntaxKind.NewKeyword); - writeSpace(writer); - buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack); - if (flags & TypeFormatFlags.InElementType) { - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - return; - } - } - - const saveInObjectTypeLiteral = inObjectTypeLiteral; - inObjectTypeLiteral = true; - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writer.writeLine(); - writer.increaseIndent(); - writeObjectLiteralType(resolved); - writer.decreaseIndent(); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - inObjectTypeLiteral = saveInObjectTypeLiteral; - } - - function writeObjectLiteralType(resolved: ResolvedType) { - for (const signature of resolved.callSignatures) { - buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - for (const signature of resolved.constructSignatures) { - buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - const stringIndexInfo = resolved.objectFlags & ObjectFlags.ReverseMapped && resolved.stringIndexInfo ? - createIndexInfo(anyType, resolved.stringIndexInfo.isReadonly, resolved.stringIndexInfo.declaration) : - resolved.stringIndexInfo; - buildIndexSignatureDisplay(stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack); - buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack); - for (const p of resolved.properties) { - if (globalFlags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral) { - if (p.flags & SymbolFlags.Prototype) { - continue; - } - if (getDeclarationModifierFlagsFromSymbol(p) & (ModifierFlags.Private | ModifierFlags.Protected)) { - writer.reportPrivateInBaseOfClassExpression(symbolName(p)); - } - } - const t = getCheckFlags(p) & CheckFlags.ReverseMapped ? anyType : getTypeOfSymbol(p); - if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) { - const signatures = getSignaturesOfType(t, SignatureKind.Call); - for (const signature of signatures) { - writePropertyWithModifiers(p); - buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - } - else { - writePropertyWithModifiers(p); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeType(t, globalFlags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - } - } - - function writeMappedType(type: MappedType) { - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writer.writeLine(); - writer.increaseIndent(); - if (type.declaration.readonlyToken) { - writeKeyword(writer, SyntaxKind.ReadonlyKeyword); - writeSpace(writer); - } - writePunctuation(writer, SyntaxKind.OpenBracketToken); - appendSymbolNameOnly(getTypeParameterFromMappedType(type).symbol, writer); - writeSpace(writer); - writeKeyword(writer, SyntaxKind.InKeyword); - writeSpace(writer); - writeType(getConstraintTypeFromMappedType(type), TypeFormatFlags.None); - writePunctuation(writer, SyntaxKind.CloseBracketToken); - if (type.declaration.questionToken) { - writePunctuation(writer, SyntaxKind.QuestionToken); - } - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - writeType(getTemplateTypeFromMappedType(type), TypeFormatFlags.None); - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - writer.decreaseIndent(); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - } - } - - function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags) { - const targetSymbol = getTargetSymbol(symbol); - if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface || targetSymbol.flags & SymbolFlags.TypeAlias) { - buildDisplayForTypeParametersAndDelimiters(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), writer, enclosingDeclaration, flags); - } - } - - function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - appendSymbolNameOnly(tp.symbol, writer); - const constraint = getConstraintOfTypeParameter(tp); - if (constraint) { - writeSpace(writer); - writeKeyword(writer, SyntaxKind.ExtendsKeyword); - writeSpace(writer); - buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack); - } - const defaultType = getDefaultFromTypeParameter(tp); - if (defaultType) { - writeSpace(writer); - writePunctuation(writer, SyntaxKind.EqualsToken); - writeSpace(writer); - buildTypeDisplay(defaultType, writer, enclosingDeclaration, flags, symbolStack); - } - } - - function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - const parameterNode = p.valueDeclaration; - - if (parameterNode ? isRestParameter(parameterNode) : isTransientSymbol(p) && p.isRestParameter) { - writePunctuation(writer, SyntaxKind.DotDotDotToken); - } - if (parameterNode && isBindingPattern(parameterNode.name)) { - buildBindingPatternDisplay(parameterNode.name, writer, enclosingDeclaration, flags, symbolStack); - } - else { - appendSymbolNameOnly(p, writer); - } - if (parameterNode && isOptionalParameter(parameterNode)) { - writePunctuation(writer, SyntaxKind.QuestionToken); - } - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - - let type = getTypeOfSymbol(p); - if (parameterNode && isRequiredInitializedParameter(parameterNode)) { - type = getOptionalType(type); - } - buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack); - } - - function buildBindingPatternDisplay(bindingPattern: BindingPattern, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - // We have to explicitly emit square bracket and bracket because these tokens are not stored inside the node. - if (bindingPattern.kind === SyntaxKind.ObjectBindingPattern) { - writePunctuation(writer, SyntaxKind.OpenBraceToken); - buildDisplayForCommaSeparatedList(bindingPattern.elements, writer, e => buildBindingElementDisplay(e, writer, enclosingDeclaration, flags, symbolStack)); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - } - else if (bindingPattern.kind === SyntaxKind.ArrayBindingPattern) { - writePunctuation(writer, SyntaxKind.OpenBracketToken); - const elements = bindingPattern.elements; - buildDisplayForCommaSeparatedList(elements, writer, e => buildBindingElementDisplay(e, writer, enclosingDeclaration, flags, symbolStack)); - if (elements && elements.hasTrailingComma) { - writePunctuation(writer, SyntaxKind.CommaToken); - } - writePunctuation(writer, SyntaxKind.CloseBracketToken); - } - } - - function buildBindingElementDisplay(bindingElement: ArrayBindingElement, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - if (isOmittedExpression(bindingElement)) { - return; - } - Debug.assert(bindingElement.kind === SyntaxKind.BindingElement); - if (bindingElement.propertyName) { - writer.writeProperty(getTextOfNode(bindingElement.propertyName)); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - } - if (isBindingPattern(bindingElement.name)) { - buildBindingPatternDisplay(bindingElement.name, writer, enclosingDeclaration, flags, symbolStack); - } - else { - if (bindingElement.dotDotDotToken) { - writePunctuation(writer, SyntaxKind.DotDotDotToken); - } - appendSymbolNameOnly(bindingElement.symbol, writer); - } - } - - function buildDisplayForTypeParametersAndDelimiters(typeParameters: ReadonlyArray, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - if (typeParameters && typeParameters.length) { - writePunctuation(writer, SyntaxKind.LessThanToken); - buildDisplayForCommaSeparatedList(typeParameters, writer, p => buildTypeParameterDisplay(p, writer, enclosingDeclaration, flags, symbolStack)); - writePunctuation(writer, SyntaxKind.GreaterThanToken); - } - } - - function buildDisplayForCommaSeparatedList(list: ReadonlyArray, writer: SymbolWriter, action: (item: T) => void) { - for (let i = 0; i < list.length; i++) { - if (i > 0) { - writePunctuation(writer, SyntaxKind.CommaToken); - writeSpace(writer); - } - action(list[i]); - } - } - - function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: ReadonlyArray, mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node) { - if (typeParameters && typeParameters.length) { - writePunctuation(writer, SyntaxKind.LessThanToken); - let flags = TypeFormatFlags.InFirstTypeArgument; - for (let i = 0; i < typeParameters.length; i++) { - if (i > 0) { - writePunctuation(writer, SyntaxKind.CommaToken); - writeSpace(writer); - flags = TypeFormatFlags.None; - } - buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, flags); - } - writePunctuation(writer, SyntaxKind.GreaterThanToken); - } - } - - function buildDisplayForParametersAndDelimiters(thisParameter: Symbol | undefined, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - writePunctuation(writer, SyntaxKind.OpenParenToken); - if (thisParameter) { - buildParameterDisplay(thisParameter, writer, enclosingDeclaration, flags, symbolStack); - } - for (let i = 0; i < parameters.length; i++) { - if (i > 0 || thisParameter) { - writePunctuation(writer, SyntaxKind.CommaToken); - writeSpace(writer); - } - buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, symbolStack); - } - writePunctuation(writer, SyntaxKind.CloseParenToken); - } - - function buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]): void { - if (isIdentifierTypePredicate(predicate)) { - writer.writeParameter(predicate.parameterName); - } - else { - writeKeyword(writer, SyntaxKind.ThisKeyword); - } - writeSpace(writer); - writeKeyword(writer, SyntaxKind.IsKeyword); - writeSpace(writer); - buildTypeDisplay(predicate.type, writer, enclosingDeclaration, flags, symbolStack); - } - - function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - const returnType = getReturnTypeOfSignature(signature); - if (flags & TypeFormatFlags.SuppressAnyReturnType && isTypeAny(returnType)) { - return; - } - - if (flags & TypeFormatFlags.WriteArrowStyleSignature) { - writeSpace(writer); - writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken); - } - else { - writePunctuation(writer, SyntaxKind.ColonToken); - } - writeSpace(writer); - - const typePredicate = getTypePredicateOfSignature(signature); - if (typePredicate) { - buildTypePredicateDisplay(typePredicate, writer, enclosingDeclaration, flags, symbolStack); - } - else { - buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack); - } - } - - function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, symbolStack?: Symbol[]) { - if (kind === SignatureKind.Construct) { - writeKeyword(writer, SyntaxKind.NewKeyword); - writeSpace(writer); - } - - if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) { - // Instantiated signature, write type arguments instead - // This is achieved by passing in the mapper separately - buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration); - } - else { - buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack); - } - - buildDisplayForParametersAndDelimiters(signature.thisParameter, signature.parameters, writer, enclosingDeclaration, flags, symbolStack); - - buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack); - } - - function buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { - if (info) { - if (info.isReadonly) { - writeKeyword(writer, SyntaxKind.ReadonlyKeyword); - writeSpace(writer); - } - writePunctuation(writer, SyntaxKind.OpenBracketToken); - writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x"); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - switch (kind) { - case IndexKind.Number: - writeKeyword(writer, SyntaxKind.NumberKeyword); - break; - case IndexKind.String: - writeKeyword(writer, SyntaxKind.StringKeyword); - break; - } - - writePunctuation(writer, SyntaxKind.CloseBracketToken); - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - if (info.type) { - buildTypeDisplay(info.type, writer, enclosingDeclaration, globalFlags, symbolStack); - } - else { - writeKeyword(writer, SyntaxKind.AnyKeyword); - } - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - } - - return _displayBuilder || (_displayBuilder = { - buildSymbolDisplay, - buildTypeDisplay, - buildTypeParameterDisplay, - buildTypePredicateDisplay, - buildParameterDisplay, - buildDisplayForParametersAndDelimiters, - buildDisplayForTypeParametersAndDelimiters, - buildTypeParameterDisplayFromSymbol, - buildSignatureDisplay, - buildIndexSignatureDisplay, - buildReturnTypeDisplay - }); - } - function isDeclarationVisible(node: Declaration): boolean { if (node) { const links = getNodeLinks(node); @@ -25348,7 +24879,7 @@ namespace ts { } } - function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) { + function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter) { // Get type of the symbol if this is the valid symbol otherwise get type at location const symbol = getSymbolOfNode(declaration); let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) @@ -25361,18 +24892,17 @@ namespace ts { if (flags & TypeFormatFlags.AddUndefined) { type = getOptionalType(type); } - - getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + typeToString(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); } - function writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) { + function writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter) { const signature = getSignatureFromDeclaration(signatureDeclaration); - getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags); + typeToString(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); } - function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) { + function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter) { const type = getWidenedType(getRegularTypeOfExpression(expr)); - getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + typeToString(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); } function hasGlobalName(name: string): boolean { @@ -25420,7 +24950,7 @@ namespace ts { return false; } - function writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: SymbolWriter) { + function writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter) { const type = getTypeOfSymbol(getSymbolOfNode(node)); writer.writeStringLiteral(literalTypeToString(type)); } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 24c2153c582..0faabbda2a0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2771,10 +2771,10 @@ namespace ts { function Signature() {} // tslint:disable-line no-empty function Node(this: Node, kind: SyntaxKind, pos: number, end: number) { - this.id = 0; - this.kind = kind; this.pos = pos; this.end = end; + this.kind = kind; + this.id = 0; this.flags = NodeFlags.None; this.modifierFlagsCache = ModifierFlags.None; this.transformFlags = TransformFlags.None; @@ -3046,6 +3046,10 @@ namespace ts { return (arg: T) => f(arg) && g(arg); } + export function or(f: (arg: T) => boolean, g: (arg: T) => boolean) { + return (arg: T) => f(arg) || g(arg); + } + export function assertTypeIsNever(_: never): void { } // tslint:disable-line no-empty export interface FileAndDirectoryExistence { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index b85c79e775c..f37ae497f84 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -20,14 +20,14 @@ namespace ts { type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic; - interface EmitTextWriterWithSymbolWriter extends EmitTextWriter, SymbolWriter { + interface EmitTextWriterWithSymbolWriter extends EmitTextWriter { getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic; } interface SymbolAccessibilityDiagnostic { errorNode: Node; diagnosticMessage: DiagnosticMessage; - typeName?: DeclarationName; + typeName?: DeclarationName | QualifiedName; } export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] { @@ -358,7 +358,7 @@ namespace ts { } else { errorNameNode = declaration.name; - const format = TypeFormatFlags.UseTypeOfFunction | + const format = TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteDefaultSymbolWithoutName | TypeFormatFlags.WriteClassExpressionAsTypeLiteral | (shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0); resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer); @@ -378,7 +378,7 @@ namespace ts { resolver.writeReturnTypeOfSignatureDeclaration( signature, enclosingDeclaration, - TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral, + TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral | TypeFormatFlags.WriteDefaultSymbolWithoutName, writer); errorNameNode = undefined; } @@ -643,7 +643,7 @@ namespace ts { resolver.writeTypeOfExpression( expr, enclosingDeclaration, - TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral, + TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral | TypeFormatFlags.WriteDefaultSymbolWithoutName, writer); write(";"); writeLine(); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index aee8c98db0d..8a1de17826c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -5,7 +5,6 @@ /// namespace ts { - const delimiters = createDelimiterMap(); const brackets = createBracketsMap(); /*@internal*/ @@ -200,7 +199,7 @@ namespace ts { // Reset state sourceMap.reset(); - writer.reset(); + writer.clear(); currentSourceFile = undefined; bundledHelpers = undefined; @@ -292,16 +291,27 @@ namespace ts { let tempFlags: TempFlags; // TempFlags for the current name generation scope. let writer: EmitTextWriter; let ownWriter: EmitTextWriter; + let write = writeBase; + let commitPendingSemicolon: typeof commitPendingSemicolonInternal = noop; + let writeSemicolon: typeof writeSemicolonInternal = writeSemicolonInternal; + let pendingSemicolon = false; + if (printerOptions.omitTrailingSemicolon) { + commitPendingSemicolon = commitPendingSemicolonInternal; + writeSemicolon = deferWriteSemicolon; + } + const syntheticParent: TextRange = { pos: -1, end: -1 }; reset(); return { // public API printNode, + printList, printFile, printBundle, // internal API writeNode, + writeList, writeFile, writeBundle }; @@ -326,6 +336,11 @@ namespace ts { return endPrint(); } + function printList(format: ListFormat, nodes: NodeArray, sourceFile: SourceFile) { + writeList(format, nodes, sourceFile, beginPrint()); + return endPrint(); + } + function printBundle(bundle: Bundle): string { writeBundle(bundle, beginPrint()); return endPrint(); @@ -349,6 +364,17 @@ namespace ts { writer = previousWriter; } + function writeList(format: ListFormat, nodes: NodeArray, sourceFile: SourceFile | undefined, output: EmitTextWriter) { + const previousWriter = writer; + setWriter(output); + if (sourceFile) { + setSourceFile(sourceFile); + } + emitList(syntheticParent, nodes, format); + reset(); + writer = previousWriter; + } + function writeBundle(bundle: Bundle, output: EmitTextWriter) { const previousWriter = writer; setWriter(output); @@ -378,7 +404,7 @@ namespace ts { function endPrint() { const text = ownWriter.getText(); - ownWriter.reset(); + ownWriter.clear(); return text; } @@ -482,7 +508,9 @@ namespace ts { function emitMappedTypeParameter(node: TypeParameterDeclaration): void { emit(node.name); - write(" in "); + writeSpace(); + writeKeyword("in"); + writeSpace(); emit(node.constraint); } @@ -493,7 +521,7 @@ namespace ts { // Strict mode reserved words // Contextual keywords if (isKeyword(kind)) { - writeTokenNode(node); + writeTokenNode(node, writeKeyword); return; } @@ -752,7 +780,7 @@ namespace ts { } if (isToken(node)) { - writeTokenNode(node); + writeTokenNode(node, writePunctuation); return; } } @@ -780,7 +808,7 @@ namespace ts { case SyntaxKind.TrueKeyword: case SyntaxKind.ThisKeyword: case SyntaxKind.ImportKeyword: - writeTokenNode(node); + writeTokenNode(node, writeKeyword); return; // Expressions @@ -885,10 +913,11 @@ namespace ts { const text = getLiteralTextOfNode(node); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { - writer.writeLiteral(text); + writeLiteral(text); } else { - write(text); + // Quick info expects all literals to be called with writeStringLiteral, as there's no specific type for numberLiterals + writeStringLiteral(text); } } @@ -897,8 +926,9 @@ namespace ts { // function emitIdentifier(node: Identifier) { - write(getTextOfNode(node, /*includeTrivia*/ false)); - emitTypeArguments(node, node.typeArguments); + const writeText = node.symbol ? writeSymbol : write; + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } // @@ -907,7 +937,7 @@ namespace ts { function emitQualifiedName(node: QualifiedName) { emitEntityName(node.left); - write("."); + writePunctuation("."); emit(node.right); } @@ -921,9 +951,9 @@ namespace ts { } function emitComputedPropertyName(node: ComputedPropertyName) { - write("["); + writePunctuation("["); emitExpression(node.expression); - write("]"); + writePunctuation("]"); } // @@ -932,8 +962,18 @@ namespace ts { function emitTypeParameter(node: TypeParameterDeclaration) { emit(node.name); - emitWithPrefix(" extends ", node.constraint); - emitWithPrefix(" = ", node.default); + if (node.constraint) { + writeSpace(); + writeKeyword("extends"); + writeSpace(); + emit(node.constraint); + } + if (node.default) { + writeSpace(); + writeOperator("="); + writeSpace(); + emit(node.default); + } } function emitParameter(node: ParameterDeclaration) { @@ -941,20 +981,20 @@ namespace ts { emitModifiers(node, node.modifiers); emitIfPresent(node.dotDotDotToken); if (node.name) { - emit(node.name); + emitNodeWithWriter(node.name, writeParameter); } emitIfPresent(node.questionToken); if (node.parent && node.parent.kind === SyntaxKind.JSDocFunctionType && !node.name) { emit(node.type); } else { - emitWithPrefix(": ", node.type); + emitTypeAnnotation(node.type); } - emitExpressionWithPrefix(" = ", node.initializer); + emitInitializer(node.initializer); } function emitDecorator(decorator: Decorator) { - write("@"); + writePunctuation("@"); emitExpression(decorator.expression); } @@ -965,10 +1005,10 @@ namespace ts { function emitPropertySignature(node: PropertySignature) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - emit(node.name); + emitNodeWithWriter(node.name, writeProperty); emitIfPresent(node.questionToken); - emitWithPrefix(": ", node.type); - write(";"); + emitTypeAnnotation(node.type); + writeSemicolon(); } function emitPropertyDeclaration(node: PropertyDeclaration) { @@ -976,9 +1016,9 @@ namespace ts { emitModifiers(node, node.modifiers); emit(node.name); emitIfPresent(node.questionToken); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); - write(";"); + emitTypeAnnotation(node.type); + emitInitializer(node.initializer); + writeSemicolon(); } function emitMethodSignature(node: MethodSignature) { @@ -988,8 +1028,8 @@ namespace ts { emitIfPresent(node.questionToken); emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); + emitTypeAnnotation(node.type); + writeSemicolon(); } function emitMethodDeclaration(node: MethodDeclaration) { @@ -1003,14 +1043,15 @@ namespace ts { function emitConstructor(node: ConstructorDeclaration) { emitModifiers(node, node.modifiers); - write("constructor"); + writeKeyword("constructor"); emitSignatureAndBody(node, emitSignatureHead); } function emitAccessorDeclaration(node: AccessorDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); + writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set"); + writeSpace(); emit(node.name); emitSignatureAndBody(node, emitSignatureHead); } @@ -1020,30 +1061,31 @@ namespace ts { emitModifiers(node, node.modifiers); emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); + emitTypeAnnotation(node.type); + writeSemicolon(); } function emitConstructSignature(node: ConstructSignatureDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write("new "); + writeKeyword("new"); + writeSpace(); emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); + emitTypeAnnotation(node.type); + writeSemicolon(); } function emitIndexSignature(node: IndexSignatureDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emitParametersForIndexSignature(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); + emitTypeAnnotation(node.type); + writeSemicolon(); } function emitSemicolonClassElement() { - write(";"); + writeSemicolon(); } // @@ -1052,7 +1094,9 @@ namespace ts { function emitTypePredicate(node: TypePredicateNode) { emit(node.parameterName); - write(" is "); + writeSpace(); + writeKeyword("is"); + writeSpace(); emit(node.type); } @@ -1064,7 +1108,9 @@ namespace ts { function emitFunctionType(node: FunctionTypeNode) { emitTypeParameters(node, node.typeParameters); emitParametersForArrow(node, node.parameters); - write(" => "); + writeSpace(); + writePunctuation("=>"); + writeSpace(); emit(node.type); } @@ -1092,28 +1138,33 @@ namespace ts { } function emitConstructorType(node: ConstructorTypeNode) { - write("new "); + writeKeyword("new"); + writeSpace(); emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); - write(" => "); + writeSpace(); + writePunctuation("=>"); + writeSpace(); emit(node.type); } function emitTypeQuery(node: TypeQueryNode) { - write("typeof "); + writeKeyword("typeof"); + writeSpace(); emit(node.exprName); } function emitTypeLiteral(node: TypeLiteralNode) { - write("{"); + writePunctuation("{"); const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers; emitList(node, node.members, flags | ListFormat.NoSpaceIfEmpty); - write("}"); + writePunctuation("}"); } function emitArrayType(node: ArrayTypeNode) { emit(node.elementType); - write("[]"); + writePunctuation("["); + writePunctuation("]"); } function emitJSDocVariadicType(node: JSDocVariadicType) { @@ -1122,9 +1173,9 @@ namespace ts { } function emitTupleType(node: TupleTypeNode) { - write("["); + writePunctuation("["); emitList(node, node.elementTypes, ListFormat.TupleTypeElements); - write("]"); + writePunctuation("]"); } function emitUnionType(node: UnionTypeNode) { @@ -1136,33 +1187,33 @@ namespace ts { } function emitParenthesizedType(node: ParenthesizedTypeNode) { - write("("); + writePunctuation("("); emit(node.type); - write(")"); + writePunctuation(")"); } function emitThisType() { - write("this"); + writeKeyword("this"); } function emitTypeOperator(node: TypeOperatorNode) { - writeTokenText(node.operator); - write(" "); + writeTokenText(node.operator, writeKeyword); + writeSpace(); emit(node.type); } function emitIndexedAccessType(node: IndexedAccessTypeNode) { emit(node.objectType); - write("["); + writePunctuation("["); emit(node.indexType); - write("]"); + writePunctuation("]"); } function emitMappedType(node: MappedTypeNode) { const emitFlags = getEmitFlags(node); - write("{"); + writePunctuation("{"); if (emitFlags & EmitFlags.SingleLine) { - write(" "); + writeSpace(); } else { writeLine(); @@ -1170,25 +1221,26 @@ namespace ts { } if (node.readonlyToken) { emit(node.readonlyToken); - write(" "); + writeSpace(); } - write("["); + writePunctuation("["); pipelineEmitWithNotification(EmitHint.MappedTypeParameter, node.typeParameter); - write("]"); + writePunctuation("]"); emitIfPresent(node.questionToken); - write(": "); + writePunctuation(":"); + writeSpace(); emit(node.type); - write(";"); + writeSemicolon(); if (emitFlags & EmitFlags.SingleLine) { - write(" "); + writeSpace(); } else { writeLine(); decreaseIndent(); } - write("}"); + writePunctuation("}"); } function emitLiteralType(node: LiteralTypeNode) { @@ -1200,22 +1252,26 @@ namespace ts { // function emitObjectBindingPattern(node: ObjectBindingPattern) { - write("{"); + writePunctuation("{"); emitList(node, node.elements, ListFormat.ObjectBindingPatternElements); - write("}"); + writePunctuation("}"); } function emitArrayBindingPattern(node: ArrayBindingPattern) { - write("["); + writePunctuation("["); emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); - write("]"); + writePunctuation("]"); } function emitBindingElement(node: BindingElement) { - emitWithSuffix(node.propertyName, ": "); + if (node.propertyName) { + emit(node.propertyName); + writePunctuation(":"); + writeSpace(); + } emitIfPresent(node.dotDotDotToken); emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); + emitInitializer(node.initializer); } // @@ -1260,7 +1316,7 @@ namespace ts { increaseIndentIf(indentBeforeDot); const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); - write(shouldEmitDotDot ? ".." : "."); + writePunctuation(shouldEmitDotDot ? ".." : "."); increaseIndentIf(indentAfterDot); emit(node.name); @@ -1289,9 +1345,9 @@ namespace ts { function emitElementAccessExpression(node: ElementAccessExpression) { emitExpression(node.expression); - write("["); + writePunctuation("["); emitExpression(node.argumentExpression); - write("]"); + writePunctuation("]"); } function emitCallExpression(node: CallExpression) { @@ -1301,7 +1357,8 @@ namespace ts { } function emitNewExpression(node: NewExpression) { - write("new "); + writeKeyword("new"); + writeSpace(); emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); @@ -1309,21 +1366,21 @@ namespace ts { function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { emitExpression(node.tag); - write(" "); + writeSpace(); emitExpression(node.template); } function emitTypeAssertionExpression(node: TypeAssertion) { - write("<"); + writePunctuation("<"); emit(node.type); - write(">"); + writePunctuation(">"); emitExpression(node.expression); } function emitParenthesizedExpression(node: ParenthesizedExpression) { - write("("); + writePunctuation("("); emitExpression(node.expression); - write(")"); + writePunctuation(")"); } function emitFunctionExpression(node: FunctionExpression) { @@ -1339,35 +1396,39 @@ namespace ts { function emitArrowFunctionHead(node: ArrowFunction) { emitTypeParameters(node, node.typeParameters); emitParametersForArrow(node, node.parameters); - emitWithPrefix(": ", node.type); - write(" "); + emitTypeAnnotation(node.type); + writeSpace(); emit(node.equalsGreaterThanToken); } function emitDeleteExpression(node: DeleteExpression) { - write("delete "); + writeKeyword("delete"); + writeSpace(); emitExpression(node.expression); } function emitTypeOfExpression(node: TypeOfExpression) { - write("typeof "); + writeKeyword("typeof"); + writeSpace(); emitExpression(node.expression); } function emitVoidExpression(node: VoidExpression) { - write("void "); + writeKeyword("void"); + writeSpace(); emitExpression(node.expression); } function emitAwaitExpression(node: AwaitExpression) { - write("await "); + writeKeyword("await"); + writeSpace(); emitExpression(node.expression); } function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { - writeTokenText(node.operator); + writeTokenText(node.operator, writeOperator); if (shouldEmitWhitespaceBeforeOperand(node)) { - write(" "); + writeSpace(); } emitExpression(node.operand); } @@ -1393,7 +1454,7 @@ namespace ts { function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { emitExpression(node.operand); - writeTokenText(node.operator); + writeTokenText(node.operator, writeOperator); } function emitBinaryExpression(node: BinaryExpression) { @@ -1404,7 +1465,7 @@ namespace ts { emitExpression(node.left); increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); emitLeadingCommentsOfPosition(node.operatorToken.pos); - writeTokenNode(node.operatorToken); + writeTokenNode(node.operatorToken, writeOperator); emitTrailingCommentsOfPosition(node.operatorToken.end, /*prefixSpace*/ true); // Binary operators should have a space before the comment starts increaseIndentIf(indentAfterOperator, " "); emitExpression(node.right); @@ -1437,13 +1498,13 @@ namespace ts { } function emitYieldExpression(node: YieldExpression) { - write("yield"); + writeKeyword("yield"); emit(node.asteriskToken); - emitExpressionWithPrefix(" ", node.expression); + emitExpressionWithLeadingSpace(node.expression); } function emitSpreadExpression(node: SpreadElement) { - write("..."); + writePunctuation("..."); emitExpression(node.expression); } @@ -1459,19 +1520,21 @@ namespace ts { function emitAsExpression(node: AsExpression) { emitExpression(node.expression); if (node.type) { - write(" as "); + writeSpace(); + writeKeyword("as"); + writeSpace(); emit(node.type); } } function emitNonNullExpression(node: NonNullExpression) { emitExpression(node.expression); - write("!"); + writeOperator("!"); } function emitMetaProperty(node: MetaProperty) { - writeToken(node.keywordToken, node.pos); - write("."); + writeToken(node.keywordToken, node.pos, writePunctuation); + writePunctuation("."); emit(node.name); } @@ -1489,13 +1552,13 @@ namespace ts { // function emitBlock(node: Block) { - writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); + writeToken(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node); emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node)); // We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted increaseIndent(); emitLeadingCommentsOfPosition(node.statements.end); decreaseIndent(); - writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); + writeToken(SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node); } function emitBlockStatements(node: BlockLike, forceSingleLine: boolean) { @@ -1506,30 +1569,30 @@ namespace ts { function emitVariableStatement(node: VariableStatement) { emitModifiers(node, node.modifiers); emit(node.declarationList); - write(";"); + writeSemicolon(); } function emitEmptyStatement() { - write(";"); + writeSemicolon(); } function emitExpressionStatement(node: ExpressionStatement) { emitExpression(node.expression); - write(";"); + writeSemicolon(); } function emitIfStatement(node: IfStatement) { - const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, node); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, node); + const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, writeKeyword, node); + writeSpace(); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end, node); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.thenStatement); if (node.elseStatement) { writeLineOrSpace(node); - writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, node); + writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, writeKeyword, node); if (node.elseStatement.kind === SyntaxKind.IfStatement) { - write(" "); + writeSpace(); emit(node.elseStatement); } else { @@ -1539,60 +1602,68 @@ namespace ts { } function emitDoStatement(node: DoStatement) { - write("do"); + writeKeyword("do"); emitEmbeddedStatement(node, node.statement); if (isBlock(node.statement)) { - write(" "); + writeSpace(); } else { writeLineOrSpace(node); } - write("while ("); + writeKeyword("while"); + writeSpace(); + writePunctuation("("); emitExpression(node.expression); - write(");"); + writePunctuation(");"); } function emitWhileStatement(node: WhileStatement) { - write("while ("); + writeKeyword("while"); + writeSpace(); + writePunctuation("("); emitExpression(node.expression); - write(")"); + writePunctuation(")"); emitEmbeddedStatement(node, node.statement); } function emitForStatement(node: ForStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, /*contextNode*/ node); + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword); + writeSpace(); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node); emitForBinding(node.initializer); - write(";"); - emitExpressionWithPrefix(" ", node.condition); - write(";"); - emitExpressionWithPrefix(" ", node.incrementor); - write(")"); + writeSemicolon(); + emitExpressionWithLeadingSpace(node.condition); + writeSemicolon(); + emitExpressionWithLeadingSpace(node.incrementor); + writePunctuation(")"); emitEmbeddedStatement(node, node.statement); } function emitForInStatement(node: ForInStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword); + writeSpace(); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation); emitForBinding(node.initializer); - write(" in "); + writeSpace(); + writeKeyword("in"); + writeSpace(); emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation); emitEmbeddedStatement(node, node.statement); } function emitForOfStatement(node: ForOfStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - emitWithSuffix(node.awaitModifier, " "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword); + writeSpace(); + emitWithTrailingSpace(node.awaitModifier); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation); emitForBinding(node.initializer); - write(" of "); + writeSpace(); + writeKeyword("of"); + writeSpace(); emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation); emitEmbeddedStatement(node, node.statement); } @@ -1608,23 +1679,23 @@ namespace ts { } function emitContinueStatement(node: ContinueStatement) { - writeToken(SyntaxKind.ContinueKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); + writeToken(SyntaxKind.ContinueKeyword, node.pos, writeKeyword); + emitWithLeadingSpace(node.label); + writeSemicolon(); } function emitBreakStatement(node: BreakStatement) { - writeToken(SyntaxKind.BreakKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); + writeToken(SyntaxKind.BreakKeyword, node.pos, writeKeyword); + emitWithLeadingSpace(node.label); + writeSemicolon(); } - function emitTokenWithComment(token: SyntaxKind, pos: number, contextNode?: Node) { + function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node) { const node = contextNode && getParseTreeNode(contextNode); if (node && node.kind === contextNode.kind) { pos = skipTrivia(currentSourceFile.text, pos); } - pos = writeToken(token, pos, /*contextNode*/ contextNode); + pos = writeToken(token, pos, writer, /*contextNode*/ contextNode); if (node && node.kind === contextNode.kind) { emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true); } @@ -1632,42 +1703,46 @@ namespace ts { } function emitReturnStatement(node: ReturnStatement) { - emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); - emitExpressionWithPrefix(" ", node.expression); - write(";"); + emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, writeKeyword, /*contextNode*/ node); + emitExpressionWithLeadingSpace(node.expression); + writeSemicolon(); } function emitWithStatement(node: WithStatement) { - write("with ("); + writeKeyword("with"); + writeSpace(); + writePunctuation("("); emitExpression(node.expression); - write(")"); + writePunctuation(")"); emitEmbeddedStatement(node, node.statement); } function emitSwitchStatement(node: SwitchStatement) { - const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); + const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos, writeKeyword); + writeSpace(); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation); emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - write(" "); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation); + writeSpace(); emit(node.caseBlock); } function emitLabeledStatement(node: LabeledStatement) { emit(node.label); - write(": "); + writePunctuation(":"); + writeSpace(); emit(node.statement); } function emitThrowStatement(node: ThrowStatement) { - write("throw"); - emitExpressionWithPrefix(" ", node.expression); - write(";"); + writeKeyword("throw"); + emitExpressionWithLeadingSpace(node.expression); + writeSemicolon(); } function emitTryStatement(node: TryStatement) { - write("try "); + writeKeyword("try"); + writeSpace(); emit(node.tryBlock); if (node.catchClause) { writeLineOrSpace(node); @@ -1675,14 +1750,15 @@ namespace ts { } if (node.finallyBlock) { writeLineOrSpace(node); - write("finally "); + writeKeyword("finally"); + writeSpace(); emit(node.finallyBlock); } } function emitDebuggerStatement(node: DebuggerStatement) { - writeToken(SyntaxKind.DebuggerKeyword, node.pos); - write(";"); + writeToken(SyntaxKind.DebuggerKeyword, node.pos, writeKeyword); + writeSemicolon(); } // @@ -1691,12 +1767,13 @@ namespace ts { function emitVariableDeclaration(node: VariableDeclaration) { emit(node.name); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); + emitTypeAnnotation(node.type); + emitInitializer(node.initializer); } function emitVariableDeclarationList(node: VariableDeclarationList) { - write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); + writeKeyword(isLet(node) ? "let" : isConst(node) ? "const" : "var"); + writeSpace(); emitList(node, node.declarations, ListFormat.VariableDeclarationList); } @@ -1707,9 +1784,9 @@ namespace ts { function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write("function"); + writeKeyword("function"); emitIfPresent(node.asteriskToken); - write(" "); + writeSpace(); emitIdentifierName(node.name); emitSignatureAndBody(node, emitSignatureHead); } @@ -1743,13 +1820,13 @@ namespace ts { } else { emitSignatureHead(node); - write(" "); + writeSpace(); emitExpression(body); } } else { emitSignatureHead(node); - write(";"); + writeSemicolon(); } } @@ -1757,7 +1834,7 @@ namespace ts { function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); + emitTypeAnnotation(node.type); } function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { @@ -1799,7 +1876,8 @@ namespace ts { } function emitBlockFunctionBody(body: Block) { - write(" {"); + writeSpace(); + writePunctuation("{"); increaseIndent(); const emitBlockFunctionBody = shouldEmitBlockFunctionBodyOnSingleLine(body) @@ -1814,7 +1892,7 @@ namespace ts { } decreaseIndent(); - writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body); + writeToken(SyntaxKind.CloseBraceToken, body.statements.end, writePunctuation, body); } function emitBlockFunctionBodyOnSingleLine(body: Block) { @@ -1843,8 +1921,11 @@ namespace ts { function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write("class"); - emitNodeWithPrefix(" ", node.name, emitIdentifierName); + writeKeyword("class"); + if (node.name) { + writeSpace(); + emitIdentifierName(node.name); + } const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { @@ -1854,9 +1935,10 @@ namespace ts { emitTypeParameters(node, node.typeParameters); emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); - write(" {"); + writeSpace(); + writePunctuation("{"); emitList(node, node.members, ListFormat.ClassMembers); - write("}"); + writePunctuation("}"); if (indentedFlag) { decreaseIndent(); @@ -1866,74 +1948,86 @@ namespace ts { function emitInterfaceDeclaration(node: InterfaceDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write("interface "); + writeKeyword("interface"); + writeSpace(); emit(node.name); emitTypeParameters(node, node.typeParameters); emitList(node, node.heritageClauses, ListFormat.HeritageClauses); - write(" {"); + writeSpace(); + writePunctuation("{"); emitList(node, node.members, ListFormat.InterfaceMembers); - write("}"); + writePunctuation("}"); } function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - write("type "); + writeKeyword("type"); + writeSpace(); emit(node.name); emitTypeParameters(node, node.typeParameters); - write(" = "); + writeSpace(); + writePunctuation("="); + writeSpace(); emit(node.type); - write(";"); + writeSemicolon(); } function emitEnumDeclaration(node: EnumDeclaration) { emitModifiers(node, node.modifiers); - write("enum "); + writeKeyword("enum"); + writeSpace(); emit(node.name); - write(" {"); + + writeSpace(); + writePunctuation("{"); emitList(node, node.members, ListFormat.EnumMembers); - write("}"); + writePunctuation("}"); } function emitModuleDeclaration(node: ModuleDeclaration) { emitModifiers(node, node.modifiers); if (~node.flags & NodeFlags.GlobalAugmentation) { - write(node.flags & NodeFlags.Namespace ? "namespace " : "module "); + writeKeyword(node.flags & NodeFlags.Namespace ? "namespace" : "module"); + writeSpace(); } emit(node.name); let body = node.body; while (body.kind === SyntaxKind.ModuleDeclaration) { - write("."); + writePunctuation("."); emit((body).name); body = (body).body; } - write(" "); + writeSpace(); emit(body); } function emitModuleBlock(node: ModuleBlock) { pushNameGenerationScope(node); - write("{"); + writePunctuation("{"); emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node)); - write("}"); + writePunctuation("}"); popNameGenerationScope(node); } function emitCaseBlock(node: CaseBlock) { - writeToken(SyntaxKind.OpenBraceToken, node.pos); + writeToken(SyntaxKind.OpenBraceToken, node.pos, writePunctuation); emitList(node, node.clauses, ListFormat.CaseBlockClauses); - writeToken(SyntaxKind.CloseBraceToken, node.clauses.end); + writeToken(SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation); } function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { emitModifiers(node, node.modifiers); - write("import "); + writeKeyword("import"); + writeSpace(); emit(node.name); - write(" = "); + writeSpace(); + writePunctuation("="); + writeSpace(); emitModuleReference(node.moduleReference); - write(";"); + writeSemicolon(); } function emitModuleReference(node: ModuleReference) { @@ -1947,25 +2041,32 @@ namespace ts { function emitImportDeclaration(node: ImportDeclaration) { emitModifiers(node, node.modifiers); - write("import "); + writeKeyword("import"); + writeSpace(); if (node.importClause) { emit(node.importClause); - write(" from "); + writeSpace(); + writeKeyword("from"); + writeSpace(); } emitExpression(node.moduleSpecifier); - write(";"); + writeSemicolon(); } function emitImportClause(node: ImportClause) { emit(node.name); if (node.name && node.namedBindings) { - write(", "); + writePunctuation(","); + writeSpace(); } emit(node.namedBindings); } function emitNamespaceImport(node: NamespaceImport) { - write("* as "); + writePunctuation("*"); + writeSpace(); + writeKeyword("as"); + writeSpace(); emit(node.name); } @@ -1978,30 +2079,46 @@ namespace ts { } function emitExportAssignment(node: ExportAssignment) { - write(node.isExportEquals ? "export = " : "export default "); + writeKeyword("export"); + writeSpace(); + if (node.isExportEquals) { + writeOperator("="); + } + else { + writeKeyword("default"); + } + writeSpace(); emitExpression(node.expression); - write(";"); + writeSemicolon(); } function emitExportDeclaration(node: ExportDeclaration) { - write("export "); + writeKeyword("export"); + writeSpace(); if (node.exportClause) { emit(node.exportClause); } else { - write("*"); + writePunctuation("*"); } if (node.moduleSpecifier) { - write(" from "); + writeSpace(); + writeKeyword("from"); + writeSpace(); emitExpression(node.moduleSpecifier); } - write(";"); + writeSemicolon(); } function emitNamespaceExportDeclaration(node: NamespaceExportDeclaration) { - write("export as namespace "); + writeKeyword("export"); + writeSpace(); + writeKeyword("as"); + writeSpace(); + writeKeyword("namespace"); + writeSpace(); emit(node.name); - write(";"); + writeSemicolon(); } function emitNamedExports(node: NamedExports) { @@ -2013,15 +2130,17 @@ namespace ts { } function emitNamedImportsOrExports(node: NamedImportsOrExports) { - write("{"); + writePunctuation("{"); emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); - write("}"); + writePunctuation("}"); } function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { if (node.propertyName) { emit(node.propertyName); - write(" as "); + writeSpace(); + writeKeyword("as"); + writeSpace(); } emit(node.name); @@ -2032,9 +2151,10 @@ namespace ts { // function emitExternalModuleReference(node: ExternalModuleReference) { - write("require("); + writeKeyword("require"); + writePunctuation("("); emitExpression(node.expression); - write(")"); + writePunctuation(")"); } // @@ -2048,14 +2168,14 @@ namespace ts { } function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { - write("<"); + writePunctuation("<"); emitJsxTagName(node.tagName); - write(" "); + writeSpace(); // We are checking here so we won't re-enter the emiting pipeline and emit extra sourcemap if (node.attributes.properties && node.attributes.properties.length > 0) { emit(node.attributes); } - write("/>"); + writePunctuation("/>"); } function emitJsxFragment(node: JsxFragment) { @@ -2065,30 +2185,31 @@ namespace ts { } function emitJsxOpeningElementOrFragment(node: JsxOpeningElement | JsxOpeningFragment) { - write("<"); + writePunctuation("<"); if (isJsxOpeningElement(node)) { emitJsxTagName(node.tagName); // We are checking here so we won't re-enter the emitting pipeline and emit extra sourcemap if (node.attributes.properties && node.attributes.properties.length > 0) { - write(" "); + writeSpace(); emit(node.attributes); } } - write(">"); + writePunctuation(">"); } function emitJsxText(node: JsxText) { + commitPendingSemicolon(); writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); } function emitJsxClosingElementOrFragment(node: JsxClosingElement | JsxClosingFragment) { - write(""); + writePunctuation(">"); } function emitJsxAttributes(node: JsxAttributes) { @@ -2097,21 +2218,21 @@ namespace ts { function emitJsxAttribute(node: JsxAttribute) { emit(node.name); - emitWithPrefix("=", node.initializer); + emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); } function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { - write("{..."); + writePunctuation("{..."); emitExpression(node.expression); - write("}"); + writePunctuation("}"); } function emitJsxExpression(node: JsxExpression) { if (node.expression) { - write("{"); + writePunctuation("{"); emitIfPresent(node.dotDotDotToken); emitExpression(node.expression); - write("}"); + writePunctuation("}"); } } @@ -2129,15 +2250,17 @@ namespace ts { // function emitCaseClause(node: CaseClause) { - write("case "); + writeKeyword("case"); + writeSpace(); emitExpression(node.expression); - write(":"); + writePunctuation(":"); emitCaseOrDefaultClauseStatements(node, node.statements); } function emitDefaultClause(node: DefaultClause) { - write("default:"); + writeKeyword("default"); + writePunctuation(":"); emitCaseOrDefaultClauseStatements(node, node.statements); } @@ -2169,27 +2292,27 @@ namespace ts { let format = ListFormat.CaseOrDefaultClauseStatements; if (emitAsSingleStatement) { - write(" "); + writeSpace(); format &= ~(ListFormat.MultiLine | ListFormat.Indented); } emitList(parentNode, statements, format); } function emitHeritageClause(node: HeritageClause) { - write(" "); - writeTokenText(node.token); - write(" "); + writeSpace(); + writeTokenText(node.token, writeKeyword); + writeSpace(); emitList(node, node.types, ListFormat.HeritageClauseTypes); } function emitCatchClause(node: CatchClause) { - const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); - write(" "); + const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos, writeKeyword); + writeSpace(); if (node.variableDeclaration) { - writeToken(SyntaxKind.OpenParenToken, openParenPos); + writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation); emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end); - write(" "); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end, writePunctuation); + writeSpace(); } emit(node.block); } @@ -2200,7 +2323,8 @@ namespace ts { function emitPropertyAssignment(node: PropertyAssignment) { emit(node.name); - write(": "); + writePunctuation(":"); + writeSpace(); // This is to ensure that we emit comment in the following case: // For example: // obj = { @@ -2219,14 +2343,16 @@ namespace ts { function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { emit(node.name); if (node.objectAssignmentInitializer) { - write(" = "); + writeSpace(); + writePunctuation("="); + writeSpace(); emitExpression(node.objectAssignmentInitializer); } } function emitSpreadAssignment(node: SpreadAssignment) { if (node.expression) { - write("..."); + writePunctuation("..."); emitExpression(node.expression); } } @@ -2237,7 +2363,7 @@ namespace ts { function emitEnumMember(node: EnumMember) { emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); + emitInitializer(node.initializer); } // @@ -2345,38 +2471,68 @@ namespace ts { // Helpers // + function emitNodeWithWriter(node: Node, writer: typeof write) { + const savedWrite = write; + write = writer; + emit(node); + write = savedWrite; + } + function emitModifiers(node: Node, modifiers: NodeArray) { if (modifiers && modifiers.length) { emitList(node, modifiers, ListFormat.Modifiers); - write(" "); + writeSpace(); } } - function emitWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emit); - } - - function emitExpressionWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emitExpression); - } - - function emitNodeWithPrefix(prefix: string, node: Node, emit: (node: Node) => void) { + function emitTypeAnnotation(node: TypeNode | undefined) { if (node) { - write(prefix); + writePunctuation(":"); + writeSpace(); emit(node); } } - function emitWithSuffix(node: Node, suffix: string) { + function emitInitializer(node: Expression | undefined) { + if (node) { + writeSpace(); + writeOperator("="); + writeSpace(); + emitExpression(node); + } + } + + function emitNodeWithPrefix(prefix: string, prefixWriter: (s: string) => void, node: Node, emit: (node: Node) => void) { + if (node) { + prefixWriter(prefix); + emit(node); + } + } + + function emitWithLeadingSpace(node: Node | undefined) { + if (node) { + writeSpace(); + emit(node); + } + } + + function emitExpressionWithLeadingSpace(node: Expression | undefined) { + if (node) { + writeSpace(); + emitExpression(node); + } + } + + function emitWithTrailingSpace(node: Node | undefined) { if (node) { emit(node); - write(suffix); + writeSpace(); } } function emitEmbeddedStatement(parent: Node, node: Statement) { if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { - write(" "); + writeSpace(); emit(node); } else { @@ -2395,7 +2551,10 @@ namespace ts { emitList(parentNode, typeArguments, ListFormat.TypeArguments); } - function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { + function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray) { + if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures + return emitTypeArguments(parentNode, parentNode.typeArguments); + } emitList(parentNode, typeParameters, ListFormat.TypeParameters); } @@ -2433,15 +2592,33 @@ namespace ts { emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); } - function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + function emitList(parentNode: TextRange, children: NodeArray, format: ListFormat, start?: number, count?: number) { emitNodeList(emit, parentNode, children, format, start, count); } - function emitExpressionList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + function emitExpressionList(parentNode: TextRange, children: NodeArray, format: ListFormat, start?: number, count?: number) { emitNodeList(emitExpression, parentNode, children, format, start, count); } - function emitNodeList(emit: (node: Node) => void, parentNode: Node, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { + function writeDelimiter(format: ListFormat) { + switch (format & ListFormat.DelimitersMask) { + case ListFormat.None: + break; + case ListFormat.CommaDelimited: + writePunctuation(","); + break; + case ListFormat.BarDelimited: + writeSpace(); + writePunctuation("|"); + break; + case ListFormat.AmpersandDelimited: + writeSpace(); + writePunctuation("&"); + break; + } + } + + function emitNodeList(emit: (node: Node) => void, parentNode: TextRange, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { const isUndefined = children === undefined; if (isUndefined && format & ListFormat.OptionalIfUndefined) { return; @@ -2459,7 +2636,7 @@ namespace ts { } if (format & ListFormat.BracketsMask) { - write(getOpeningBracket(format)); + writePunctuation(getOpeningBracket(format)); } if (onBeforeEmitNodeArray) { @@ -2472,7 +2649,7 @@ namespace ts { writeLine(); } else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) { - write(" "); + writeSpace(); } } else { @@ -2484,7 +2661,7 @@ namespace ts { shouldEmitInterveningComments = false; } else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); + writeSpace(); } // Increase the indent, if requested. @@ -2495,7 +2672,6 @@ namespace ts { // Emit each child. let previousSibling: Node; let shouldDecreaseIndentAfterEmit: boolean; - const delimiter = getDelimiter(format); for (let i = 0; i < count; i++) { const child = children[start + i]; @@ -2507,10 +2683,10 @@ namespace ts { // a // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline // , - if (delimiter && previousSibling.end !== parentNode.end) { + if (format & ListFormat.DelimitersMask && previousSibling.end !== parentNode.end) { emitLeadingCommentsOfPosition(previousSibling.end); } - write(delimiter); + writeDelimiter(format); // Write either a line terminator or whitespace to separate the elements. if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { @@ -2525,7 +2701,7 @@ namespace ts { shouldEmitInterveningComments = false; } else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { - write(" "); + writeSpace(); } } @@ -2553,7 +2729,7 @@ namespace ts { // Write a trailing comma, if requested. const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; if (format & ListFormat.CommaDelimited && hasTrailingComma) { - write(","); + writePunctuation(","); } @@ -2563,7 +2739,7 @@ namespace ts { // 2 // /* end of element 2 */ // ]; - if (previousSibling && delimiter && previousSibling.end !== parentNode.end && !(getEmitFlags(previousSibling) & EmitFlags.NoTrailingComments)) { + if (previousSibling && format & ListFormat.DelimitersMask && previousSibling.end !== parentNode.end && !(getEmitFlags(previousSibling) & EmitFlags.NoTrailingComments)) { emitLeadingCommentsOfPosition(previousSibling.end); } @@ -2577,7 +2753,7 @@ namespace ts { writeLine(); } else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); + writeSpace(); } } @@ -2586,51 +2762,115 @@ namespace ts { } if (format & ListFormat.BracketsMask) { - write(getClosingBracket(format)); + writePunctuation(getClosingBracket(format)); } } - function write(s: string) { + function commitPendingSemicolonInternal() { + if (pendingSemicolon) { + writeSemicolonInternal(); + pendingSemicolon = false; + } + } + + function writeLiteral(s: string) { + commitPendingSemicolon(); + writer.writeLiteral(s); + } + + function writeStringLiteral(s: string) { + commitPendingSemicolon(); + writer.writeStringLiteral(s); + } + + function writeBase(s: string) { + commitPendingSemicolon(); writer.write(s); } + function writeSymbol(s: string, sym: Symbol) { + commitPendingSemicolon(); + writer.writeSymbol(s, sym); + } + + function writePunctuation(s: string) { + commitPendingSemicolon(); + writer.writePunctuation(s); + } + + function deferWriteSemicolon() { + pendingSemicolon = true; + } + + function writeSemicolonInternal() { + writer.writePunctuation(";"); + } + + function writeKeyword(s: string) { + commitPendingSemicolon(); + writer.writeKeyword(s); + } + + function writeOperator(s: string) { + commitPendingSemicolon(); + writer.writeOperator(s); + } + + function writeParameter(s: string) { + commitPendingSemicolon(); + writer.writeParameter(s); + } + + function writeSpace() { + commitPendingSemicolon(); + writer.writeSpace(" "); + } + + function writeProperty(s: string) { + commitPendingSemicolon(); + writer.writeProperty(s); + } + function writeLine() { + commitPendingSemicolon(); writer.writeLine(); } function increaseIndent() { + commitPendingSemicolon(); writer.increaseIndent(); } function decreaseIndent() { + commitPendingSemicolon(); writer.decreaseIndent(); } - function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) { + function writeToken(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node) { return onEmitSourceMapOfToken - ? onEmitSourceMapOfToken(contextNode, token, pos, writeTokenText) - : writeTokenText(token, pos); + ? onEmitSourceMapOfToken(contextNode, token, writer, pos, writeTokenText) + : writeTokenText(token, writer, pos); } - function writeTokenNode(node: Node) { + function writeTokenNode(node: Node, writer: (s: string) => void) { if (onBeforeEmitToken) { onBeforeEmitToken(node); } - write(tokenToString(node.kind)); + writer(tokenToString(node.kind)); if (onAfterEmitToken) { onAfterEmitToken(node); } } - function writeTokenText(token: SyntaxKind, pos?: number) { + function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number) { const tokenString = tokenToString(token); - write(tokenString); + writer(tokenString); return pos < 0 ? pos : pos + tokenString.length; } function writeLineOrSpace(node: Node) { if (getEmitFlags(node) & EmitFlags.SingleLine) { - write(" "); + writeSpace(); } else { writeLine(); @@ -2688,7 +2928,7 @@ namespace ts { } } - function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + function shouldWriteLeadingLineTerminator(parentNode: TextRange, children: NodeArray, format: ListFormat) { if (format & ListFormat.MultiLine) { return true; } @@ -2734,7 +2974,7 @@ namespace ts { } } - function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + function shouldWriteClosingLineTerminator(parentNode: TextRange, children: NodeArray, format: ListFormat) { if (format & ListFormat.MultiLine) { return (format & ListFormat.NoTrailingNewLine) === 0; } @@ -3073,19 +3313,6 @@ namespace ts { } } - function createDelimiterMap() { - const delimiters: string[] = []; - delimiters[ListFormat.None] = ""; - delimiters[ListFormat.CommaDelimited] = ","; - delimiters[ListFormat.BarDelimited] = " |"; - delimiters[ListFormat.AmpersandDelimited] = " &"; - return delimiters; - } - - function getDelimiter(format: ListFormat) { - return delimiters[format & ListFormat.DelimitersMask]; - } - function createBracketsMap() { const brackets: string[][] = []; brackets[ListFormat.Braces] = ["{", "}"]; @@ -3109,86 +3336,4 @@ namespace ts { CountMask = 0x0FFFFFFF, // Temp variable counter _i = 0x10000000, // Use/preference flag for '_i' } - - const enum ListFormat { - None = 0, - - // Line separators - SingleLine = 0, // Prints the list on a single line (default). - MultiLine = 1 << 0, // Prints the list on multiple lines. - PreserveLines = 1 << 1, // Prints the list using line preservation if possible. - LinesMask = SingleLine | MultiLine | PreserveLines, - - // Delimiters - NotDelimited = 0, // There is no delimiter between list items (default). - BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. - AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. - CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. - DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, - - AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. - - // Whitespace - Indented = 1 << 6, // The list should be indented. - SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. - SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. - - // Brackets/Braces - Braces = 1 << 9, // The list is surrounded by "{" and "}". - Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". - AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". - SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". - BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, - - OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. - OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. - Optional = OptionalIfUndefined | OptionalIfEmpty, - - // Other - PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. - NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. - NoInterveningComments = 1 << 17, // Do not emit comments between each node - - NoSpaceIfEmpty = 1 << 18, // If the literal is empty, do not add spaces between braces. - SingleElement = 1 << 19, - - // Precomputed Formats - Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments, - HeritageClauses = SingleLine | SpaceBetweenSiblings, - SingleLineTypeLiteralMembers = SingleLine | SpaceBetweenBraces | SpaceBetweenSiblings | Indented, - MultiLineTypeLiteralMembers = MultiLine | Indented, - - TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, - UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, - IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, - ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, - ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty, - ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, - CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine, - CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, - NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, - TemplateExpressionSpans = SingleLine | NoInterveningComments, - SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, - MultiLineBlockStatements = Indented | MultiLine, - VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, - MultiLineFunctionBodyStatements = MultiLine, - ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, - ClassMembers = Indented | MultiLine, - InterfaceMembers = Indented | MultiLine, - EnumMembers = CommaDelimited | Indented | MultiLine, - CaseBlockClauses = Indented | MultiLine, - NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, - JsxElementOrFragmentChildren = SingleLine | NoInterveningComments, - JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, - CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, - HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SourceFileStatements = MultiLine | NoTrailingNewLine, - Decorators = MultiLine | Optional, - TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis, - IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, - } } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 7ddc8a0cd5f..14c8ad91eeb 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -112,21 +112,23 @@ namespace ts { export function createIdentifier(text: string): Identifier; /* @internal */ - // tslint:disable-next-line unified-signatures - export function createIdentifier(text: string, typeArguments: ReadonlyArray): Identifier; - export function createIdentifier(text: string, typeArguments?: ReadonlyArray): Identifier { + export function createIdentifier(text: string, typeArguments: ReadonlyArray): Identifier; // tslint:disable-line unified-signatures + export function createIdentifier(text: string, typeArguments?: ReadonlyArray): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); node.escapedText = escapeLeadingUnderscores(text); node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; node.autoGenerateKind = GeneratedIdentifierKind.None; node.autoGenerateId = 0; if (typeArguments) { - node.typeArguments = createNodeArray(typeArguments); + node.typeArguments = createNodeArray(typeArguments as ReadonlyArray); } return node; } - export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier { + export function updateIdentifier(node: Identifier): Identifier; + /* @internal */ + export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; // tslint:disable-line unified-signatures + export function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments ? updateNode(createIdentifier(idText(node), typeArguments), node) : node; @@ -578,11 +580,12 @@ namespace ts { } /* @internal */ - export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined) { + export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, typeArguments?: TypeNode[] | undefined) { const node = createSynthesizedNode(kind) as SignatureDeclaration; node.typeParameters = asNodeArray(typeParameters); node.parameters = asNodeArray(parameters); node.type = type; + node.typeArguments = asNodeArray(typeArguments); return node; } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 828c5744bbd..2dabb97b08d 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -51,7 +51,7 @@ namespace ts { * @param tokenStartPos The start pos of the token. * @param emitCallback The callback used to emit the token. */ - emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenStartPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number): number; + emitTokenWithSourceMap(node: Node, token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number): number; /** * Gets the text for the source map. @@ -372,9 +372,9 @@ namespace ts { * @param tokenStartPos The start pos of the token. * @param emitCallback The callback used to emit the token. */ - function emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number) { + function emitTokenWithSourceMap(node: Node, token: SyntaxKind, writer: (s: string) => void, tokenPos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number) { if (disabled) { - return emitCallback(token, tokenPos); + return emitCallback(token, writer, tokenPos); } const emitNode = node && node.emitNode; @@ -386,7 +386,7 @@ namespace ts { emitPos(tokenPos); } - tokenPos = emitCallback(token, tokenPos); + tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c51208c4f79..6622348e101 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -695,7 +695,7 @@ namespace ts { /*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace - /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics. + /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics, quickinfo, and signature help. /*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id. /*@internal*/ skipNameGenerationScope?: boolean; // Should skip a name generation scope when generating the name for this identifier } @@ -783,6 +783,7 @@ namespace ts { typeParameters?: NodeArray; parameters: NodeArray; type: TypeNode | undefined; + /* @internal */ typeArguments?: NodeArray; // Used for quick info, replaces typeParameters for instantiated signatures } export type SignatureDeclaration = @@ -966,7 +967,8 @@ namespace ts { | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration - | CallSignatureDeclaration; + | CallSignatureDeclaration + | JSDocFunctionType; export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; @@ -2762,6 +2764,16 @@ namespace ts { signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration; /** Note that the resulting nodes cannot be checked. */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration; + /** Note that the resulting nodes cannot be checked. */ + symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName; + /** Note that the resulting nodes cannot be checked. */ + symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Expression; + /** Note that the resulting nodes cannot be checked. */ + symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): NodeArray | undefined; + /** Note that the resulting nodes cannot be checked. */ + symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): ParameterDeclaration; + /** Note that the resulting nodes cannot be checked. */ + typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeParameterDeclaration; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; @@ -2780,9 +2792,17 @@ namespace ts { getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; + signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; + + /* @internal */ writeSignature(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, writer?: EmitTextWriter): string; + /* @internal */ writeType(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer?: EmitTextWriter): string; + /* @internal */ writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags, writer?: EmitTextWriter): string; + /* @internal */ writeTypePredicate(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer?: EmitTextWriter): string; + /** * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead * This will be removed in a future version. @@ -2897,7 +2917,7 @@ namespace ts { * This should be called in a loop climbing parents of the symbol, so we'll get `N`. */ /* @internal */ getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined; - + /* @internal */ getTypePredicateOfSignature(signature: Signature): TypePredicate; /* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol; } @@ -2908,30 +2928,98 @@ namespace ts { Subtype } - export enum NodeBuilderFlags { + export const enum NodeBuilderFlags { None = 0, // Options NoTruncation = 1 << 0, // Don't truncate result WriteArrayAsGenericType = 1 << 1, // Write Array instead T[] + WriteDefaultSymbolWithoutName = 1 << 2, // Write `default`-named symbols as `default` instead of how they were written + // empty space WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature UseFullyQualifiedType = 1 << 6, // Write out the fully qualified type name (eg. Module.Type, instead of Type) + UseOnlyExternalAliasing = 1 << 7, // Only use external aliases for a symbol SuppressAnyReturnType = 1 << 8, // If the return type is any-like, don't offer a return type. WriteTypeParametersInQualifiedName = 1 << 9, + MultilineObjectLiterals = 1 << 10, // Always write object literals across multiple lines + WriteClassExpressionAsTypeLiteral = 1 << 11, // Write class {} as { new(): {} } - used for mixin declaration emit + UseTypeOfFunction = 1 << 12, // Build using typeof instead of function type literal + OmitParameterModifiers = 1 << 13, // Omit modifiers on parameters + UseAliasDefinedOutsideCurrentScope = 1 << 14, // Allow non-visible aliases // Error handling - AllowThisInObjectLiteral = 1 << 10, - AllowQualifedNameInPlaceOfIdentifier = 1 << 11, - AllowAnonymousIdentifier = 1 << 13, - AllowEmptyUnionOrIntersection = 1 << 14, - AllowEmptyTuple = 1 << 15, + AllowThisInObjectLiteral = 1 << 15, + AllowQualifedNameInPlaceOfIdentifier = 1 << 16, + AllowAnonymousIdentifier = 1 << 17, + AllowEmptyUnionOrIntersection = 1 << 18, + AllowEmptyTuple = 1 << 19, + AllowUniqueESSymbolType = 1 << 20, + AllowEmptyIndexInfoType = 1 << 21, - IgnoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple, + IgnoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType, // State - InObjectTypeLiteral = 1 << 20, + InObjectTypeLiteral = 1 << 22, InTypeAlias = 1 << 23, // Writing type in type alias declaration } + // Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment + export const enum TypeFormatFlags { + None = 0, + NoTruncation = 1 << 0, // Don't truncate typeToString result + WriteArrayAsGenericType = 1 << 1, // Write Array instead T[] + WriteDefaultSymbolWithoutName = 1 << 2, // Write all `defaut`-named symbols as `default` instead of their written name + // hole because there's a hole in node builder flags + WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature + UseFullyQualifiedType = 1 << 6, // Write out the fully qualified type name (eg. Module.Type, instead of Type) + // hole because `UseOnlyExternalAliasing` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` instead + SuppressAnyReturnType = 1 << 8, // If the return type is any-like, don't offer a return type. + // hole because `WriteTypeParametersInQualifiedName` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` for this instead + MultilineObjectLiterals = 1 << 10, // Always print object literals across multiple lines (only used to map into node builder flags) + WriteClassExpressionAsTypeLiteral = 1 << 11, // Write a type literal instead of (Anonymous class) + UseTypeOfFunction = 1 << 12, // Write typeof instead of function type literal + OmitParameterModifiers = 1 << 13, // Omit modifiers on parameters + UseAliasDefinedOutsideCurrentScope = 1 << 14, // For a `type T = ... ` defined in a different file, write `T` instead of its value, + // even though `T` can't be accessed in the current scope. + + // Error Handling + AllowUniqueESSymbolType = 1 << 20, // This is bit 20 to align with the same bit in `NodeBuilderFlags` + + // TypeFormatFlags exclusive + AddUndefined = 1 << 17, // Add undefined to types of initialized, non-optional parameters + WriteArrowStyleSignature = 1 << 18, // Write arrow style signature + + // State + InArrayType = 1 << 19, // Writing an array element type + InElementType = 1 << 21, // Writing an array or union element type + InFirstTypeArgument = 1 << 22, // Writing first type argument of the instantiated type + InTypeAlias = 1 << 23, // Writing type in type alias declaration + + /** @deprecated */ WriteOwnNameForAnyLike = 0, // Does nothing + + NodeBuilderFlagsMask = + NoTruncation | WriteArrayAsGenericType | WriteDefaultSymbolWithoutName | WriteTypeArgumentsOfSignature | + UseFullyQualifiedType | SuppressAnyReturnType | MultilineObjectLiterals | WriteClassExpressionAsTypeLiteral | + UseTypeOfFunction | OmitParameterModifiers | UseAliasDefinedOutsideCurrentScope | AllowUniqueESSymbolType | InTypeAlias, + } + + export const enum SymbolFormatFlags { + None = 0x00000000, + + // Write symbols's type argument if it is instantiated symbol + // eg. class C { p: T } <-- Show p as C.p here + // var a: C; + // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p + WriteTypeParametersOrArguments = 0x00000001, + + // Use only external alias information to get the symbol name in the given context + // eg. module m { export class c { } } import x = m.c; + // When this flag is specified m.c will be used to refer to the class instead of alias symbol x + UseOnlyExternalAliasing = 0x00000002, + + // Build symbol name using any nodes needed, instead of just components of an entity name + AllowAnyNodeKind = 0x00000004, + } + /* @internal */ export interface SymbolWalker { /** Note: Return values are not ordered. */ @@ -2940,21 +3028,27 @@ namespace ts { walkSymbol(root: Symbol): { visitedTypes: ReadonlyArray, visitedSymbols: ReadonlyArray }; } + /** + * @deprecated + */ export interface SymbolDisplayBuilder { - buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; - buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; + /** @deprecated */ buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + /** @deprecated */ buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + /** @deprecated */ buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } - export interface SymbolWriter { + /** + * @deprecated Migrate to other methods of generating symbol names, ex symbolToEntityName + a printer or symbolToString + */ + export interface SymbolWriter extends SymbolTracker { writeKeyword(text: string): void; writeOperator(text: string): void; writePunctuation(text: string): void; @@ -2967,50 +3061,6 @@ namespace ts { increaseIndent(): void; decreaseIndent(): void; clear(): void; - - // Called when the symbol writer encounters a symbol to write. Currently only used by the - // declaration emitter to help determine if it should patch up the final declaration file - // with import statements it previously saw (but chose not to emit). - trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; - reportInaccessibleThisError(): void; - reportPrivateInBaseOfClassExpression(propertyName: string): void; - reportInaccessibleUniqueSymbolError(): void; - } - - export const enum TypeFormatFlags { - None = 0, - WriteArrayAsGenericType = 1 << 0, // Write Array instead T[] - UseTypeOfFunction = 1 << 2, // Write typeof instead of function type literal - NoTruncation = 1 << 3, // Don't truncate typeToString result - WriteArrowStyleSignature = 1 << 4, // Write arrow style signature - WriteOwnNameForAnyLike = 1 << 5, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc) - WriteTypeArgumentsOfSignature = 1 << 6, // Write the type arguments instead of type parameters of the signature - InElementType = 1 << 7, // Writing an array or union element type - UseFullyQualifiedType = 1 << 8, // Write out the fully qualified type name (eg. Module.Type, instead of Type) - InFirstTypeArgument = 1 << 9, // Writing first type argument of the instantiated type - InTypeAlias = 1 << 10, // Writing type in type alias declaration - SuppressAnyReturnType = 1 << 12, // If the return type is any-like, don't offer a return type. - AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters - WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class) - InArrayType = 1 << 15, // Writing an array element type - UseAliasDefinedOutsideCurrentScope = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value, - // even though `T` can't be accessed in the current scope. - AllowUniqueESSymbolType = 1 << 17, - } - - export const enum SymbolFormatFlags { - None = 0x00000000, - - // Write symbols's type argument if it is instantiated symbol - // eg. class C { p: T } <-- Show p as C.p here - // var a: C; - // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p - WriteTypeParametersOrArguments = 0x00000001, - - // Use only external alias information to get the symbol name in the given context - // eg. module m { export class c { } } import x = m.c; - // When this flag is specified m.c will be used to refer to the class instead of alias symbol x - UseOnlyExternalAliasing = 0x00000002, } /* @internal */ @@ -3102,9 +3152,9 @@ namespace ts { isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; - writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; - writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; - writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; + writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter): void; + writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter): void; + writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: EmitTextWriter): void; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant @@ -3118,7 +3168,7 @@ namespace ts { getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; - writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: SymbolWriter): void; + writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter): void; getJsxFactoryEntity(): EntityName; } @@ -4765,6 +4815,10 @@ namespace ts { * collisions. */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a list of nodes using the given format flags + */ + printList(format: ListFormat, list: NodeArray, sourceFile: SourceFile): string; /** * Prints a source file as-is, without any emit transformations. */ @@ -4774,6 +4828,7 @@ namespace ts { */ printBundle(bundle: Bundle): string; /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; + /*@internal*/ writeList(format: ListFormat, list: NodeArray, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void; } @@ -4821,7 +4876,7 @@ namespace ts { */ substituteNode?(hint: EmitHint, node: Node): Node; /*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number; + /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number; /*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void; /*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void; /*@internal*/ onSetSourceFile?: (node: SourceFile) => void; @@ -4834,13 +4889,14 @@ namespace ts { export interface PrinterOptions { removeComments?: boolean; newLine?: NewLineKind; + omitTrailingSemicolon?: boolean; /*@internal*/ sourceMap?: boolean; /*@internal*/ inlineSourceMap?: boolean; /*@internal*/ extendedDiagnostics?: boolean; } - /*@internal*/ - export interface EmitTextWriter { + /* @internal */ + export interface EmitTextWriter extends SymbolTracker, SymbolWriter { write(s: string): void; writeTextOfNode(text: string, node: Node): void; writeLine(): void; @@ -4854,7 +4910,26 @@ namespace ts { getColumn(): number; getIndent(): number; isAtStartOfLine(): boolean; - reset(): void; + clear(): void; + + writeKeyword(text: string): void; + writeOperator(text: string): void; + writePunctuation(text: string): void; + writeSpace(text: string): void; + writeStringLiteral(text: string): void; + writeParameter(text: string): void; + writeProperty(text: string): void; + writeSymbol(text: string, symbol: Symbol): void; + } + + export interface SymbolTracker { + // Called when the symbol writer encounters a symbol to write. Currently only used by the + // declaration emitter to help determine if it should patch up the final declaration file + // with import statements it previously saw (but chose not to emit). + trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; + reportInaccessibleThisError?(): void; + reportPrivateInBaseOfClassExpression?(propertyName: string): void; + reportInaccessibleUniqueSymbolError?(): void; } export interface TextSpan { @@ -4893,4 +4968,86 @@ namespace ts { export interface SyntaxList extends Node { _children: Node[]; } + + export const enum ListFormat { + None = 0, + + // Line separators + SingleLine = 0, // Prints the list on a single line (default). + MultiLine = 1 << 0, // Prints the list on multiple lines. + PreserveLines = 1 << 1, // Prints the list using line preservation if possible. + LinesMask = SingleLine | MultiLine | PreserveLines, + + // Delimiters + NotDelimited = 0, // There is no delimiter between list items (default). + BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. + AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. + CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. + DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, + + AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. + + // Whitespace + Indented = 1 << 6, // The list should be indented. + SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. + SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. + + // Brackets/Braces + Braces = 1 << 9, // The list is surrounded by "{" and "}". + Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". + AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". + SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". + BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, + + OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. + OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. + Optional = OptionalIfUndefined | OptionalIfEmpty, + + // Other + PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. + NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. + NoInterveningComments = 1 << 17, // Do not emit comments between each node + + NoSpaceIfEmpty = 1 << 18, // If the literal is empty, do not add spaces between braces. + SingleElement = 1 << 19, + + // Precomputed Formats + Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments, + HeritageClauses = SingleLine | SpaceBetweenSiblings, + SingleLineTypeLiteralMembers = SingleLine | SpaceBetweenBraces | SpaceBetweenSiblings | Indented, + MultiLineTypeLiteralMembers = MultiLine | Indented, + + TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, + UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, + IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, + ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, + ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, + ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty, + ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, + CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine, + CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, + NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, + TemplateExpressionSpans = SingleLine | NoInterveningComments, + SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, + MultiLineBlockStatements = Indented | MultiLine, + VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, + MultiLineFunctionBodyStatements = MultiLine, + ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, + ClassMembers = Indented | MultiLine, + InterfaceMembers = Indented | MultiLine, + EnumMembers = CommaDelimited | Indented | MultiLine, + CaseBlockClauses = Indented | MultiLine, + NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, + JsxElementOrFragmentChildren = SingleLine | NoInterveningComments, + JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, + CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, + HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SourceFileStatements = MultiLine | NoTrailingNewLine, + Decorators = MultiLine | Optional, + TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | AngleBrackets | Optional, + TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | AngleBrackets | Optional, + Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, + IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, + } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 8304320b301..796ed35a861 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -29,26 +29,31 @@ namespace ts { return undefined; } - export interface StringSymbolWriter extends SymbolWriter { - string(): string; - } - const stringWriter = createSingleLineStringWriter(); - function createSingleLineStringWriter(): StringSymbolWriter { + function createSingleLineStringWriter(): EmitTextWriter { let str = ""; const writeText: (text: string) => void = text => str += text; return { - string: () => str, + getText: () => str, + write: writeText, + rawWrite: writeText, + writeTextOfNode: writeText, writeKeyword: writeText, writeOperator: writeText, writePunctuation: writeText, writeSpace: writeText, writeStringLiteral: writeText, + writeLiteral: writeText, writeParameter: writeText, writeProperty: writeText, writeSymbol: writeText, + getTextPos: () => str.length, + getLine: () => 0, + getColumn: () => 0, + getIndent: () => 0, + isAtStartOfLine: () => false, // Completely ignore indentation for string writers. And map newlines to // a single space. @@ -63,11 +68,11 @@ namespace ts { }; } - export function usingSingleLineStringWriter(action: (writer: StringSymbolWriter) => void): string { - const oldString = stringWriter.string(); + export function usingSingleLineStringWriter(action: (writer: EmitTextWriter) => void): string { + const oldString = stringWriter.getText(); try { action(stringWriter); - return stringWriter.string(); + return stringWriter.getText(); } finally { stringWriter.clear(); @@ -2606,7 +2611,19 @@ namespace ts { getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1, getText: () => output, isAtStartOfLine: () => lineStart, - reset + clear: reset, + reportInaccessibleThisError: noop, + reportPrivateInBaseOfClassExpression: noop, + reportInaccessibleUniqueSymbolError: noop, + trackSymbol: noop, + writeKeyword: write, + writeOperator: write, + writeParameter: write, + writeProperty: write, + writePunctuation: write, + writeSpace: write, + writeStringLiteral: write, + writeSymbol: write }; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 2d678eb0eff..12b5d4f1b07 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -3,6 +3,8 @@ /// namespace ts { + const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration); + /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -222,7 +224,7 @@ namespace ts { // Names case SyntaxKind.Identifier: - return updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNode)); + return updateIdentifier(node, nodesVisitor((node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); case SyntaxKind.QualifiedName: return updateQualifiedName(node, diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 95d85bc5aa0..6f6b2f3c61e 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -229,13 +229,13 @@ namespace ts.codefix { } } - function getTypeAccessiblityWriter(checker: TypeChecker): StringSymbolWriter { + function getTypeAccessiblityWriter(checker: TypeChecker): EmitTextWriter { let str = ""; let typeIsAccessible = true; const writeText: (text: string) => void = text => str += text; return { - string: () => typeIsAccessible ? str : undefined, + getText: () => typeIsAccessible ? str : undefined, writeKeyword: writeText, writeOperator: writeText, writePunctuation: writeText, @@ -244,6 +244,15 @@ namespace ts.codefix { writeParameter: writeText, writeProperty: writeText, writeSymbol: writeText, + write: writeText, + writeTextOfNode: writeText, + rawWrite: writeText, + writeLiteral: writeText, + getTextPos: () => 0, + getLine: () => 0, + getColumn: () => 0, + getIndent: () => 0, + isAtStartOfLine: () => false, writeLine: () => writeText(" "), increaseIndent: noop, decreaseIndent: noop, @@ -261,8 +270,8 @@ namespace ts.codefix { function typeToString(type: Type, enclosingDeclaration: Declaration, checker: TypeChecker): string { const writer = getTypeAccessiblityWriter(checker); - checker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration); - return writer.string(); + checker.writeType(type, enclosingDeclaration, /*flags*/ undefined, writer); + return writer.getText(); } namespace InferFromReference { diff --git a/src/services/services.ts b/src/services/services.ts index 90e9b64a1df..4236416fbb3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -883,7 +883,8 @@ namespace ts { scriptKind: ScriptKind; } - export interface DisplayPartsSymbolWriter extends SymbolWriter { + /* @internal */ + export interface DisplayPartsSymbolWriter extends EmitTextWriter { displayParts(): SymbolDisplayPart[]; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f5338db954b..734912b3ffc 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -360,6 +360,7 @@ namespace ts.SignatureHelp { const callTarget = getInvokedExpression(invocation); const callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget); const callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); + const printer = createPrinter({ removeComments: true }); const items: SignatureHelpItem[] = map(candidates, candidateSignature => { let signatureHelpParameters: SignatureHelpParameter[]; const prefixDisplayParts: SymbolDisplayPart[] = []; @@ -376,14 +377,22 @@ namespace ts.SignatureHelp { const typeParameters = (candidateSignature.target || candidateSignature).typeParameters; signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken)); - const parameterParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisParameter, candidateSignature.parameters, writer, invocation)); + const parameterParts = mapToDisplayParts(writer => { + const flags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors; + const thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, flags)] : []; + const params = createNodeArray([...thisParameter, ...map(candidateSignature.parameters, param => typeChecker.symbolToParameterDeclaration(param, invocation, flags))]); + printer.writeList(ListFormat.CallExpressionArguments, params, getSourceFileOfNode(getParseTreeNode(invocation)), writer); + }); addRange(suffixDisplayParts, parameterParts); } else { isVariadic = candidateSignature.hasRestParameter; - const typeParameterParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation)); + const typeParameterParts = mapToDisplayParts(writer => { + if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { + const args = createNodeArray(map(candidateSignature.typeParameters, p => typeChecker.typeParameterToDeclaration(p, invocation))); + printer.writeList(ListFormat.TypeParameters, args, getSourceFileOfNode(getParseTreeNode(invocation)), writer); + } + }); addRange(prefixDisplayParts, typeParameterParts); prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); @@ -391,8 +400,17 @@ namespace ts.SignatureHelp { suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } - const returnTypeParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation)); + const returnTypeParts = mapToDisplayParts(writer => { + writer.writePunctuation(":"); + writer.writeSpace(" "); + const predicate = typeChecker.getTypePredicateOfSignature(candidateSignature); + if (predicate) { + typeChecker.writeTypePredicate(predicate, invocation, /*flags*/ undefined, writer); + } + else { + typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), invocation, /*flags*/ undefined, writer); + } + }); addRange(suffixDisplayParts, returnTypeParts); return { @@ -416,8 +434,10 @@ namespace ts.SignatureHelp { return { items, applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter { - const displayParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation)); + const displayParts = mapToDisplayParts(writer => { + const param = typeChecker.symbolToParameterDeclaration(parameter, invocation, NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors); + printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer); + }); return { name: parameter.name, @@ -428,8 +448,10 @@ namespace ts.SignatureHelp { } function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter { - const displayParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation)); + const displayParts = mapToDisplayParts(writer => { + const param = typeChecker.typeParameterToDeclaration(typeParameter, invocation); + printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer); + }); return { name: typeParameter.symbol.name, diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 6f979f1721b..9ec99f6ccaf 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -120,6 +120,7 @@ namespace ts.SymbolDisplay { let hasAddedSymbolInfo: boolean; const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location); let type: Type; + let printer: Printer; let documentationFromAlias: SymbolDisplayPart[]; // Class at constructor site need to be shown as constructor apart from property,method, vars @@ -198,7 +199,7 @@ namespace ts.SymbolDisplay { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); + addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); displayParts.push(lineBreakPart()); } if (useConstructSignatures) { @@ -450,7 +451,8 @@ namespace ts.SymbolDisplay { // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { const typeParameterParts = mapToDisplayParts(writer => { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); + const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration); + getPrinter().writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); }); addRange(displayParts, typeParameterParts); } @@ -510,6 +512,13 @@ namespace ts.SymbolDisplay { return { displayParts, documentation, symbolKind, tags }; + function getPrinter() { + if (!printer) { + printer = createPrinter({ removeComments: true }); + } + return printer; + } + function prefixNextMeaning() { if (displayParts.length) { displayParts.push(lineBreakPart()); @@ -535,7 +544,7 @@ namespace ts.SymbolDisplay { symbolToDisplay = alias; } const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, - SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); + SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing | SymbolFormatFlags.AllowAnyNodeKind); addRange(displayParts, fullSymbolDisplayParts); } @@ -584,7 +593,8 @@ namespace ts.SymbolDisplay { function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { const typeParameterParts = mapToDisplayParts(writer => { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); + const params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration); + getPrinter().writeList(ListFormat.TypeParameters, params, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); }); addRange(displayParts, typeParameterParts); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index b0efef44642..467ba6735ca 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -810,6 +810,38 @@ namespace ts.textChanges { this.writer.write(s); this.setLastNonTriviaPosition(s, /*force*/ false); } + writeKeyword(s: string): void { + this.writer.writeKeyword(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeOperator(s: string): void { + this.writer.writeOperator(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writePunctuation(s: string): void { + this.writer.writePunctuation(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeParameter(s: string): void { + this.writer.writeParameter(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeProperty(s: string): void { + this.writer.writeProperty(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeSpace(s: string): void { + this.writer.writeSpace(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeStringLiteral(s: string): void { + this.writer.writeStringLiteral(s); + this.setLastNonTriviaPosition(s, /*force*/ false); + } + writeSymbol(s: string, sym: Symbol): void { + this.writer.writeSymbol(s, sym); + this.setLastNonTriviaPosition(s, /*force*/ false); + } writeTextOfNode(text: string, node: Node): void { this.writer.writeTextOfNode(text, node); } @@ -848,8 +880,8 @@ namespace ts.textChanges { isAtStartOfLine(): boolean { return this.writer.isAtStartOfLine(); } - reset(): void { - this.writer.reset(); + clear(): void { + this.writer.clear(); this.lastNonTriviaPosition = 0; } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9562def31f5..c5694625493 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1127,6 +1127,7 @@ namespace ts { let indent: number; resetWriter(); + const unknownWrite = (text: string) => writeKind(text, SymbolDisplayPartKind.text); return { displayParts: () => displayParts, writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword), @@ -1136,8 +1137,18 @@ namespace ts { writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName), writeProperty: text => writeKind(text, SymbolDisplayPartKind.propertyName), + writeLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), writeSymbol, writeLine, + write: unknownWrite, + writeTextOfNode: unknownWrite, + getText: () => "", + getTextPos: () => 0, + getColumn: () => 0, + getLine: () => 0, + isAtStartOfLine: () => false, + rawWrite: notImplemented, + getIndent: () => indent, increaseIndent: () => { indent++; }, decreaseIndent: () => { indent--; }, clear: resetWriter, @@ -1249,6 +1260,7 @@ namespace ts { return displayPart("\n", SymbolDisplayPartKind.lineBreak); } + /* @internal */ export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] { try { writeDisplayParts(displayPartWriter); @@ -1261,20 +1273,20 @@ namespace ts { export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); }); } 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); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags, writer); }); } export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { - flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope; + flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; return mapToDisplayParts(writer => { - typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); + typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); }); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3eabea4435a..bee3d4d2637 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -639,7 +639,7 @@ declare namespace ts { body?: Block | Expression; } type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionExpression | ArrowFunction; - type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration; + type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | JSDocFunctionType; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; name?: Identifier; @@ -1729,6 +1729,16 @@ declare namespace ts { signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration; /** Note that the resulting nodes cannot be checked. */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration; + /** Note that the resulting nodes cannot be checked. */ + symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName; + /** Note that the resulting nodes cannot be checked. */ + symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Expression; + /** Note that the resulting nodes cannot be checked. */ + symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): NodeArray | undefined; + /** Note that the resulting nodes cannot be checked. */ + symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): ParameterDeclaration; + /** Note that the resulting nodes cannot be checked. */ + typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeParameterDeclaration; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; @@ -1748,7 +1758,8 @@ declare namespace ts { getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; /** * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead * This will be removed in a future version. @@ -1788,33 +1799,77 @@ declare namespace ts { None = 0, NoTruncation = 1, WriteArrayAsGenericType = 2, + WriteDefaultSymbolWithoutName = 4, + WriteTypeArgumentsOfSignature = 32, + UseFullyQualifiedType = 64, + UseOnlyExternalAliasing = 128, + SuppressAnyReturnType = 256, + WriteTypeParametersInQualifiedName = 512, + MultilineObjectLiterals = 1024, + WriteClassExpressionAsTypeLiteral = 2048, + UseTypeOfFunction = 4096, + OmitParameterModifiers = 8192, + UseAliasDefinedOutsideCurrentScope = 16384, + AllowThisInObjectLiteral = 32768, + AllowQualifedNameInPlaceOfIdentifier = 65536, + AllowAnonymousIdentifier = 131072, + AllowEmptyUnionOrIntersection = 262144, + AllowEmptyTuple = 524288, + AllowUniqueESSymbolType = 1048576, + AllowEmptyIndexInfoType = 2097152, + IgnoreErrors = 3112960, + InObjectTypeLiteral = 4194304, + InTypeAlias = 8388608, + } + enum TypeFormatFlags { + None = 0, + NoTruncation = 1, + WriteArrayAsGenericType = 2, + WriteDefaultSymbolWithoutName = 4, WriteTypeArgumentsOfSignature = 32, UseFullyQualifiedType = 64, SuppressAnyReturnType = 256, - WriteTypeParametersInQualifiedName = 512, - AllowThisInObjectLiteral = 1024, - AllowQualifedNameInPlaceOfIdentifier = 2048, - AllowAnonymousIdentifier = 8192, - AllowEmptyUnionOrIntersection = 16384, - AllowEmptyTuple = 32768, - IgnoreErrors = 60416, - InObjectTypeLiteral = 1048576, + MultilineObjectLiterals = 1024, + WriteClassExpressionAsTypeLiteral = 2048, + UseTypeOfFunction = 4096, + OmitParameterModifiers = 8192, + UseAliasDefinedOutsideCurrentScope = 16384, + AllowUniqueESSymbolType = 1048576, + AddUndefined = 131072, + WriteArrowStyleSignature = 262144, + InArrayType = 524288, + InElementType = 2097152, + InFirstTypeArgument = 4194304, InTypeAlias = 8388608, + /** @deprecated */ WriteOwnNameForAnyLike = 0, + NodeBuilderFlagsMask = 9469287, } + enum SymbolFormatFlags { + None = 0, + WriteTypeParametersOrArguments = 1, + UseOnlyExternalAliasing = 2, + AllowAnyNodeKind = 4, + } + /** + * @deprecated + */ interface SymbolDisplayBuilder { - buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; - buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; + /** @deprecated */ buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + /** @deprecated */ buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + /** @deprecated */ buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } - interface SymbolWriter { + /** + * @deprecated Migrate to other methods of generating symbol names, ex symbolToEntityName + a printer or symbolToString + */ + interface SymbolWriter extends SymbolTracker { writeKeyword(text: string): void; writeOperator(text: string): void; writePunctuation(text: string): void; @@ -1827,34 +1882,6 @@ declare namespace ts { increaseIndent(): void; decreaseIndent(): void; clear(): void; - trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; - reportInaccessibleThisError(): void; - reportPrivateInBaseOfClassExpression(propertyName: string): void; - reportInaccessibleUniqueSymbolError(): void; - } - enum TypeFormatFlags { - None = 0, - WriteArrayAsGenericType = 1, - UseTypeOfFunction = 4, - NoTruncation = 8, - WriteArrowStyleSignature = 16, - WriteOwnNameForAnyLike = 32, - WriteTypeArgumentsOfSignature = 64, - InElementType = 128, - UseFullyQualifiedType = 256, - InFirstTypeArgument = 512, - InTypeAlias = 1024, - SuppressAnyReturnType = 4096, - AddUndefined = 8192, - WriteClassExpressionAsTypeLiteral = 16384, - InArrayType = 32768, - UseAliasDefinedOutsideCurrentScope = 65536, - AllowUniqueESSymbolType = 131072, - } - enum SymbolFormatFlags { - None = 0, - WriteTypeParametersOrArguments = 1, - UseOnlyExternalAliasing = 2, } enum TypePredicateKind { This = 0, @@ -2634,6 +2661,10 @@ declare namespace ts { * collisions. */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a list of nodes using the given format flags + */ + printList(format: ListFormat, list: NodeArray, sourceFile: SourceFile): string; /** * Prints a source file as-is, without any emit transformations. */ @@ -2689,6 +2720,13 @@ declare namespace ts { interface PrinterOptions { removeComments?: boolean; newLine?: NewLineKind; + omitTrailingSemicolon?: boolean; + } + interface SymbolTracker { + trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; + reportInaccessibleThisError?(): void; + reportPrivateInBaseOfClassExpression?(propertyName: string): void; + reportInaccessibleUniqueSymbolError?(): void; } interface TextSpan { start: number; @@ -2701,6 +2739,71 @@ declare namespace ts { interface SyntaxList extends Node { _children: Node[]; } + enum ListFormat { + None = 0, + SingleLine = 0, + MultiLine = 1, + PreserveLines = 2, + LinesMask = 3, + NotDelimited = 0, + BarDelimited = 4, + AmpersandDelimited = 8, + CommaDelimited = 16, + DelimitersMask = 28, + AllowTrailingComma = 32, + Indented = 64, + SpaceBetweenBraces = 128, + SpaceBetweenSiblings = 256, + Braces = 512, + Parenthesis = 1024, + AngleBrackets = 2048, + SquareBrackets = 4096, + BracketsMask = 7680, + OptionalIfUndefined = 8192, + OptionalIfEmpty = 16384, + Optional = 24576, + PreferNewLine = 32768, + NoTrailingNewLine = 65536, + NoInterveningComments = 131072, + NoSpaceIfEmpty = 262144, + SingleElement = 524288, + Modifiers = 131328, + HeritageClauses = 256, + SingleLineTypeLiteralMembers = 448, + MultiLineTypeLiteralMembers = 65, + TupleTypeElements = 336, + UnionTypeConstituents = 260, + IntersectionTypeConstituents = 264, + ObjectBindingPatternElements = 262576, + ArrayBindingPatternElements = 262448, + ObjectLiteralExpressionProperties = 263122, + ArrayLiteralExpressionElements = 4466, + CommaListElements = 272, + CallExpressionArguments = 1296, + NewExpressionArguments = 9488, + TemplateExpressionSpans = 131072, + SingleLineBlockStatements = 384, + MultiLineBlockStatements = 65, + VariableDeclarationList = 272, + SingleLineFunctionBodyStatements = 384, + MultiLineFunctionBodyStatements = 1, + ClassHeritageClauses = 256, + ClassMembers = 65, + InterfaceMembers = 65, + EnumMembers = 81, + CaseBlockClauses = 65, + NamedImportsOrExportsElements = 432, + JsxElementOrFragmentChildren = 131072, + JsxElementAttributes = 131328, + CaseOrDefaultClauseStatements = 81985, + HeritageClauseTypes = 272, + SourceFileStatements = 65537, + Decorators = 24577, + TypeArguments = 26896, + TypeParameters = 26896, + Parameters = 1296, + IndexSignatureParameters = 4432, + } } declare namespace ts { const versionMajorMinor = "2.7"; @@ -3296,7 +3399,7 @@ declare namespace ts { function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; function createIdentifier(text: string): Identifier; - function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; + function updateIdentifier(node: Identifier): Identifier; /** Create a unique temporary variable. */ function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; /** Create a unique temporary variable for use in a loop. */ @@ -4661,9 +4764,6 @@ declare namespace ts { declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.7"; - interface DisplayPartsSymbolWriter extends SymbolWriter { - displayParts(): SymbolDisplayPart[]; - } function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[]): string; function getDefaultCompilerOptions(): CompilerOptions; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 630b7a08a28..09db501300b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -639,7 +639,7 @@ declare namespace ts { body?: Block | Expression; } type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionExpression | ArrowFunction; - type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration; + type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | JSDocFunctionType; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; name?: Identifier; @@ -1729,6 +1729,16 @@ declare namespace ts { signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration; /** Note that the resulting nodes cannot be checked. */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration; + /** Note that the resulting nodes cannot be checked. */ + symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName; + /** Note that the resulting nodes cannot be checked. */ + symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Expression; + /** Note that the resulting nodes cannot be checked. */ + symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): NodeArray | undefined; + /** Note that the resulting nodes cannot be checked. */ + symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): ParameterDeclaration; + /** Note that the resulting nodes cannot be checked. */ + typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeParameterDeclaration; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; @@ -1748,7 +1758,8 @@ declare namespace ts { getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; /** * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead * This will be removed in a future version. @@ -1788,33 +1799,77 @@ declare namespace ts { None = 0, NoTruncation = 1, WriteArrayAsGenericType = 2, + WriteDefaultSymbolWithoutName = 4, + WriteTypeArgumentsOfSignature = 32, + UseFullyQualifiedType = 64, + UseOnlyExternalAliasing = 128, + SuppressAnyReturnType = 256, + WriteTypeParametersInQualifiedName = 512, + MultilineObjectLiterals = 1024, + WriteClassExpressionAsTypeLiteral = 2048, + UseTypeOfFunction = 4096, + OmitParameterModifiers = 8192, + UseAliasDefinedOutsideCurrentScope = 16384, + AllowThisInObjectLiteral = 32768, + AllowQualifedNameInPlaceOfIdentifier = 65536, + AllowAnonymousIdentifier = 131072, + AllowEmptyUnionOrIntersection = 262144, + AllowEmptyTuple = 524288, + AllowUniqueESSymbolType = 1048576, + AllowEmptyIndexInfoType = 2097152, + IgnoreErrors = 3112960, + InObjectTypeLiteral = 4194304, + InTypeAlias = 8388608, + } + enum TypeFormatFlags { + None = 0, + NoTruncation = 1, + WriteArrayAsGenericType = 2, + WriteDefaultSymbolWithoutName = 4, WriteTypeArgumentsOfSignature = 32, UseFullyQualifiedType = 64, SuppressAnyReturnType = 256, - WriteTypeParametersInQualifiedName = 512, - AllowThisInObjectLiteral = 1024, - AllowQualifedNameInPlaceOfIdentifier = 2048, - AllowAnonymousIdentifier = 8192, - AllowEmptyUnionOrIntersection = 16384, - AllowEmptyTuple = 32768, - IgnoreErrors = 60416, - InObjectTypeLiteral = 1048576, + MultilineObjectLiterals = 1024, + WriteClassExpressionAsTypeLiteral = 2048, + UseTypeOfFunction = 4096, + OmitParameterModifiers = 8192, + UseAliasDefinedOutsideCurrentScope = 16384, + AllowUniqueESSymbolType = 1048576, + AddUndefined = 131072, + WriteArrowStyleSignature = 262144, + InArrayType = 524288, + InElementType = 2097152, + InFirstTypeArgument = 4194304, InTypeAlias = 8388608, + /** @deprecated */ WriteOwnNameForAnyLike = 0, + NodeBuilderFlagsMask = 9469287, } + enum SymbolFormatFlags { + None = 0, + WriteTypeParametersOrArguments = 1, + UseOnlyExternalAliasing = 2, + AllowAnyNodeKind = 4, + } + /** + * @deprecated + */ interface SymbolDisplayBuilder { - buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; - buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; + /** @deprecated */ buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + /** @deprecated */ buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + /** @deprecated */ buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } - interface SymbolWriter { + /** + * @deprecated Migrate to other methods of generating symbol names, ex symbolToEntityName + a printer or symbolToString + */ + interface SymbolWriter extends SymbolTracker { writeKeyword(text: string): void; writeOperator(text: string): void; writePunctuation(text: string): void; @@ -1827,34 +1882,6 @@ declare namespace ts { increaseIndent(): void; decreaseIndent(): void; clear(): void; - trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; - reportInaccessibleThisError(): void; - reportPrivateInBaseOfClassExpression(propertyName: string): void; - reportInaccessibleUniqueSymbolError(): void; - } - enum TypeFormatFlags { - None = 0, - WriteArrayAsGenericType = 1, - UseTypeOfFunction = 4, - NoTruncation = 8, - WriteArrowStyleSignature = 16, - WriteOwnNameForAnyLike = 32, - WriteTypeArgumentsOfSignature = 64, - InElementType = 128, - UseFullyQualifiedType = 256, - InFirstTypeArgument = 512, - InTypeAlias = 1024, - SuppressAnyReturnType = 4096, - AddUndefined = 8192, - WriteClassExpressionAsTypeLiteral = 16384, - InArrayType = 32768, - UseAliasDefinedOutsideCurrentScope = 65536, - AllowUniqueESSymbolType = 131072, - } - enum SymbolFormatFlags { - None = 0, - WriteTypeParametersOrArguments = 1, - UseOnlyExternalAliasing = 2, } enum TypePredicateKind { This = 0, @@ -2634,6 +2661,10 @@ declare namespace ts { * collisions. */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a list of nodes using the given format flags + */ + printList(format: ListFormat, list: NodeArray, sourceFile: SourceFile): string; /** * Prints a source file as-is, without any emit transformations. */ @@ -2689,6 +2720,13 @@ declare namespace ts { interface PrinterOptions { removeComments?: boolean; newLine?: NewLineKind; + omitTrailingSemicolon?: boolean; + } + interface SymbolTracker { + trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; + reportInaccessibleThisError?(): void; + reportPrivateInBaseOfClassExpression?(propertyName: string): void; + reportInaccessibleUniqueSymbolError?(): void; } interface TextSpan { start: number; @@ -2701,6 +2739,71 @@ declare namespace ts { interface SyntaxList extends Node { _children: Node[]; } + enum ListFormat { + None = 0, + SingleLine = 0, + MultiLine = 1, + PreserveLines = 2, + LinesMask = 3, + NotDelimited = 0, + BarDelimited = 4, + AmpersandDelimited = 8, + CommaDelimited = 16, + DelimitersMask = 28, + AllowTrailingComma = 32, + Indented = 64, + SpaceBetweenBraces = 128, + SpaceBetweenSiblings = 256, + Braces = 512, + Parenthesis = 1024, + AngleBrackets = 2048, + SquareBrackets = 4096, + BracketsMask = 7680, + OptionalIfUndefined = 8192, + OptionalIfEmpty = 16384, + Optional = 24576, + PreferNewLine = 32768, + NoTrailingNewLine = 65536, + NoInterveningComments = 131072, + NoSpaceIfEmpty = 262144, + SingleElement = 524288, + Modifiers = 131328, + HeritageClauses = 256, + SingleLineTypeLiteralMembers = 448, + MultiLineTypeLiteralMembers = 65, + TupleTypeElements = 336, + UnionTypeConstituents = 260, + IntersectionTypeConstituents = 264, + ObjectBindingPatternElements = 262576, + ArrayBindingPatternElements = 262448, + ObjectLiteralExpressionProperties = 263122, + ArrayLiteralExpressionElements = 4466, + CommaListElements = 272, + CallExpressionArguments = 1296, + NewExpressionArguments = 9488, + TemplateExpressionSpans = 131072, + SingleLineBlockStatements = 384, + MultiLineBlockStatements = 65, + VariableDeclarationList = 272, + SingleLineFunctionBodyStatements = 384, + MultiLineFunctionBodyStatements = 1, + ClassHeritageClauses = 256, + ClassMembers = 65, + InterfaceMembers = 65, + EnumMembers = 81, + CaseBlockClauses = 65, + NamedImportsOrExportsElements = 432, + JsxElementOrFragmentChildren = 131072, + JsxElementAttributes = 131328, + CaseOrDefaultClauseStatements = 81985, + HeritageClauseTypes = 272, + SourceFileStatements = 65537, + Decorators = 24577, + TypeArguments = 26896, + TypeParameters = 26896, + Parameters = 1296, + IndexSignatureParameters = 4432, + } } declare namespace ts { const versionMajorMinor = "2.7"; @@ -3243,7 +3346,7 @@ declare namespace ts { function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; function createIdentifier(text: string): Identifier; - function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; + function updateIdentifier(node: Identifier): Identifier; /** Create a unique temporary variable. */ function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; /** Create a unique temporary variable for use in a loop. */ @@ -4661,9 +4764,6 @@ declare namespace ts { declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.7"; - interface DisplayPartsSymbolWriter extends SymbolWriter { - displayParts(): SymbolDisplayPart[]; - } function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[]): string; function getDefaultCompilerOptions(): CompilerOptions; diff --git a/tests/baselines/reference/commentOnParameter1.js b/tests/baselines/reference/commentOnParameter1.js index 10ae2af1264..3e7ba725017 100644 --- a/tests/baselines/reference/commentOnParameter1.js +++ b/tests/baselines/reference/commentOnParameter1.js @@ -11,10 +11,10 @@ b //// [commentOnParameter1.js] function commentedParameters( - /* Parameter a */ - a - /* End of parameter a */ - /* Parameter b */ - , b - /* End of parameter b */ +/* Parameter a */ +a +/* End of parameter a */ +/* Parameter b */ +, b +/* End of parameter b */ ) { } diff --git a/tests/baselines/reference/commentOnParameter2.js b/tests/baselines/reference/commentOnParameter2.js index d0c024a6b3b..236e660abdf 100644 --- a/tests/baselines/reference/commentOnParameter2.js +++ b/tests/baselines/reference/commentOnParameter2.js @@ -10,9 +10,9 @@ b //// [commentOnParameter2.js] function commentedParameters( - /* Parameter a */ - a /* End of parameter a */ - /* Parameter b */ - , b - /* End of parameter b */ +/* Parameter a */ +a /* End of parameter a */ +/* Parameter b */ +, b +/* End of parameter b */ ) { } diff --git a/tests/baselines/reference/commentsFunction.js b/tests/baselines/reference/commentsFunction.js index ad31aa47b91..5588a27f5ba 100644 --- a/tests/baselines/reference/commentsFunction.js +++ b/tests/baselines/reference/commentsFunction.js @@ -61,8 +61,8 @@ function foo() { foo(); /** This is comment for function signature*/ function fooWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { +/** this is comment for b*/ +b) { var d = a; } // trailing comment of function fooWithParameters("a", 10); @@ -78,7 +78,7 @@ var lambddaNoVarComment = function (/**param a*/ a, /**param b*/ b) { return a * lambdaFoo(10, 20); lambddaNoVarComment(10, 20); function blah(a /* multiline trailing comment - multiline */) { +multiline */) { } function blah2(a /* single line multiple trailing comments */ /* second */) { } diff --git a/tests/baselines/reference/declFileConstructors.js b/tests/baselines/reference/declFileConstructors.js index 9f5fc12e002..f40ae2d5382 100644 --- a/tests/baselines/reference/declFileConstructors.js +++ b/tests/baselines/reference/declFileConstructors.js @@ -109,8 +109,8 @@ exports.SimpleConstructor = SimpleConstructor; var ConstructorWithParameters = /** @class */ (function () { /** This is comment for function signature*/ function ConstructorWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; } return ConstructorWithParameters; @@ -172,8 +172,8 @@ var GlobalSimpleConstructor = /** @class */ (function () { var GlobalConstructorWithParameters = /** @class */ (function () { /** This is comment for function signature*/ function GlobalConstructorWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; } return GlobalConstructorWithParameters; diff --git a/tests/baselines/reference/declFileFunctions.js b/tests/baselines/reference/declFileFunctions.js index 68ac66200a6..3e5c8af32ec 100644 --- a/tests/baselines/reference/declFileFunctions.js +++ b/tests/baselines/reference/declFileFunctions.js @@ -85,8 +85,8 @@ function foo() { exports.foo = foo; /** This is comment for function signature*/ function fooWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { +/** this is comment for b*/ +b) { var d = a; } exports.fooWithParameters = fooWithParameters; @@ -131,8 +131,8 @@ function nonExportedFoo() { } /** This is comment for function signature*/ function nonExportedFooWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { +/** this is comment for b*/ +b) { var d = a; } function nonExportedFooWithRestParameters(a) { @@ -151,8 +151,8 @@ function globalfoo() { } /** This is comment for function signature*/ function globalfooWithParameters(/** this is comment about a*/ a, - /** this is comment for b*/ - b) { +/** this is comment for b*/ +b) { var d = a; } function globalfooWithRestParameters(a) { diff --git a/tests/baselines/reference/declFileMethods.js b/tests/baselines/reference/declFileMethods.js index 78af9adcd98..a70dde6c3ee 100644 --- a/tests/baselines/reference/declFileMethods.js +++ b/tests/baselines/reference/declFileMethods.js @@ -200,8 +200,8 @@ var c1 = /** @class */ (function () { }; /** This is comment for function signature*/ c1.prototype.fooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c1.prototype.fooWithRestParameters = function (a) { @@ -219,8 +219,8 @@ var c1 = /** @class */ (function () { }; /** This is comment for function signature*/ c1.prototype.privateFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c1.prototype.privateFooWithRestParameters = function (a) { @@ -238,8 +238,8 @@ var c1 = /** @class */ (function () { }; /** This is comment for function signature*/ c1.staticFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c1.staticFooWithRestParameters = function (a) { @@ -257,8 +257,8 @@ var c1 = /** @class */ (function () { }; /** This is comment for function signature*/ c1.privateStaticFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c1.privateStaticFooWithRestParameters = function (a) { @@ -283,8 +283,8 @@ var c2 = /** @class */ (function () { }; /** This is comment for function signature*/ c2.prototype.fooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c2.prototype.fooWithRestParameters = function (a) { @@ -302,8 +302,8 @@ var c2 = /** @class */ (function () { }; /** This is comment for function signature*/ c2.prototype.privateFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c2.prototype.privateFooWithRestParameters = function (a) { @@ -321,8 +321,8 @@ var c2 = /** @class */ (function () { }; /** This is comment for function signature*/ c2.staticFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c2.staticFooWithRestParameters = function (a) { @@ -340,8 +340,8 @@ var c2 = /** @class */ (function () { }; /** This is comment for function signature*/ c2.privateStaticFooWithParameters = function (/** this is comment about a*/ a, - /** this is comment for b*/ - b) { + /** this is comment for b*/ + b) { var d = a; }; c2.privateStaticFooWithRestParameters = function (a) { diff --git a/tests/baselines/reference/declarationEmitBindingPatterns.js b/tests/baselines/reference/declarationEmitBindingPatterns.js index 800e30032c6..70ac7f437d3 100644 --- a/tests/baselines/reference/declarationEmitBindingPatterns.js +++ b/tests/baselines/reference/declarationEmitBindingPatterns.js @@ -18,7 +18,7 @@ function f(_a, _b, _c) { //// [declarationEmitBindingPatterns.d.ts] -declare const k: ({x: z}: { +declare const k: ({ x: z }: { x?: string; }) => void; declare var a: any; diff --git a/tests/baselines/reference/declarationEmitDestructuring2.js b/tests/baselines/reference/declarationEmitDestructuring2.js index 09980c5c9dd..c979b654960 100644 --- a/tests/baselines/reference/declarationEmitDestructuring2.js +++ b/tests/baselines/reference/declarationEmitDestructuring2.js @@ -26,18 +26,18 @@ declare function f({x, y: [a, b, c, d]}?: { }): void; declare function g([a, b, c, d]?: [number, number, number, number]): void; declare function h([a, [b], [[c]], {x, y: [a, b, c], z: {a1, b1}}]: [any, [any], [[any]], { - x?: number; - y: [any, any, any]; - z: { - a1: any; - b1: any; - }; -}]): void; + x?: number; + y: [any, any, any]; + z: { + a1: any; + b1: any; + }; + }]): void; declare function h1([a, [b], [[c]], {x, y, z: {a1, b1}}]: [any, [any], [[any]], { - x?: number; - y?: number[]; - z: { - a1: any; - b1: any; - }; -}]): void; + x?: number; + y?: number[]; + z: { + a1: any; + b1: any; + }; + }]): void; diff --git a/tests/baselines/reference/declarationEmitIndexTypeArray.js b/tests/baselines/reference/declarationEmitIndexTypeArray.js index a84080fb5c4..9fe8878a8db 100644 --- a/tests/baselines/reference/declarationEmitIndexTypeArray.js +++ b/tests/baselines/reference/declarationEmitIndexTypeArray.js @@ -21,5 +21,5 @@ var utilityFunctions = { //// [declarationEmitIndexTypeArray.d.ts] declare function doSomethingWithKeys(...keys: (keyof T)[]): void; declare const utilityFunctions: { - doSomethingWithKeys: (...keys: (keyof T)[]) => void; + doSomethingWithKeys: typeof doSomethingWithKeys; }; diff --git a/tests/baselines/reference/declarationEmitTypeofDefaultExport.symbols b/tests/baselines/reference/declarationEmitTypeofDefaultExport.symbols index 195f10a78a1..898a9883781 100644 --- a/tests/baselines/reference/declarationEmitTypeofDefaultExport.symbols +++ b/tests/baselines/reference/declarationEmitTypeofDefaultExport.symbols @@ -7,7 +7,7 @@ import * as a from "./a"; >a : Symbol(a, Decl(b.ts, 0, 6)) export default a.default; ->a.default : Symbol(a.default, Decl(a.ts, 0, 0)) +>a.default : Symbol(a.C, Decl(a.ts, 0, 0)) >a : Symbol(a, Decl(b.ts, 0, 6)) ->default : Symbol(a.default, Decl(a.ts, 0, 0)) +>default : Symbol(a.C, Decl(a.ts, 0, 0)) diff --git a/tests/baselines/reference/deferredLookupTypeResolution.js b/tests/baselines/reference/deferredLookupTypeResolution.js index 5f8edd63e57..e5baa6891e8 100644 --- a/tests/baselines/reference/deferredLookupTypeResolution.js +++ b/tests/baselines/reference/deferredLookupTypeResolution.js @@ -54,9 +54,7 @@ declare type T2 = ObjectHasKey<{ declare function f1(a: A, b: B): { [P in A | B]: any; }; -declare function f2(a: A): { - [P in A | "x"]: any; -}; +declare function f2(a: A): { [P in A | "x"]: any; }; declare function f3(x: 'a' | 'b'): { a: any; b: any; diff --git a/tests/baselines/reference/deferredLookupTypeResolution.types b/tests/baselines/reference/deferredLookupTypeResolution.types index d9486d30b07..cd123a6019e 100644 --- a/tests/baselines/reference/deferredLookupTypeResolution.types +++ b/tests/baselines/reference/deferredLookupTypeResolution.types @@ -17,7 +17,7 @@ type StringContains = ( >L : L type ObjectHasKey = StringContains ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >O : O >L : L >StringContains : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] @@ -25,19 +25,19 @@ type ObjectHasKey = StringContains >L : L type First = ObjectHasKey; // Should be deferred ->First : ({ [K in S]: "true"; } & { [key: string]: "false"; })["0"] +>First : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["0"] >T : T ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >T : T type T1 = ObjectHasKey<{ a: string }, 'a'>; // 'true' >T1 : "true" ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >a : string type T2 = ObjectHasKey<{ a: string }, 'b'>; // 'false' >T2 : "false" ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >a : string // Verify that mapped type isn't eagerly resolved in type-to-string operation @@ -55,13 +55,13 @@ declare function f1(a: A, b: B): { [P in A | >B : B function f2(a: A) { ->f2 : (a: A) => { [P in A | B]: any; } +>f2 : (a: A) => { [P in A | "x"]: any; } >A : A >a : A >A : A return f1(a, 'x'); ->f1(a, 'x') : { [P in A | B]: any; } +>f1(a, 'x') : { [P in A | "x"]: any; } >f1 : (a: A, b: B) => { [P in A | B]: any; } >a : A >'x' : "x" @@ -73,7 +73,7 @@ function f3(x: 'a' | 'b') { return f2(x); >f2(x) : { a: any; b: any; x: any; } ->f2 : (a: A) => { [P in A | B]: any; } +>f2 : (a: A) => { [P in A | "x"]: any; } >x : "a" | "b" } diff --git a/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt b/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt index f6bbe72f1a6..6d1d579c0ad 100644 --- a/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt +++ b/tests/baselines/reference/deferredLookupTypeResolution2.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/deferredLookupTypeResolution2.ts(14,13): error TS2536: Type '({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. -tests/cases/compiler/deferredLookupTypeResolution2.ts(19,21): error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. +tests/cases/compiler/deferredLookupTypeResolution2.ts(14,13): error TS2536: Type '({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. +tests/cases/compiler/deferredLookupTypeResolution2.ts(19,21): error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. ==== tests/cases/compiler/deferredLookupTypeResolution2.ts (2 errors) ==== @@ -18,14 +18,14 @@ tests/cases/compiler/deferredLookupTypeResolution2.ts(19,21): error TS2536: Type // Error, "false" not handled type E = { true: 'true' }[ObjectHasKey]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type '({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. +!!! error TS2536: Type '({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'. type Juxtapose = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey]; // Error, "otherwise" is missing type DeepError = { true: 'true' }[Juxtapose]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. +!!! error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'. type DeepOK = { true: 'true', otherwise: 'false' }[Juxtapose]; \ No newline at end of file diff --git a/tests/baselines/reference/deferredLookupTypeResolution2.types b/tests/baselines/reference/deferredLookupTypeResolution2.types index 25b3ceff934..76354731097 100644 --- a/tests/baselines/reference/deferredLookupTypeResolution2.types +++ b/tests/baselines/reference/deferredLookupTypeResolution2.types @@ -11,7 +11,7 @@ type StringContains = ({ [K in S]: 'true' } >L : L type ObjectHasKey = StringContains; ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >O : O >L : L >StringContains : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] @@ -19,52 +19,52 @@ type ObjectHasKey = StringContains; >L : L type A = ObjectHasKey; ->A : ({ [K in S]: "true"; } & { [key: string]: "false"; })["0"] +>A : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["0"] >T : T ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >T : T type B = ObjectHasKey<[string, number], '1'>; // "true" >B : "true" ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] type C = ObjectHasKey<[string, number], '2'>; // "false" >C : "false" ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] type D = A<[string]>; // "true" >D : "true" ->A : ({ [K in S]: "true"; } & { [key: string]: "false"; })["0"] +>A : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["0"] // Error, "false" not handled type E = { true: 'true' }[ObjectHasKey]; ->E : { true: "true"; }[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]] +>E : { true: "true"; }[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]] >T : T >true : "true" ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >T : T type Juxtapose = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey]; ->Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]] +>Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]] >T : T >true : "otherwise" >k : string ->ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L] +>ObjectHasKey : ({ [K in keyof O]: "true"; } & { [key: string]: "false"; })[L] >T : T // Error, "otherwise" is missing type DeepError = { true: 'true' }[Juxtapose]; ->DeepError : { true: "true"; }[({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]] +>DeepError : { true: "true"; }[({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]]] >T : T >true : "true" ->Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]] +>Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]] >T : T type DeepOK = { true: 'true', otherwise: 'false' }[Juxtapose]; ->DeepOK : { true: "true"; otherwise: "false"; }[({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]] +>DeepOK : { true: "true"; otherwise: "false"; }[({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]]] >T : T >true : "true" >otherwise : "false" ->Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]] +>Juxtapose : ({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["1"]] >T : T diff --git a/tests/baselines/reference/isomorphicMappedTypeInference.js b/tests/baselines/reference/isomorphicMappedTypeInference.js index aa000bc2913..e7df29894f9 100644 --- a/tests/baselines/reference/isomorphicMappedTypeInference.js +++ b/tests/baselines/reference/isomorphicMappedTypeInference.js @@ -275,9 +275,7 @@ declare function f3(): void; declare function f4(): void; declare function makeRecord(obj: { [P in K]: T; -}): { - [P in K]: T; -}; +}): { [P in K]: T; }; declare function f5(s: string): void; declare function makeDictionary(obj: { [x: string]: T; diff --git a/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.symbols b/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.symbols index 773fb3f5760..558ec029790 100644 --- a/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.symbols +++ b/tests/baselines/reference/objectTypeWithStringNamedPropertyOfIllegalCharacters.symbols @@ -31,7 +31,7 @@ var r3 = c["a b"]; var r4 = c["~!@#$%^&*()_+{}|:'<>?\/.,`"]; >r4 : Symbol(r4, Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 13, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 26, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 39, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 51, 3)) >c : Symbol(c, Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 8, 3)) ->"~!@#$%^&*()_+{}|:'<>?\/.,`" : Symbol(C["~!@#$%^&*()_+{}|:'<>?\/.,`"], Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 2, 20)) +>"~!@#$%^&*()_+{}|:'<>?\/.,`" : Symbol(C["~!@#$%^&*()_+{}|:'<>?/.,`"], Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 2, 20)) interface I { >I : Symbol(I, Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 13, 41)) @@ -63,7 +63,7 @@ var r3 = i["a b"]; var r4 = i["~!@#$%^&*()_+{}|:'<>?\/.,`"]; >r4 : Symbol(r4, Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 13, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 26, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 39, 3), Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 51, 3)) >i : Symbol(i, Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 21, 3)) ->"~!@#$%^&*()_+{}|:'<>?\/.,`" : Symbol(I["~!@#$%^&*()_+{}|:'<>?\/.,`"], Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 17, 20)) +>"~!@#$%^&*()_+{}|:'<>?\/.,`" : Symbol(I["~!@#$%^&*()_+{}|:'<>?/.,`"], Decl(objectTypeWithStringNamedPropertyOfIllegalCharacters.ts, 17, 20)) var a: { diff --git a/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline b/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline index 39ab90e8e09..1d2d8216808 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline @@ -38,7 +38,7 @@ }, { "text": "1", - "kind": "methodName" + "kind": "stringLiteral" }, { "text": "]", @@ -310,7 +310,7 @@ }, { "text": "1", - "kind": "methodName" + "kind": "stringLiteral" }, { "text": "]", @@ -380,7 +380,7 @@ }, { "text": "1", - "kind": "methodName" + "kind": "stringLiteral" }, { "text": "]", diff --git a/tests/baselines/reference/recursiveTypeRelations.types b/tests/baselines/reference/recursiveTypeRelations.types index 110ff8175c4..03008690d8d 100644 --- a/tests/baselines/reference/recursiveTypeRelations.types +++ b/tests/baselines/reference/recursiveTypeRelations.types @@ -17,7 +17,7 @@ class Query> { >A : A multiply>(x: B): Query; ->multiply : (x: B) => Query +>multiply : (x: B) => Query >B : B >Attributes : { [Key in Keys]: string; } >B : B diff --git a/tests/baselines/reference/typeGuardFunctionOfFormThisErrors.js b/tests/baselines/reference/typeGuardFunctionOfFormThisErrors.js index 84db5d4a4a9..5f8a850c589 100644 --- a/tests/baselines/reference/typeGuardFunctionOfFormThisErrors.js +++ b/tests/baselines/reference/typeGuardFunctionOfFormThisErrors.js @@ -152,6 +152,6 @@ declare let b: GuardInterface; declare function invalidGuard(c: any): this is number; declare let c: number | number[]; declare let holder: { - invalidGuard: (c: any) => this is number; + invalidGuard: typeof invalidGuard; }; declare let detached: () => this is FollowerGuard; diff --git a/tests/cases/fourslash/codeFixClassImplementInterfaceMappedType.ts b/tests/cases/fourslash/codeFixClassImplementInterfaceMappedType.ts index b787d0c271e..5fff622f2db 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterfaceMappedType.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterfaceMappedType.ts @@ -13,6 +13,6 @@ verify.codeFix({ x: { readonly [K in keyof X]: X[K] }; } class C implements I {\r - x: { readonly [K in keyof X]: Y[K]; };\r + x: { readonly [K in keyof Y]: Y[K]; };\r }`, });