Merge branch 'master' into elideExportStarForNonValues

This commit is contained in:
Vladimir Matveev 2015-11-09 10:38:38 -08:00
commit 810c45b5fb
28 changed files with 1203 additions and 495 deletions

View file

@ -2990,7 +2990,7 @@ namespace ts {
(<GenericType>type).typeArguments = type.typeParameters;
type.thisType = <TypeParameter>createType(TypeFlags.TypeParameter | TypeFlags.ThisType);
type.thisType.symbol = symbol;
type.thisType.constraint = getTypeWithThisArgument(type);
type.thisType.constraint = type;
}
}
return <InterfaceType>links.declaredType;
@ -3533,6 +3533,21 @@ namespace ts {
return type.flags & TypeFlags.UnionOrIntersection ? getPropertiesOfUnionOrIntersectionType(<UnionType>type) : getPropertiesOfObjectType(type);
}
/**
* The apparent type of a type parameter is the base constraint instantiated with the type parameter
* as the type argument for the 'this' type.
*/
function getApparentTypeOfTypeParameter(type: TypeParameter) {
if (!type.resolvedApparentType) {
let constraintType = getConstraintOfTypeParameter(type);
while (constraintType && constraintType.flags & TypeFlags.TypeParameter) {
constraintType = getConstraintOfTypeParameter(<TypeParameter>constraintType);
}
type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type);
}
return type.resolvedApparentType;
}
/**
* For a type parameter, return the base constraint of the type parameter. For the string, number,
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
@ -3540,12 +3555,7 @@ namespace ts {
*/
function getApparentType(type: Type): Type {
if (type.flags & TypeFlags.TypeParameter) {
do {
type = getConstraintOfTypeParameter(<TypeParameter>type);
} while (type && type.flags & TypeFlags.TypeParameter);
if (!type) {
type = emptyObjectType;
}
type = getApparentTypeOfTypeParameter(<TypeParameter>type);
}
if (type.flags & TypeFlags.StringLike) {
type = globalStringType;
@ -5606,18 +5616,31 @@ namespace ts {
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
}
function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) {
// A source signature matches a target signature if the two signatures have the same number of required,
// optional, and rest parameters.
if (source.parameters.length === target.parameters.length &&
source.minArgumentCount === target.minArgumentCount &&
source.hasRestParameter === target.hasRestParameter) {
return true;
}
// A source signature partially matches a target signature if the target signature has no fewer required
// parameters and no more overall parameters than the source signature (where a signature with a rest
// parameter is always considered to have more overall parameters than one without).
if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (
source.hasRestParameter && !target.hasRestParameter ||
source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) {
return true;
}
return false;
}
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
if (source === target) {
return Ternary.True;
}
if (source.parameters.length !== target.parameters.length ||
source.minArgumentCount !== target.minArgumentCount ||
source.hasRestParameter !== target.hasRestParameter) {
if (!partialMatch ||
source.parameters.length < target.parameters.length && !source.hasRestParameter ||
source.minArgumentCount > target.minArgumentCount) {
return Ternary.False;
}
if (!(isMatchingSignature(source, target, partialMatch))) {
return Ternary.False;
}
let result = Ternary.True;
if (source.typeParameters && target.typeParameters) {
@ -6424,9 +6447,10 @@ namespace ts {
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
// Check that type is not any, assumed result is true, and we have variable symbol on the left
if (isTypeAny(type) || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
return type;
}
// Check that right operand is a function type with a prototype property
const rightType = checkExpression(expr.right);
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
@ -6458,6 +6482,13 @@ namespace ts {
}
if (targetType) {
if (!assumeTrue) {
if (type.flags & TypeFlags.Union) {
return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, targetType)));
}
return type;
}
return getNarrowedType(type, targetType);
}

View file

@ -785,7 +785,8 @@ namespace ts {
};
export interface ObjectAllocator {
getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node;
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
@ -804,17 +805,17 @@ namespace ts {
function Signature(checker: TypeChecker) {
}
function Node(kind: SyntaxKind, pos: number, end: number) {
this.kind = kind;
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
export let objectAllocator: ObjectAllocator = {
getNodeConstructor: kind => {
function Node(pos: number, end: number) {
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
Node.prototype = { kind };
return <any>Node;
},
getNodeConstructor: () => <any>Node,
getSourceFileConstructor: () => <any>Node,
getSymbolConstructor: () => <any>Symbol,
getTypeConstructor: () => <any>Type,
getSignatureConstructor: () => <any>Signature

View file

@ -45,12 +45,15 @@ namespace ts {
let writeLine: () => void;
let increaseIndent: () => void;
let decreaseIndent: () => void;
let writeTextOfNode: (sourceFile: SourceFile, node: Node) => void;
let writeTextOfNode: (text: string, node: Node) => void;
let writer = createAndSetNewTextWriterWithSymbolWriter();
let enclosingDeclaration: Node;
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: number[];
let currentIdentifiers: Map<string>;
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
let errorNameNode: DeclarationName;
const emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
@ -134,14 +137,13 @@ namespace ts {
};
function hasInternalAnnotation(range: CommentRange) {
const text = currentSourceFile.text;
const comment = text.substring(range.pos, range.end);
const comment = currentText.substring(range.pos, range.end);
return comment.indexOf("@internal") >= 0;
}
function stripInternal(node: Node) {
if (node) {
const leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos);
const leadingCommentRanges = getLeadingCommentRanges(currentText, node.pos);
if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
return;
}
@ -243,7 +245,7 @@ namespace ts {
if (errorInfo.typeName) {
diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
errorInfo.diagnosticMessage,
getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName),
getTextOfNodeFromSourceText(currentText, errorInfo.typeName),
symbolAccesibilityResult.errorSymbolName,
symbolAccesibilityResult.errorModuleName));
}
@ -321,10 +323,10 @@ namespace ts {
function writeJsDocComments(declaration: Node) {
if (declaration) {
const jsDocComments = getJsDocComments(declaration, currentSourceFile);
emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
}
}
@ -343,7 +345,7 @@ namespace ts {
case SyntaxKind.VoidKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.StringLiteral:
return writeTextOfNode(currentSourceFile, type);
return writeTextOfNode(currentText, type);
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
case SyntaxKind.TypeReference:
@ -375,14 +377,14 @@ namespace ts {
function writeEntityName(entityName: EntityName | Expression) {
if (entityName.kind === SyntaxKind.Identifier) {
writeTextOfNode(currentSourceFile, entityName);
writeTextOfNode(currentText, entityName);
}
else {
const left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
const right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
writeEntityName(left);
write(".");
writeTextOfNode(currentSourceFile, right);
writeTextOfNode(currentText, right);
}
}
@ -417,7 +419,7 @@ namespace ts {
}
function emitTypePredicate(type: TypePredicateNode) {
writeTextOfNode(currentSourceFile, type.parameterName);
writeTextOfNode(currentText, type.parameterName);
write(" is ");
emitType(type.type);
}
@ -466,9 +468,12 @@ namespace ts {
}
function emitSourceFile(node: SourceFile) {
currentSourceFile = node;
currentText = node.text;
currentLineMap = getLineStarts(node);
currentIdentifiers = node.identifiers;
isCurrentFileExternalModule = isExternalModule(node);
enclosingDeclaration = node;
emitDetachedComments(currentSourceFile, writer, writeCommentRange, node, newLine, true /* remove comments */);
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, true /* remove comments */);
emitLines(node.statements);
}
@ -478,13 +483,13 @@ namespace ts {
// do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string {
const baseName = "_default";
if (!hasProperty(currentSourceFile.identifiers, baseName)) {
if (!hasProperty(currentIdentifiers, baseName)) {
return baseName;
}
let count = 0;
while (true) {
const name = baseName + "_" + (++count);
if (!hasProperty(currentSourceFile.identifiers, name)) {
if (!hasProperty(currentIdentifiers, name)) {
return name;
}
}
@ -493,7 +498,7 @@ namespace ts {
function emitExportAssignment(node: ExportAssignment) {
if (node.expression.kind === SyntaxKind.Identifier) {
write(node.isExportEquals ? "export = " : "export default ");
writeTextOfNode(currentSourceFile, node.expression);
writeTextOfNode(currentText, node.expression);
}
else {
// Expression
@ -537,7 +542,7 @@ namespace ts {
}
// Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective
else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
(node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) {
(node.parent.kind === SyntaxKind.SourceFile && isCurrentFileExternalModule)) {
let isVisible: boolean;
if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
// Import declaration of another module that is visited async so lets put it in right spot
@ -593,7 +598,7 @@ namespace ts {
function emitModuleElementDeclarationFlags(node: Node) {
// If the node is parented in the current source file we need to emit export declare or just export
if (node.parent === currentSourceFile) {
if (node.parent.kind === SyntaxKind.SourceFile) {
// If the node is exported
if (node.flags & NodeFlags.Export) {
write("export ");
@ -632,7 +637,7 @@ namespace ts {
write("export ");
}
write("import ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
write(" = ");
if (isInternalModuleImportEqualsDeclaration(node)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError);
@ -640,7 +645,7 @@ namespace ts {
}
else {
write("require(");
writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node));
writeTextOfNode(currentText, getExternalModuleImportEqualsDeclarationExpression(node));
write(");");
}
writer.writeLine();
@ -678,7 +683,7 @@ namespace ts {
if (node.importClause) {
const currentWriterPos = writer.getTextPos();
if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
writeTextOfNode(currentSourceFile, node.importClause.name);
writeTextOfNode(currentText, node.importClause.name);
}
if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
if (currentWriterPos !== writer.getTextPos()) {
@ -687,7 +692,7 @@ namespace ts {
}
if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
write("* as ");
writeTextOfNode(currentSourceFile, (<NamespaceImport>node.importClause.namedBindings).name);
writeTextOfNode(currentText, (<NamespaceImport>node.importClause.namedBindings).name);
}
else {
write("{ ");
@ -697,17 +702,17 @@ namespace ts {
}
write(" from ");
}
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
writeTextOfNode(currentText, node.moduleSpecifier);
write(";");
writer.writeLine();
}
function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) {
if (node.propertyName) {
writeTextOfNode(currentSourceFile, node.propertyName);
writeTextOfNode(currentText, node.propertyName);
write(" as ");
}
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
function emitExportSpecifier(node: ExportSpecifier) {
@ -733,7 +738,7 @@ namespace ts {
}
if (node.moduleSpecifier) {
write(" from ");
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
writeTextOfNode(currentText, node.moduleSpecifier);
}
write(";");
writer.writeLine();
@ -748,11 +753,11 @@ namespace ts {
else {
write("module ");
}
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
@ -772,7 +777,7 @@ namespace ts {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("type ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
emitTypeParameters(node.typeParameters);
write(" = ");
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
@ -796,7 +801,7 @@ namespace ts {
write("const ");
}
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
write(" {");
writeLine();
increaseIndent();
@ -808,7 +813,7 @@ namespace ts {
function emitEnumMemberDeclaration(node: EnumMember) {
emitJsDocComments(node);
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
const enumMemberValue = resolver.getConstantValue(node);
if (enumMemberValue !== undefined) {
write(" = ");
@ -827,7 +832,7 @@ namespace ts {
increaseIndent();
emitJsDocComments(node);
decreaseIndent();
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
// If there is constraint present and this is not a type parameter of the private method emit the constraint
if (node.constraint && !isPrivateMethodTypeParameter(node)) {
write(" extends ");
@ -958,7 +963,7 @@ namespace ts {
}
write("class ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
@ -982,7 +987,7 @@ namespace ts {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("interface ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
@ -1020,7 +1025,7 @@ namespace ts {
// If this node is a computed name, it can only be a symbol, because we've already skipped
// it if it's not a well known symbol. In that case, the text of the name will be exactly
// what we want, namely the name expression enclosed in brackets.
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
// If optional property emit ?
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
write("?");
@ -1107,7 +1112,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>bindingElement.name);
}
else {
writeTextOfNode(currentSourceFile, bindingElement.name);
writeTextOfNode(currentText, bindingElement.name);
writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError);
}
}
@ -1157,7 +1162,7 @@ namespace ts {
emitJsDocComments(accessors.getAccessor);
emitJsDocComments(accessors.setAccessor);
emitClassMemberDeclarationFlags(node);
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
if (!(node.flags & NodeFlags.Private)) {
accessorWithTypeAnnotation = node;
let type = getTypeAnnotationFromAccessor(node);
@ -1247,13 +1252,13 @@ namespace ts {
}
if (node.kind === SyntaxKind.FunctionDeclaration) {
write("function ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
else if (node.kind === SyntaxKind.Constructor) {
write("constructor");
}
else {
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
if (hasQuestionToken(node)) {
write("?");
}
@ -1393,7 +1398,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>node.name);
}
else {
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
if (resolver.isOptionalParameter(node)) {
write("?");
@ -1519,7 +1524,7 @@ namespace ts {
// Example:
// original: function foo({y: [a,b,c]}) {}
// emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
writeTextOfNode(currentSourceFile, bindingElement.propertyName);
writeTextOfNode(currentText, bindingElement.propertyName);
write(": ");
}
if (bindingElement.name) {
@ -1542,7 +1547,7 @@ namespace ts {
if (bindingElement.dotDotDotToken) {
write("...");
}
writeTextOfNode(currentSourceFile, bindingElement.name);
writeTextOfNode(currentText, bindingElement.name);
}
}
}

View file

@ -333,6 +333,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
const jsxDesugaring = host.getCompilerOptions().jsx !== JsxEmit.Preserve;
const shouldEmitJsx = (s: SourceFile) => (s.languageVariant === LanguageVariant.JSX && !jsxDesugaring);
const emitJavaScript = createFileEmitter();
if (targetSourceFile === undefined) {
forEach(host.getSourceFiles(), sourceFile => {
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
@ -470,11 +472,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
const writer = createTextWriter(newLine);
function createFileEmitter(): (jsFilePath: string, root?: SourceFile) => void {
const writer: EmitTextWriter = createTextWriter(newLine);
const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: number[];
let currentFileIdentifiers: Map<string>;
let renamedDependencies: Map<string>;
let isEs6Module: boolean;
let isCurrentFileExternalModule: boolean;
// name of an exporter function if file is a System external module
// System.register([...], function (<exporter>) {...})
// exporting in System modules looks like:
@ -483,17 +492,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// var x;... exporter("x", x = 1)
let exportFunctionForFile: string;
const generatedNameSet: Map<string> = {};
const nodeToGeneratedName: string[] = [];
let generatedNameSet: Map<string>;
let nodeToGeneratedName: string[];
let computedPropertyNamesToGeneratedNames: string[];
let convertedLoopState: ConvertedLoopState;
let extendsEmitted = false;
let decorateEmitted = false;
let paramEmitted = false;
let awaiterEmitted = false;
let tempFlags = 0;
let extendsEmitted: boolean;
let decorateEmitted: boolean;
let paramEmitted: boolean;
let awaiterEmitted: boolean;
let tempFlags: TempFlags;
let tempVariables: Identifier[];
let tempParameters: Identifier[];
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
@ -547,35 +556,74 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
[ModuleKind.CommonJS]: emitCommonJSModule,
};
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
initializeEmitterWithSourceMaps();
}
return doEmit;
if (root) {
// Do not call emit directly. It does not set the currentSourceFile.
emitSourceFile(root);
}
else {
forEach(host.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
emitSourceFile(sourceFile);
}
});
}
function doEmit(jsFilePath: string, root?: SourceFile) {
// reset the state
writer.reset();
currentSourceFile = undefined;
currentText = undefined;
currentLineMap = undefined;
exportFunctionForFile = undefined;
generatedNameSet = {};
nodeToGeneratedName = [];
computedPropertyNamesToGeneratedNames = undefined;
convertedLoopState = undefined;
writeLine();
writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM);
return;
extendsEmitted = false;
decorateEmitted = false;
paramEmitted = false;
awaiterEmitted = false;
tempFlags = 0;
tempVariables = undefined;
tempParameters = undefined;
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = undefined;
detachedCommentsInfo = undefined;
sourceMapData = undefined;
isEs6Module = false;
renamedDependencies = undefined;
isCurrentFileExternalModule = false;
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
initializeEmitterWithSourceMaps(jsFilePath, root);
}
if (root) {
// Do not call emit directly. It does not set the currentSourceFile.
emitSourceFile(root);
}
else {
forEach(host.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
emitSourceFile(sourceFile);
}
});
}
writeLine();
writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM);
}
function emitSourceFile(sourceFile: SourceFile): void {
currentSourceFile = sourceFile;
currentText = sourceFile.text;
currentLineMap = getLineStarts(sourceFile);
exportFunctionForFile = undefined;
isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"];
renamedDependencies = sourceFile.renamedDependencies;
currentFileIdentifiers = sourceFile.identifiers;
isCurrentFileExternalModule = isExternalModule(sourceFile);
emit(sourceFile);
}
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentSourceFile.identifiers, name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
}
@ -667,7 +715,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node)));
}
function initializeEmitterWithSourceMaps() {
function initializeEmitterWithSourceMaps(jsFilePath: string, root?: SourceFile) {
let sourceMapDir: string; // The directory in which sourcemap will be
// Current source map file and its index in the sources list
@ -771,7 +819,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function recordSourceMapSpan(pos: number) {
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
const sourceLinePos = computeLineAndCharacterOfPosition(currentLineMap, pos);
// Convert the location to be one-based.
sourceLinePos.line++;
@ -810,7 +858,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function recordEmitNodeStartSpan(node: Node) {
// Get the token pos after skipping to the token (ignoring the leading trivia)
recordSourceMapSpan(skipTrivia(currentSourceFile.text, node.pos));
recordSourceMapSpan(skipTrivia(currentText, node.pos));
}
function recordEmitNodeEndSpan(node: Node) {
@ -818,7 +866,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
const tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
const tokenStartPos = ts.skipTrivia(currentText, startPos);
recordSourceMapSpan(tokenStartPos);
const tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
recordSourceMapSpan(tokenEndPos);
@ -912,9 +960,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
sourceMapNameIndices.pop();
};
function writeCommentRangeWithMap(curentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
function writeCommentRangeWithMap(currentText: string, currentLineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
recordSourceMapSpan(comment.pos);
writeCommentRange(currentSourceFile, writer, comment, newLine);
writeCommentRange(currentText, currentLineMap, writer, comment, newLine);
recordSourceMapSpan(comment.end);
}
@ -950,7 +998,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
function writeJavaScriptAndSourceMapFile(emitOutput: string, jsFilePath: string, writeByteOrderMark: boolean) {
encodeLastRecordedSourceMapSpan();
const sourceMapText = serializeSourceMapContents(
@ -977,7 +1025,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
// Write sourcemap url to the js file and write the js file
writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark);
writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark);
}
// Initialize source map data
@ -1059,7 +1107,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
writeComment = writeCommentRangeWithMap;
}
function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) {
function writeJavaScriptFile(emitOutput: string, jsFilePath: string, writeByteOrderMark: boolean) {
writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
}
@ -1269,7 +1317,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// If we don't need to downlevel and we can reach the original source text using
// the node's parent reference, then simply get the text as it was originally written.
if (node.parent) {
return getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
return getTextOfNodeFromSourceText(currentText, node);
}
// If we can't reach the original source text, use the canonical form if it's a number,
@ -1300,7 +1348,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
let text = getTextOfNodeFromSourceText(currentText, node);
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
@ -1772,7 +1820,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write((<LiteralExpression>node).text);
}
else {
writeTextOfNode(currentSourceFile, node);
writeTextOfNode(currentText, node);
}
write("\"");
@ -1876,7 +1924,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Identifier references named import
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent.parent.parent));
const name = (<ImportSpecifier>declaration).propertyName || (<ImportSpecifier>declaration).name;
const identifier = getSourceTextOfNodeFromSourceFile(currentSourceFile, name);
const identifier = getTextOfNodeFromSourceText(currentText, name);
if (languageVersion === ScriptTarget.ES3 && identifier === "default") {
write(`["default"]`);
}
@ -1902,7 +1950,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(node.text);
}
else {
writeTextOfNode(currentSourceFile, node);
writeTextOfNode(currentText, node);
}
}
@ -1943,7 +1991,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(node.text);
}
else {
writeTextOfNode(currentSourceFile, node);
writeTextOfNode(currentText, node);
}
}
@ -2403,7 +2451,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
// The name property of a short-hand property assignment is considered an expression position, so here
// we manually emit the identifier to avoid rewriting.
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
// If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier,
// we emit a normal property assignment. For example:
// module m {
@ -2480,11 +2528,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// 1 .toString is a valid property access, emit a space after the literal
// Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal
let shouldEmitSpace: boolean;
let shouldEmitSpace = false;
if (!indentedBeforeDot) {
if (node.expression.kind === SyntaxKind.NumericLiteral) {
// check if numeric literal was originally written with a dot
const text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression);
const text = getTextOfNodeFromSourceText(currentText, node.expression);
shouldEmitSpace = text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
}
else {
@ -3815,18 +3863,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function nodeStartPositionsAreOnSameLine(node1: Node, node2: Node) {
return getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node1.pos)) ===
getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
return getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node1.pos)) ===
getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos));
}
function nodeEndPositionsAreOnSameLine(node1: Node, node2: Node) {
return getLineOfLocalPosition(currentSourceFile, node1.end) ===
getLineOfLocalPosition(currentSourceFile, node2.end);
return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) ===
getLineOfLocalPositionFromLineMap(currentLineMap, node2.end);
}
function nodeEndIsOnSameLineAsNodeStart(node1: Node, node2: Node) {
return getLineOfLocalPosition(currentSourceFile, node1.end) ===
getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) ===
getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos));
}
function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
@ -3948,7 +3996,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
Debug.assert(!!(node.flags & NodeFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
// only allow export default at a source file level
if (modulekind === ModuleKind.CommonJS || modulekind === ModuleKind.AMD || modulekind === ModuleKind.UMD) {
if (!currentSourceFile.symbol.exports["___esModule"]) {
if (!isEs6Module) {
if (languageVersion === ScriptTarget.ES5) {
// default value of configurable, enumerable, writable are `false`.
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
@ -6304,8 +6352,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression): string {
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
return `"${currentSourceFile.renamedDependencies[moduleName.text]}"`;
if (renamedDependencies && hasProperty(renamedDependencies, moduleName.text)) {
return `"${renamedDependencies[moduleName.text]}"`;
}
return undefined;
}
@ -6467,7 +6515,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// - current file is not external module
// - import declaration is top level and target is value imported by entity name
if (resolver.isReferencedAliasDeclaration(node) ||
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
(!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
emitLeadingComments(node);
emitStart(node);
@ -6712,7 +6760,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
return getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name);
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
@ -7068,7 +7116,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function isCurrentFileSystemExternalModule() {
return modulekind === ModuleKind.System && isExternalModule(currentSourceFile);
return modulekind === ModuleKind.System && isCurrentFileExternalModule;
}
function emitSystemModuleBody(node: SourceFile, dependencyGroups: DependencyGroup[], startIndex: number): void {
@ -7933,7 +7981,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function getLeadingCommentsWithoutDetachedComments() {
// get the leading comments from detachedPos
const leadingComments = getLeadingCommentRanges(currentSourceFile.text,
const leadingComments = getLeadingCommentRanges(currentText,
lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos);
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
@ -7953,10 +8001,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function isTripleSlashComment(comment: CommentRange) {
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
// so that we don't end up computing comment string and doing match for all // comments
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
if (currentText.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
comment.pos + 2 < comment.end &&
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
const textSubStr = currentSourceFile.text.substring(comment.pos, comment.end);
currentText.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
const textSubStr = currentText.substring(comment.pos, comment.end);
return textSubStr.match(fullTripleSlashReferencePathRegEx) ||
textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ?
true : false;
@ -7974,7 +8022,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
else {
// get the leading comments from the node
return getLeadingCommentRangesOfNode(node, currentSourceFile);
return getLeadingCommentRangesOfNodeFromText(node, currentText);
}
}
}
@ -7984,7 +8032,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments
if (node.parent) {
if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
return getTrailingCommentRanges(currentSourceFile.text, node.end);
return getTrailingCommentRanges(currentText, node.end);
}
}
}
@ -8023,10 +8071,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment);
}
function emitTrailingComments(node: Node) {
@ -8038,7 +8086,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
const trailingComments = getTrailingCommentsToEmit(node);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
}
/**
@ -8051,10 +8099,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return;
}
const trailingComments = getTrailingCommentRanges(currentSourceFile.text, pos);
const trailingComments = getTrailingCommentRanges(currentText, pos);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitLeadingCommentsOfPositionWorker(pos: number) {
@ -8069,17 +8117,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
else {
// get the leading comments from the node
leadingComments = getLeadingCommentRanges(currentSourceFile.text, pos);
leadingComments = getLeadingCommentRanges(currentText, pos);
}
emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange) {
const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments);
const currentDetachedCommentInfo = emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments);
if (currentDetachedCommentInfo) {
if (detachedCommentsInfo) {
@ -8092,7 +8140,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function emitShebang() {
const shebang = getShebang(currentSourceFile.text);
const shebang = getShebang(currentText);
if (shebang) {
write(shebang);
}

View file

@ -2,15 +2,18 @@
/// <reference path="utilities.ts"/>
namespace ts {
const nodeConstructors = new Array<new (pos: number, end: number) => Node>(SyntaxKind.Count);
/* @internal */ export let parseTime = 0;
export function getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node {
return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
}
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
return new (getNodeConstructor(kind))(pos, end);
if (kind === SyntaxKind.SourceFile) {
return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
}
else {
return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
}
}
function visitNode<T>(cbNode: (node: Node) => T, node: Node): T {
@ -437,6 +440,10 @@ namespace ts {
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
const disallowInAndDecoratorContext = ParserContextFlags.DisallowIn | ParserContextFlags.Decorator;
// capture constructors in 'initializeState' to avoid null checks
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let sourceFile: SourceFile;
let parseDiagnostics: Diagnostic[];
let syntaxCursor: IncrementalParser.SyntaxCursor;
@ -537,6 +544,9 @@ namespace ts {
}
function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor) {
NodeConstructor = objectAllocator.getNodeConstructor();
SourceFileConstructor = objectAllocator.getSourceFileConstructor();
sourceText = _sourceText;
syntaxCursor = _syntaxCursor;
@ -657,10 +667,11 @@ namespace ts {
}
function createSourceFile(fileName: string, languageVersion: ScriptTarget): SourceFile {
const sourceFile = <SourceFile>createNode(SyntaxKind.SourceFile, /*pos*/ 0);
// code from createNode is inlined here so createNode won't have to deal with special case of creating source files
// this is quite rare comparing to other nodes and createNode should be as fast as possible
const sourceFile = <SourceFile>new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length);
nodeCount++;
sourceFile.pos = 0;
sourceFile.end = sourceText.length;
sourceFile.text = sourceText;
sourceFile.bindDiagnostics = [];
sourceFile.languageVersion = languageVersion;
@ -671,7 +682,7 @@ namespace ts {
return sourceFile;
}
function setContextFlag(val: Boolean, flag: ParserContextFlags) {
function setContextFlag(val: boolean, flag: ParserContextFlags) {
if (val) {
contextFlags |= flag;
}
@ -991,12 +1002,14 @@ namespace ts {
}
}
// note: this function creates only node
function createNode(kind: SyntaxKind, pos?: number): Node {
nodeCount++;
if (!(pos >= 0)) {
pos = scanner.getStartPos();
}
return new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(pos, pos);
return new NodeConstructor(kind, pos, pos);
}
function finishNode<T extends Node>(node: T, end?: number): T {

View file

@ -580,7 +580,7 @@ namespace ts {
function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
let result: CommentRange[];
let collecting = trailing || pos === 0;
while (true) {
while (pos < text.length) {
const ch = text.charCodeAt(pos);
switch (ch) {
case CharacterCodes.carriageReturn:
@ -650,6 +650,8 @@ namespace ts {
}
return result;
}
return result;
}
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
@ -741,7 +743,7 @@ namespace ts {
}
}
function scanNumber(): number {
function scanNumber(): string {
const start = pos;
while (isDigit(text.charCodeAt(pos))) pos++;
if (text.charCodeAt(pos) === CharacterCodes.dot) {
@ -761,7 +763,7 @@ namespace ts {
error(Diagnostics.Digit_expected);
}
}
return +(text.substring(start, end));
return "" + +(text.substring(start, end));
}
function scanOctalDigits(): number {
@ -1229,7 +1231,7 @@ namespace ts {
return pos++, token = SyntaxKind.MinusToken;
case CharacterCodes.dot:
if (isDigit(text.charCodeAt(pos + 1))) {
tokenValue = "" + scanNumber();
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
@ -1343,7 +1345,7 @@ namespace ts {
case CharacterCodes._7:
case CharacterCodes._8:
case CharacterCodes._9:
tokenValue = "" + scanNumber();
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
case CharacterCodes.colon:
return pos++, token = SyntaxKind.ColonToken;

View file

@ -1958,6 +1958,8 @@ namespace ts {
target?: TypeParameter; // Instantiation target
/* @internal */
mapper?: TypeMapper; // Instantiation mapper
/* @internal */
resolvedApparentType: Type;
}
export const enum SignatureKind {

View file

@ -421,18 +421,26 @@ namespace ts {
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
}
export function getLeadingCommentRangesOfNodeFromText(node: Node, text: string) {
return getLeadingCommentRanges(text, node.pos);
}
export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
return getJsDocCommentsFromText(node, sourceFileOfNode.text);
}
export function getJsDocCommentsFromText(node: Node, text: string) {
const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ?
concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) :
getLeadingCommentRangesOfNode(node, sourceFileOfNode);
concatenate(getTrailingCommentRanges(text, node.pos),
getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRangesOfNodeFromText(node, text);
return filter(commentRanges, isJsDocComment);
function isJsDocComment(comment: CommentRange) {
// True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
}
}
@ -1383,8 +1391,8 @@ namespace ts {
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
const simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
const isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.exec(comment)) {
if (isNoDefaultLibRegEx.exec(comment)) {
if (simpleReferenceRegEx.test(comment)) {
if (isNoDefaultLibRegEx.test(comment)) {
return {
isNoDefaultLib: true
};
@ -1689,7 +1697,7 @@ namespace ts {
export interface EmitTextWriter {
write(s: string): void;
writeTextOfNode(sourceFile: SourceFile, node: Node): void;
writeTextOfNode(text: string, node: Node): void;
writeLine(): void;
increaseIndent(): void;
decreaseIndent(): void;
@ -1700,6 +1708,7 @@ namespace ts {
getLine(): number;
getColumn(): number;
getIndent(): number;
reset(): void;
}
const indentStrings: string[] = ["", " "];
@ -1715,11 +1724,11 @@ namespace ts {
}
export function createTextWriter(newLine: String): EmitTextWriter {
let output = "";
let indent = 0;
let lineStart = true;
let lineCount = 0;
let linePos = 0;
let output: string;
let indent: number;
let lineStart: boolean;
let lineCount: number;
let linePos: number;
function write(s: string) {
if (s && s.length) {
@ -1731,6 +1740,14 @@ namespace ts {
}
}
function reset(): void {
output = "";
indent = 0;
lineStart = true;
lineCount = 0;
linePos = 0;
}
function rawWrite(s: string) {
if (s !== undefined) {
if (lineStart) {
@ -1760,10 +1777,12 @@ namespace ts {
}
}
function writeTextOfNode(sourceFile: SourceFile, node: Node) {
write(getSourceTextOfNodeFromSourceFile(sourceFile, node));
function writeTextOfNode(text: string, node: Node) {
write(getTextOfNodeFromSourceText(text, node));
}
reset();
return {
write,
rawWrite,
@ -1777,6 +1796,7 @@ namespace ts {
getLine: () => lineCount + 1,
getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
getText: () => output,
reset
};
}
@ -1809,6 +1829,10 @@ namespace ts {
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
}
export function getLineOfLocalPositionFromLineMap(lineMap: number[], pos: number) {
return computeLineAndCharacterOfPosition(lineMap, pos).line;
}
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
return forEach(node.members, member => {
if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) {
@ -1883,23 +1907,23 @@ namespace ts {
};
}
export function emitNewLineBeforeLeadingComments(currentSourceFile: SourceFile, writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
// If the leading comments start on different line than the start of node, write new line
if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
writer.writeLine();
}
}
export function emitComments(currentSourceFile: SourceFile, writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
export function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
let emitLeadingSpace = !trailingSeparator;
forEach(comments, comment => {
if (emitLeadingSpace) {
writer.write(" ");
emitLeadingSpace = false;
}
writeComment(currentSourceFile, writer, comment, newLine);
writeComment(text, lineMap, writer, comment, newLine);
if (comment.hasTrailingNewLine) {
writer.writeLine();
}
@ -1917,8 +1941,8 @@ namespace ts {
* Detached comment is a comment at the top of file or function body that is separated from
* the next statement by space.
*/
export function emitDetachedComments(currentSourceFile: SourceFile, writer: EmitTextWriter,
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void,
export function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter,
writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void,
node: TextRange, newLine: string, removeComments: boolean) {
let leadingComments: CommentRange[];
let currentDetachedCommentInfo: {nodePos: number, detachedCommentEndPos: number};
@ -1929,12 +1953,12 @@ namespace ts {
//
// var x = 10;
if (node.pos === 0) {
leadingComments = filter(getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment);
leadingComments = filter(getLeadingCommentRanges(text, node.pos), isPinnedComment);
}
}
else {
// removeComments is false, just get detached as normal and bypass the process to filter comment
leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos);
leadingComments = getLeadingCommentRanges(text, node.pos);
}
if (leadingComments) {
@ -1943,8 +1967,8 @@ namespace ts {
for (const comment of leadingComments) {
if (lastComment) {
const lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end);
const commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos);
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end);
const commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos);
if (commentLine >= lastCommentLine + 2) {
// There was a blank line between the last comment and this comment. This
@ -1962,12 +1986,12 @@ namespace ts {
// All comments look like they could have been part of the copyright header. Make
// sure there is at least one blank line between it and the node. If not, it's not
// a copyright header.
const lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastOrUndefined(detachedComments).end);
const nodeLine = getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node.pos));
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastOrUndefined(detachedComments).end);
const nodeLine = getLineOfLocalPositionFromLineMap(lineMap, skipTrivia(text, node.pos));
if (nodeLine >= lastCommentLine + 2) {
// Valid detachedComments
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments);
emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end };
}
}
@ -1976,25 +2000,26 @@ namespace ts {
return currentDetachedCommentInfo;
function isPinnedComment(comment: CommentRange) {
return currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
}
}
export function writeCommentRange(currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
const firstCommentLineAndCharacter = getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
const lineCount = getLineStarts(currentSourceFile).length;
export function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
if (text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, comment.pos);
const lineCount = lineMap.length;
let firstCommentLineIndent: number;
for (let pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
const nextLineStart = (currentLine + 1) === lineCount
? currentSourceFile.text.length + 1
: getStartPositionOfLine(currentLine + 1, currentSourceFile);
? text.length + 1
: lineMap[currentLine + 1];
if (pos !== comment.pos) {
// If we are not emitting first line, we need to write the spaces to adjust the alignment
if (firstCommentLineIndent === undefined) {
firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos);
}
// These are number of spaces writer is going to write at current indent
@ -2014,7 +2039,7 @@ namespace ts {
// More right indented comment */ --4 = 8 - 4 + 11
// class c { }
// }
const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart);
if (spacesToEmit > 0) {
let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
const indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
@ -2035,47 +2060,47 @@ namespace ts {
}
// Write the comment line text
writeTrimmedCurrentLine(pos, nextLineStart);
writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart);
pos = nextLineStart;
}
}
else {
// Single line comment of style //....
writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
writer.write(text.substring(comment.pos, comment.end));
}
}
function writeTrimmedCurrentLine(pos: number, nextLineStart: number) {
const end = Math.min(comment.end, nextLineStart - 1);
const currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, "");
if (currentLineText) {
// trimmed forward and ending spaces text
writer.write(currentLineText);
if (end !== comment.end) {
writer.writeLine();
}
function writeTrimmedCurrentLine(text: string, comment: CommentRange, writer: EmitTextWriter, newLine: string, pos: number, nextLineStart: number) {
const end = Math.min(comment.end, nextLineStart - 1);
const currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, "");
if (currentLineText) {
// trimmed forward and ending spaces text
writer.write(currentLineText);
if (end !== comment.end) {
writer.writeLine();
}
}
else {
// Empty string - make sure we write empty line
writer.writeLiteral(newLine);
}
}
function calculateIndent(text: string, pos: number, end: number) {
let currentLineIndent = 0;
for (; pos < end && isWhiteSpace(text.charCodeAt(pos)); pos++) {
if (text.charCodeAt(pos) === CharacterCodes.tab) {
// Tabs = TabSize = indent size and go to next tabStop
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
}
else {
// Empty string - make sure we write empty line
writer.writeLiteral(newLine);
// Single space
currentLineIndent++;
}
}
function calculateIndent(pos: number, end: number) {
let currentLineIndent = 0;
for (; pos < end && isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
if (currentSourceFile.text.charCodeAt(pos) === CharacterCodes.tab) {
// Tabs = TabSize = indent size and go to next tabStop
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
}
else {
// Single space
currentLineIndent++;
}
}
return currentLineIndent;
}
return currentLineIndent;
}
export function modifierToFlag(token: SyntaxKind): NodeFlags {

View file

@ -174,7 +174,7 @@ namespace ts {
let jsDocCompletionEntries: CompletionEntry[];
function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
let node = <NodeObject> new (getNodeConstructor(kind))(pos, end);
let node = new NodeObject(kind, pos, end);
node.flags = flags;
node.parent = parent;
return node;
@ -188,6 +188,14 @@ namespace ts {
public parent: Node;
private _children: Node[];
constructor(kind: SyntaxKind, pos: number, end: number) {
this.kind = kind;
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
public getSourceFile(): SourceFile {
return getSourceFileOfNode(this);
}
@ -805,6 +813,10 @@ namespace ts {
public imports: LiteralExpression[];
private namedDeclarations: Map<Declaration[]>;
constructor(kind: SyntaxKind, pos: number, end: number) {
super(kind, pos, end)
}
public update(newText: string, textChangeRange: TextChangeRange): SourceFile {
return updateSourceFile(this, newText, textChangeRange);
}
@ -7970,18 +7982,8 @@ namespace ts {
function initializeServices() {
objectAllocator = {
getNodeConstructor: kind => {
function Node(pos: number, end: number) {
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
let proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject();
proto.kind = kind;
Node.prototype = proto;
return <any>Node;
},
getNodeConstructor: () => NodeObject,
getSourceFileConstructor: () => SourceFileObject,
getSymbolConstructor: () => SymbolObject,
getTypeConstructor: () => TypeObject,
getSignatureConstructor: () => SignatureObject,

View file

@ -1032,7 +1032,7 @@ namespace ts {
public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim {
try {
if (this.documentRegistry === undefined) {
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory());
}
var hostAdapter = new LanguageServiceShimHostAdapter(host);
var languageService = createLanguageService(hostAdapter, this.documentRegistry);
@ -1068,7 +1068,7 @@ namespace ts {
public close(): void {
// Forget all the registered shims
this._shims = [];
this.documentRegistry = createDocumentRegistry();
this.documentRegistry = undefined;
}
public registerShim(shim: Shim): void {

View file

@ -4,6 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,20): error TS2322: Type '{ anything: number; on
Types of property 'oneI' are incompatible.
Type 'this' is not assignable to type 'I'.
Type 'C' is not assignable to type 'I'.
Property 'alsoWorks' is missing in type 'C'.
tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this; }' nor type 'R' is assignable to the other.
Property 'anything' is missing in type '{ oneI: this; }'.
@ -38,6 +39,7 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this;
!!! error TS2322: Types of property 'oneI' are incompatible.
!!! error TS2322: Type 'this' is not assignable to type 'I'.
!!! error TS2322: Type 'C' is not assignable to type 'I'.
!!! error TS2322: Property 'alsoWorks' is missing in type 'C'.
}
worksToo():R {

View file

@ -63,7 +63,7 @@ if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
} else if (elementA instanceof Match && elementB instanceof Match) {
>elementA instanceof Match && elementB instanceof Match : boolean
>elementA instanceof Match : boolean
>elementA : FileMatch | Match
>elementA : Match | FileMatch
>Match : typeof Match
>elementB instanceof Match : boolean
>elementB : FileMatch | Match

View file

@ -0,0 +1,50 @@
//// [thisTypeAndConstraints.ts]
class A {
self() {
return this;
}
}
function f<T extends A>(x: T) {
function g<U extends T>(x: U) {
x = x.self();
}
x = x.self();
}
class B<T extends A> {
foo(x: T) {
x = x.self();
}
bar<U extends T>(x: U) {
x = x.self();
}
}
//// [thisTypeAndConstraints.js]
var A = (function () {
function A() {
}
A.prototype.self = function () {
return this;
};
return A;
})();
function f(x) {
function g(x) {
x = x.self();
}
x = x.self();
}
var B = (function () {
function B() {
}
B.prototype.foo = function (x) {
x = x.self();
};
B.prototype.bar = function (x) {
x = x.self();
};
return B;
})();

View file

@ -0,0 +1,70 @@
=== tests/cases/conformance/types/thisType/thisTypeAndConstraints.ts ===
class A {
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
self() {
>self : Symbol(self, Decl(thisTypeAndConstraints.ts, 0, 9))
return this;
>this : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
}
}
function f<T extends A>(x: T) {
>f : Symbol(f, Decl(thisTypeAndConstraints.ts, 4, 1))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
function g<U extends T>(x: U) {
>g : Symbol(g, Decl(thisTypeAndConstraints.ts, 6, 31))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 7, 15))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 7, 15))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
class B<T extends A> {
>B : Symbol(B, Decl(thisTypeAndConstraints.ts, 11, 1))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
foo(x: T) {
>foo : Symbol(foo, Decl(thisTypeAndConstraints.ts, 13, 22))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
bar<U extends T>(x: U) {
>bar : Symbol(bar, Decl(thisTypeAndConstraints.ts, 16, 5))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 17, 8))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 17, 8))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
}

View file

@ -0,0 +1,78 @@
=== tests/cases/conformance/types/thisType/thisTypeAndConstraints.ts ===
class A {
>A : A
self() {
>self : () => this
return this;
>this : this
}
}
function f<T extends A>(x: T) {
>f : <T extends A>(x: T) => void
>T : T
>A : A
>x : T
>T : T
function g<U extends T>(x: U) {
>g : <U extends T>(x: U) => void
>U : U
>T : T
>x : U
>U : U
x = x.self();
>x = x.self() : U
>x : U
>x.self() : U
>x.self : () => U
>x : U
>self : () => U
}
x = x.self();
>x = x.self() : T
>x : T
>x.self() : T
>x.self : () => T
>x : T
>self : () => T
}
class B<T extends A> {
>B : B<T>
>T : T
>A : A
foo(x: T) {
>foo : (x: T) => void
>x : T
>T : T
x = x.self();
>x = x.self() : T
>x : T
>x.self() : T
>x.self : () => T
>x : T
>self : () => T
}
bar<U extends T>(x: U) {
>bar : <U extends T>(x: U) => void
>U : U
>T : T
>x : U
>U : U
x = x.self();
>x = x.self() : U
>x : U
>x.self() : U
>x.self : () => U
>x : U
>self : () => U
}
}

View file

@ -1,57 +0,0 @@
tests/cases/conformance/types/thisType/thisTypeInClasses.ts(4,20): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
==== tests/cases/conformance/types/thisType/thisTypeInClasses.ts (1 errors) ====
class C1 {
x: this;
f(x: this): this { return undefined; }
constructor(x: this) { }
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
}
class C2 {
[x: string]: this;
}
interface Foo<T> {
x: T;
y: this;
}
class C3 {
a: this[];
b: [this, this];
c: this | Date;
d: this & Date;
e: (((this)));
f: (x: this) => this;
g: new (x: this) => this;
h: Foo<this>;
i: Foo<this | (() => this)>;
j: (x: any) => x is this;
}
declare class C4 {
x: this;
f(x: this): this;
}
class C5 {
foo() {
let f1 = (x: this): this => this;
let f2 = (x: this) => this;
let f3 = (x: this) => (y: this) => this;
let f4 = (x: this) => {
let g = (y: this) => {
return () => this;
}
return g(this);
}
}
bar() {
let x1 = <this>undefined;
let x2 = undefined as this;
}
}

View file

@ -2,7 +2,6 @@
class C1 {
x: this;
f(x: this): this { return undefined; }
constructor(x: this) { }
}
class C2 {
@ -53,7 +52,7 @@ class C5 {
//// [thisTypeInClasses.js]
var C1 = (function () {
function C1(x) {
function C1() {
}
C1.prototype.f = function (x) { return undefined; };
return C1;

View file

@ -9,131 +9,128 @@ class C1 {
>f : Symbol(f, Decl(thisTypeInClasses.ts, 1, 12))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 2, 6))
>undefined : Symbol(undefined)
constructor(x: this) { }
>x : Symbol(x, Decl(thisTypeInClasses.ts, 3, 16))
}
class C2 {
>C2 : Symbol(C2, Decl(thisTypeInClasses.ts, 4, 1))
>C2 : Symbol(C2, Decl(thisTypeInClasses.ts, 3, 1))
[x: string]: this;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 7, 5))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 6, 5))
}
interface Foo<T> {
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 10, 14))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 9, 14))
x: T;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 10, 18))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 10, 14))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 9, 18))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 9, 14))
y: this;
>y : Symbol(y, Decl(thisTypeInClasses.ts, 11, 9))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 10, 9))
}
class C3 {
>C3 : Symbol(C3, Decl(thisTypeInClasses.ts, 13, 1))
>C3 : Symbol(C3, Decl(thisTypeInClasses.ts, 12, 1))
a: this[];
>a : Symbol(a, Decl(thisTypeInClasses.ts, 15, 10))
>a : Symbol(a, Decl(thisTypeInClasses.ts, 14, 10))
b: [this, this];
>b : Symbol(b, Decl(thisTypeInClasses.ts, 16, 14))
>b : Symbol(b, Decl(thisTypeInClasses.ts, 15, 14))
c: this | Date;
>c : Symbol(c, Decl(thisTypeInClasses.ts, 17, 20))
>c : Symbol(c, Decl(thisTypeInClasses.ts, 16, 20))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
d: this & Date;
>d : Symbol(d, Decl(thisTypeInClasses.ts, 18, 19))
>d : Symbol(d, Decl(thisTypeInClasses.ts, 17, 19))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
e: (((this)));
>e : Symbol(e, Decl(thisTypeInClasses.ts, 19, 19))
>e : Symbol(e, Decl(thisTypeInClasses.ts, 18, 19))
f: (x: this) => this;
>f : Symbol(f, Decl(thisTypeInClasses.ts, 20, 18))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 21, 8))
>f : Symbol(f, Decl(thisTypeInClasses.ts, 19, 18))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 20, 8))
g: new (x: this) => this;
>g : Symbol(g, Decl(thisTypeInClasses.ts, 21, 25))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 22, 12))
>g : Symbol(g, Decl(thisTypeInClasses.ts, 20, 25))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 21, 12))
h: Foo<this>;
>h : Symbol(h, Decl(thisTypeInClasses.ts, 22, 29))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1))
>h : Symbol(h, Decl(thisTypeInClasses.ts, 21, 29))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
i: Foo<this | (() => this)>;
>i : Symbol(i, Decl(thisTypeInClasses.ts, 23, 17))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1))
>i : Symbol(i, Decl(thisTypeInClasses.ts, 22, 17))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
j: (x: any) => x is this;
>j : Symbol(j, Decl(thisTypeInClasses.ts, 24, 32))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 25, 8))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 25, 8))
>j : Symbol(j, Decl(thisTypeInClasses.ts, 23, 32))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 24, 8))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 24, 8))
}
declare class C4 {
>C4 : Symbol(C4, Decl(thisTypeInClasses.ts, 26, 1))
>C4 : Symbol(C4, Decl(thisTypeInClasses.ts, 25, 1))
x: this;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 28, 18))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 27, 18))
f(x: this): this;
>f : Symbol(f, Decl(thisTypeInClasses.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 30, 6))
>f : Symbol(f, Decl(thisTypeInClasses.ts, 28, 12))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 29, 6))
}
class C5 {
>C5 : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>C5 : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
foo() {
>foo : Symbol(foo, Decl(thisTypeInClasses.ts, 33, 10))
>foo : Symbol(foo, Decl(thisTypeInClasses.ts, 32, 10))
let f1 = (x: this): this => this;
>f1 : Symbol(f1, Decl(thisTypeInClasses.ts, 35, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 35, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>f1 : Symbol(f1, Decl(thisTypeInClasses.ts, 34, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 34, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f2 = (x: this) => this;
>f2 : Symbol(f2, Decl(thisTypeInClasses.ts, 36, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 36, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>f2 : Symbol(f2, Decl(thisTypeInClasses.ts, 35, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 35, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f3 = (x: this) => (y: this) => this;
>f3 : Symbol(f3, Decl(thisTypeInClasses.ts, 37, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 37, 18))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 37, 31))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>f3 : Symbol(f3, Decl(thisTypeInClasses.ts, 36, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 36, 18))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 36, 31))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f4 = (x: this) => {
>f4 : Symbol(f4, Decl(thisTypeInClasses.ts, 38, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 38, 18))
>f4 : Symbol(f4, Decl(thisTypeInClasses.ts, 37, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 37, 18))
let g = (y: this) => {
>g : Symbol(g, Decl(thisTypeInClasses.ts, 39, 15))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 39, 21))
>g : Symbol(g, Decl(thisTypeInClasses.ts, 38, 15))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 38, 21))
return () => this;
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
}
return g(this);
>g : Symbol(g, Decl(thisTypeInClasses.ts, 39, 15))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1))
>g : Symbol(g, Decl(thisTypeInClasses.ts, 38, 15))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
}
}
bar() {
>bar : Symbol(bar, Decl(thisTypeInClasses.ts, 44, 5))
>bar : Symbol(bar, Decl(thisTypeInClasses.ts, 43, 5))
let x1 = <this>undefined;
>x1 : Symbol(x1, Decl(thisTypeInClasses.ts, 46, 11))
>x1 : Symbol(x1, Decl(thisTypeInClasses.ts, 45, 11))
>undefined : Symbol(undefined)
let x2 = undefined as this;
>x2 : Symbol(x2, Decl(thisTypeInClasses.ts, 47, 11))
>x2 : Symbol(x2, Decl(thisTypeInClasses.ts, 46, 11))
>undefined : Symbol(undefined)
}
}

View file

@ -9,9 +9,6 @@ class C1 {
>f : (x: this) => this
>x : this
>undefined : undefined
constructor(x: this) { }
>x : this
}
class C2 {

View file

@ -14,21 +14,58 @@ class C2 {
class D1 extends C1 {
p3: number;
}
class C3 {
p4: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var ctor1: C1 | C2;
str = ctor1 instanceof C1 && ctor1.p1; // C1
num = ctor1 instanceof C2 && ctor1.p2; // C2
str = ctor1 instanceof D1 && ctor1.p1; // D1
num = ctor1 instanceof D1 && ctor1.p3; // D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
var ctor2: C2 | D1;
num = ctor2 instanceof C2 && ctor2.p2; // C2
num = ctor2 instanceof D1 && ctor2.p3; // D1
str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var ctor3: C1 | C2;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4: C1 | C2 | C3;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5: C1 | D1 | C2;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6: C1 | C2 | C3;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}
//// [typeGuardOfFormInstanceOf.js]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
@ -58,16 +95,51 @@ var D1 = (function (_super) {
}
return D1;
})(C1);
var C3 = (function () {
function C3() {
}
return C3;
})();
var str;
var num;
var strOrNum;
var c1Orc2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var c2Ord1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
var ctor1;
str = ctor1 instanceof C1 && ctor1.p1; // C1
num = ctor1 instanceof C2 && ctor1.p2; // C2
str = ctor1 instanceof D1 && ctor1.p1; // D1
num = ctor1 instanceof D1 && ctor1.p3; // D1
var ctor2;
num = ctor2 instanceof C2 && ctor2.p2; // C2
num = ctor2 instanceof D1 && ctor2.p3; // D1
str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var ctor3;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}

View file

@ -24,86 +24,184 @@ class D1 extends C1 {
p3: number;
>p3 : Symbol(p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
}
class C3 {
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
p4: number;
>p4 : Symbol(p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}
var str: string;
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3))
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
var num: number;
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3))
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
var strOrNum: string | number;
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 17, 3))
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 20, 3))
var c1Orc2: C1 | C2;
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
var ctor1: C1 | C2;
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
str = ctor1 instanceof C1 && ctor1.p1; // C1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
num = ctor1 instanceof C2 && ctor1.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c1Orc2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
str = ctor1 instanceof D1 && ctor1.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
num = ctor1 instanceof D1 && ctor1.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c1Orc2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
var c2Ord1: C2 | D1;
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
var ctor2: C2 | D1;
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
num = ctor2 instanceof C2 && ctor2.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c2Ord1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
>ctor2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
num = ctor2 instanceof D1 && ctor2.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c2Ord1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
>ctor2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
str = ctor2 instanceof D1 && ctor2.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c2Ord1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
>ctor2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
>r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 29, 3))
var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
>r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 32, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3))
>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
var ctor3: C1 | C2;
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
if (ctor3 instanceof C1) {
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor3.p1; // C1
>ctor3.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else {
ctor3.p2; // C2
>ctor3.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
var ctor4: C1 | C2 | C3;
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
if (ctor4 instanceof C1) {
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor4.p1; // C1
>ctor4.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else if (ctor4 instanceof C2) {
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
ctor4.p2; // C2
>ctor4.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
else {
ctor4.p4; // C3
>ctor4.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}
var ctor5: C1 | D1 | C2;
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
if (ctor5 instanceof C1) {
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor5.p1; // C1
>ctor5.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else {
ctor5.p2; // C2
>ctor5.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
var ctor6: C1 | C2 | C3;
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
}
else {
ctor6.p4; // C3
>ctor6.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}

View file

@ -24,6 +24,12 @@ class D1 extends C1 {
p3: number;
>p3 : number
}
class C3 {
>C3 : C3
p4: number;
>p4 : number
}
var str: string;
>str : string
@ -33,100 +39,199 @@ var num: number;
var strOrNum: string | number;
>strOrNum : string | number
var c1Orc2: C1 | C2;
>c1Orc2 : C1 | C2
var ctor1: C1 | C2;
>ctor1 : C1 | C2
>C1 : C1
>C2 : C2
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
>str = c1Orc2 instanceof C1 && c1Orc2.p1 : string
str = ctor1 instanceof C1 && ctor1.p1; // C1
>str = ctor1 instanceof C1 && ctor1.p1 : string
>str : string
>c1Orc2 instanceof C1 && c1Orc2.p1 : string
>c1Orc2 instanceof C1 : boolean
>c1Orc2 : C1 | C2
>ctor1 instanceof C1 && ctor1.p1 : string
>ctor1 instanceof C1 : boolean
>ctor1 : C1 | C2
>C1 : typeof C1
>c1Orc2.p1 : string
>c1Orc2 : C1
>ctor1.p1 : string
>ctor1 : C1
>p1 : string
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
>num = c1Orc2 instanceof C2 && c1Orc2.p2 : number
num = ctor1 instanceof C2 && ctor1.p2; // C2
>num = ctor1 instanceof C2 && ctor1.p2 : number
>num : number
>c1Orc2 instanceof C2 && c1Orc2.p2 : number
>c1Orc2 instanceof C2 : boolean
>c1Orc2 : C1 | C2
>ctor1 instanceof C2 && ctor1.p2 : number
>ctor1 instanceof C2 : boolean
>ctor1 : C1 | C2
>C2 : typeof C2
>c1Orc2.p2 : number
>c1Orc2 : C2
>ctor1.p2 : number
>ctor1 : C2
>p2 : number
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
>str = c1Orc2 instanceof D1 && c1Orc2.p1 : string
str = ctor1 instanceof D1 && ctor1.p1; // D1
>str = ctor1 instanceof D1 && ctor1.p1 : string
>str : string
>c1Orc2 instanceof D1 && c1Orc2.p1 : string
>c1Orc2 instanceof D1 : boolean
>c1Orc2 : C1 | C2
>ctor1 instanceof D1 && ctor1.p1 : string
>ctor1 instanceof D1 : boolean
>ctor1 : C1 | C2
>D1 : typeof D1
>c1Orc2.p1 : string
>c1Orc2 : D1
>ctor1.p1 : string
>ctor1 : D1
>p1 : string
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
>num = c1Orc2 instanceof D1 && c1Orc2.p3 : number
num = ctor1 instanceof D1 && ctor1.p3; // D1
>num = ctor1 instanceof D1 && ctor1.p3 : number
>num : number
>c1Orc2 instanceof D1 && c1Orc2.p3 : number
>c1Orc2 instanceof D1 : boolean
>c1Orc2 : C1 | C2
>ctor1 instanceof D1 && ctor1.p3 : number
>ctor1 instanceof D1 : boolean
>ctor1 : C1 | C2
>D1 : typeof D1
>c1Orc2.p3 : number
>c1Orc2 : D1
>ctor1.p3 : number
>ctor1 : D1
>p3 : number
var c2Ord1: C2 | D1;
>c2Ord1 : C2 | D1
var ctor2: C2 | D1;
>ctor2 : C2 | D1
>C2 : C2
>D1 : D1
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
>num = c2Ord1 instanceof C2 && c2Ord1.p2 : number
num = ctor2 instanceof C2 && ctor2.p2; // C2
>num = ctor2 instanceof C2 && ctor2.p2 : number
>num : number
>c2Ord1 instanceof C2 && c2Ord1.p2 : number
>c2Ord1 instanceof C2 : boolean
>c2Ord1 : C2 | D1
>ctor2 instanceof C2 && ctor2.p2 : number
>ctor2 instanceof C2 : boolean
>ctor2 : C2 | D1
>C2 : typeof C2
>c2Ord1.p2 : number
>c2Ord1 : C2
>ctor2.p2 : number
>ctor2 : C2
>p2 : number
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
>num = c2Ord1 instanceof D1 && c2Ord1.p3 : number
num = ctor2 instanceof D1 && ctor2.p3; // D1
>num = ctor2 instanceof D1 && ctor2.p3 : number
>num : number
>c2Ord1 instanceof D1 && c2Ord1.p3 : number
>c2Ord1 instanceof D1 : boolean
>c2Ord1 : C2 | D1
>ctor2 instanceof D1 && ctor2.p3 : number
>ctor2 instanceof D1 : boolean
>ctor2 : C2 | D1
>D1 : typeof D1
>c2Ord1.p3 : number
>c2Ord1 : D1
>ctor2.p3 : number
>ctor2 : D1
>p3 : number
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
>str = c2Ord1 instanceof D1 && c2Ord1.p1 : string
str = ctor2 instanceof D1 && ctor2.p1; // D1
>str = ctor2 instanceof D1 && ctor2.p1 : string
>str : string
>c2Ord1 instanceof D1 && c2Ord1.p1 : string
>c2Ord1 instanceof D1 : boolean
>c2Ord1 : C2 | D1
>ctor2 instanceof D1 && ctor2.p1 : string
>ctor2 instanceof D1 : boolean
>ctor2 : C2 | D1
>D1 : typeof D1
>c2Ord1.p1 : string
>c2Ord1 : D1
>ctor2.p1 : string
>ctor2 : D1
>p1 : string
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
>r2 : D1 | C2
>D1 : D1
>C2 : C2
>c2Ord1 instanceof C1 && c2Ord1 : D1
>c2Ord1 instanceof C1 : boolean
>c2Ord1 : C2 | D1
>ctor2 instanceof C1 && ctor2 : D1
>ctor2 instanceof C1 : boolean
>ctor2 : C2 | D1
>C1 : typeof C1
>c2Ord1 : D1
>ctor2 : D1
var ctor3: C1 | C2;
>ctor3 : C1 | C2
>C1 : C1
>C2 : C2
if (ctor3 instanceof C1) {
>ctor3 instanceof C1 : boolean
>ctor3 : C1 | C2
>C1 : typeof C1
ctor3.p1; // C1
>ctor3.p1 : string
>ctor3 : C1
>p1 : string
}
else {
ctor3.p2; // C2
>ctor3.p2 : number
>ctor3 : C2
>p2 : number
}
var ctor4: C1 | C2 | C3;
>ctor4 : C1 | C2 | C3
>C1 : C1
>C2 : C2
>C3 : C3
if (ctor4 instanceof C1) {
>ctor4 instanceof C1 : boolean
>ctor4 : C1 | C2 | C3
>C1 : typeof C1
ctor4.p1; // C1
>ctor4.p1 : string
>ctor4 : C1
>p1 : string
}
else if (ctor4 instanceof C2) {
>ctor4 instanceof C2 : boolean
>ctor4 : C2 | C3
>C2 : typeof C2
ctor4.p2; // C2
>ctor4.p2 : number
>ctor4 : C2
>p2 : number
}
else {
ctor4.p4; // C3
>ctor4.p4 : number
>ctor4 : C3
>p4 : number
}
var ctor5: C1 | D1 | C2;
>ctor5 : C1 | D1 | C2
>C1 : C1
>D1 : D1
>C2 : C2
if (ctor5 instanceof C1) {
>ctor5 instanceof C1 : boolean
>ctor5 : C1 | D1 | C2
>C1 : typeof C1
ctor5.p1; // C1
>ctor5.p1 : string
>ctor5 : C1
>p1 : string
}
else {
ctor5.p2; // C2
>ctor5.p2 : number
>ctor5 : C2
>p2 : number
}
var ctor6: C1 | C2 | C3;
>ctor6 : C1 | C2 | C3
>C1 : C1
>C2 : C2
>C3 : C3
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
>ctor6 instanceof C1 || ctor6 instanceof C2 : boolean
>ctor6 instanceof C1 : boolean
>ctor6 : C1 | C2 | C3
>C1 : typeof C1
>ctor6 instanceof C2 : boolean
>ctor6 : C2 | C3
>C2 : typeof C2
}
else {
ctor6.p4; // C3
>ctor6.p4 : number
>ctor6 : C3
>p4 : number
}

View file

@ -0,0 +1,41 @@
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(10,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(20,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(23,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(25,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/conformance/types/union/unionTypeCallSignatures4.ts (4 errors) ====
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
f12345("a", "b");
f12345("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.

View file

@ -0,0 +1,45 @@
//// [unionTypeCallSignatures4.ts]
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error
//// [unionTypeCallSignatures4.js]
var f12;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error

View file

@ -13,18 +13,55 @@ class C2 {
class D1 extends C1 {
p3: number;
}
class C3 {
p4: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var ctor1: C1 | C2;
str = ctor1 instanceof C1 && ctor1.p1; // C1
num = ctor1 instanceof C2 && ctor1.p2; // C2
str = ctor1 instanceof D1 && ctor1.p1; // D1
num = ctor1 instanceof D1 && ctor1.p3; // D1
var ctor2: C2 | D1;
num = ctor2 instanceof C2 && ctor2.p2; // C2
num = ctor2 instanceof D1 && ctor2.p3; // D1
str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
var ctor3: C1 | C2;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4: C1 | C2 | C3;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5: C1 | D1 | C2;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6: C1 | C2 | C3;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}

View file

@ -0,0 +1,21 @@
class A {
self() {
return this;
}
}
function f<T extends A>(x: T) {
function g<U extends T>(x: U) {
x = x.self();
}
x = x.self();
}
class B<T extends A> {
foo(x: T) {
x = x.self();
}
bar<U extends T>(x: U) {
x = x.self();
}
}

View file

@ -1,7 +1,6 @@
class C1 {
x: this;
f(x: this): this { return undefined; }
constructor(x: this) { }
}
class C2 {

View file

@ -0,0 +1,25 @@
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error