diff --git a/package.json b/package.json index 2079c41fdd4..52dabc79f6e 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,11 @@ "build:compiler": "jake local", "build:tests": "jake tests", "clean": "jake clean" - } + }, + "browser": { + "buffer": false, + "fs": false, + "os": false, + "path": false + } } diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 50ba634b58d..340bf478209 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -74,7 +74,7 @@ namespace ts { // If the current node is a container that also container that also contains locals. Examples: // // Functions, Methods, Modules, Source-files. - IsContainerWithLocals = IsContainer | HasLocals + IsContainerWithLocals = IsContainer | HasLocals } export function bindSourceFile(file: SourceFile) { @@ -1062,4 +1062,4 @@ namespace ts { : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } } -} +} diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c185e0e2326..fd4cc741076 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3122,52 +3122,66 @@ namespace ts { setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType); } - function findMatchingSignature(signature: Signature, signatureList: Signature[]): Signature { - for (let s of signatureList) { - // Only signatures with no type parameters may differ in return types - if (compareSignatures(signature, s, /*compareReturnTypes*/ !!signature.typeParameters, compareTypes)) { + function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { + for (let s of signatureList) { + if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) { return s; } } } - function findMatchingSignatures(signature: Signature, signatureLists: Signature[][]): Signature[] { + function findMatchingSignatures(signatureLists: Signature[][], signature: Signature, listIndex: number): Signature[] { + if (signature.typeParameters) { + // We require an exact match for generic signatures, so we only return signatures from the first + // signature list and only if they have exact matches in the other signature lists. + if (listIndex > 0) { + return undefined; + } + for (let i = 1; i < signatureLists.length; i++) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ false)) { + return undefined; + } + } + return [signature]; + } let result: Signature[] = undefined; - for (let i = 1; i < signatureLists.length; i++) { - let match = findMatchingSignature(signature, signatureLists[i]); + for (let i = 0; i < signatureLists.length; i++) { + // Allow matching non-generic signatures to have excess parameters and different return types + let match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } - if (!result) { - result = [signature]; - } - if (match !== signature) { - result.push(match); + if (!contains(result, match)) { + (result || (result = [])).push(match); } } return result; } - // The signatures of a union type are those signatures that are present and identical in each of the - // constituent types, except that non-generic signatures may differ in return types. When signatures - // differ in return types, the resulting return type is the union of the constituent return types. + // The signatures of a union type are those signatures that are present in each of the constituent types. + // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional + // parameters and may differ in return types. When signatures differ in return types, the resulting return + // type is the union of the constituent return types. function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] { let signatureLists = map(types, t => getSignaturesOfType(t, kind)); let result: Signature[] = undefined; - for (let source of signatureLists[0]) { - let unionSignatures = findMatchingSignatures(source, signatureLists); - if (unionSignatures) { - let signature: Signature = undefined; - if (unionSignatures.length === 1 || source.typeParameters) { - signature = source; + for (let i = 0; i < signatureLists.length; i++) { + for (let signature of signatureLists[i]) { + // Only process signatures with parameter lists that aren't already in the result list + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true)) { + let unionSignatures = findMatchingSignatures(signatureLists, signature, i); + if (unionSignatures) { + let s = signature; + // Union the result types when more than one signature matches + if (unionSignatures.length > 1) { + s = cloneSignature(signature); + // Clear resolved return type we possibly got from cloneSignature + s.resolvedReturnType = undefined; + s.unionSignatures = unionSignatures; + } + (result || (result = [])).push(s); + } } - else { - signature = cloneSignature(source); - // Clear resolved return type we possibly got from cloneSignature - signature.resolvedReturnType = undefined; - signature.unionSignatures = unionSignatures; - } - (result || (result = [])).push(signature); } } return result || emptyArray; @@ -3465,8 +3479,10 @@ namespace ts { return emptyArray; } - // Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and - // maps primitive types and type parameters are to their apparent types. + /** + * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and + * maps primitive types and type parameters are to their apparent types. + */ function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] { return getSignaturesOfStructuredType(getApparentType(type), kind); } @@ -5081,30 +5097,24 @@ namespace ts { let result = Ternary.True; let saveErrorInfo = errorInfo; - // Because the "abstractness" of a class is the same across all construct signatures - // (internally we are checking the corresponding declaration), it is enough to perform - // the check and report an error once over all pairs of source and target construct signatures. - let sourceSig = sourceSignatures[0]; - // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. - let targetSig = targetSignatures[0]; - if (sourceSig && targetSig) { - let sourceErasedSignature = getErasedSignature(sourceSig); - let targetErasedSignature = getErasedSignature(targetSig); - let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); - let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + if (kind === SignatureKind.Construct) { + // Only want to compare the construct signatures for abstractness guarantees. + + // Because the "abstractness" of a class is the same across all construct signatures + // (internally we are checking the corresponding declaration), it is enough to perform + // the check and report an error once over all pairs of source and target construct signatures. + // + // sourceSig and targetSig are (possibly) undefined. + // + // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. + let sourceSig = sourceSignatures[0]; + let targetSig = targetSignatures[0]; - let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration); - let targetReturnDecl = targetReturnType && targetReturnType.symbol && getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration); - let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract; - let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract; - - if (sourceIsAbstract && !targetIsAbstract) { - if (reportErrors) { - reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); - } - return Ternary.False; + result &= abstractSignatureRelatedTo(source, sourceSig, target, targetSig); + if (result !== Ternary.True) { + return result; } } @@ -5128,6 +5138,40 @@ namespace ts { } } return result; + + function abstractSignatureRelatedTo(source: Type, sourceSig: Signature, target: Type, targetSig: Signature) { + if (sourceSig && targetSig) { + + let sourceDecl = source.symbol && getDeclarationOfKind(source.symbol, SyntaxKind.ClassDeclaration); + let targetDecl = target.symbol && getDeclarationOfKind(target.symbol, SyntaxKind.ClassDeclaration); + + if (!sourceDecl) { + // If the source object isn't itself a class declaration, it can be freely assigned, regardless + // of whether the constructed object is abstract or not. + return Ternary.True; + } + + let sourceErasedSignature = getErasedSignature(sourceSig); + let targetErasedSignature = getErasedSignature(targetSig); + + let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + + let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration); + let targetReturnDecl = targetReturnType && targetReturnType.symbol && getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration); + let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract; + let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract; + + if (sourceIsAbstract && !(targetIsAbstract && targetDecl)) { + // if target isn't a class-declaration type, then it can be new'd, so we forbid the assignment. + if (reportErrors) { + reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return Ternary.False; + } + } + return Ternary.True; + } } function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { @@ -5233,7 +5277,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; ++i) { - let related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*compareReturnTypes*/ true, isRelatedTo); + let related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -5363,14 +5407,18 @@ namespace ts { return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } - function compareSignatures(source: Signature, target: Signature, compareReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + 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) { - return Ternary.False; + if (!partialMatch || + source.parameters.length < target.parameters.length && !source.hasRestParameter || + source.minArgumentCount > target.minArgumentCount) { + return Ternary.False; + } } let result = Ternary.True; if (source.typeParameters && target.typeParameters) { @@ -5392,16 +5440,18 @@ namespace ts { // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature(source); target = getErasedSignature(target); - for (let i = 0, len = source.parameters.length; i < len; i++) { - let s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); - let t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); + let sourceLen = source.parameters.length; + let targetLen = target.parameters.length; + for (let i = 0; i < targetLen; i++) { + let s = source.hasRestParameter && i === sourceLen - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); + let t = target.hasRestParameter && i === targetLen - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); let related = compareTypes(s, t); if (!related) { return Ternary.False; } result &= related; } - if (compareReturnTypes) { + if (!ignoreReturnTypes) { result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } return result; @@ -6915,20 +6965,13 @@ namespace ts { let signatureList: Signature[]; let types = (type).types; for (let current of types) { - // The signature set of all constituent type with call signatures should match - // So number of signatures allowed is either 0 or 1 - if (signatureList && - getSignaturesOfStructuredType(current, SignatureKind.Call).length > 1) { - return undefined; - } - let signature = getNonGenericSignature(current); if (signature) { if (!signatureList) { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignatures(signatureList[0], signature, /*compareReturnTypes*/ false, compareTypes)) { + else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) { // Signatures aren't identical, do not use return undefined; } @@ -14342,15 +14385,17 @@ namespace ts { return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - let symbol = resolveEntityName(node.typeName, SymbolFlags.Value, /*ignoreErrors*/ true); - let constructorType = symbol ? getTypeOfSymbol(symbol) : undefined; + let valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true); + let constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } - let type = getTypeFromTypeNode(node); + // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. + let typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true); + let type = getDeclaredTypeOfSymbol(typeSymbol); if (type === unknownType) { return TypeReferenceSerializationKind.Unknown; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 7859e1f750d..5fc9335073c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -198,6 +198,13 @@ namespace ts { return array[array.length - 1]; } + /** + * Performs a binary search, finding the index at which 'value' occurs in 'array'. + * If no such index is found, returns the 2's-complement of first index at which + * number[index] exceeds number. + * @param array A sorted array whose first element must be no larger than number + * @param number The value to be searched for in the array. + */ export function binarySearch(array: number[], value: number): number { let low = 0; let high = array.length - 1; diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 63d71b0339e..a490ba39a46 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -750,14 +750,18 @@ namespace ts { } function writeTypeAliasDeclaration(node: TypeAliasDeclaration) { + let prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); writeTextOfNode(currentSourceFile, node.name); + emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); write(";"); writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { return { @@ -1497,11 +1501,8 @@ namespace ts { // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; writeTextOfNode(currentSourceFile, bindingElement.propertyName); write(": "); - - // If bindingElement has propertyName property, then its name must be another bindingPattern of SyntaxKind.ObjectBindingPattern - emitBindingPattern(bindingElement.name); } - else if (bindingElement.name) { + if (bindingElement.name) { if (isBindingPattern(bindingElement.name)) { // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. // In the case of rest element, we will omit rest element. diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e5bdb9a2585..c745d5ea65c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -832,7 +832,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(", "); } } - emitNode(nodes[start + i]); + let node = nodes[start + i]; + // This emitting is to make sure we emit following comment properly + // ...(x, /*comment1*/ y)... + // ^ => node.pos + // "comment1" is not considered leading comment for "y" but rather + // considered as trailing comment of the previous node. + emitTrailingCommentsOfPosition(node.pos); + emitNode(node); leadingComma = true; } if (trailingComma) { @@ -1976,6 +1983,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyAssignment(node: PropertyDeclaration) { emit(node.name); write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + emitTrailingCommentsOfPosition(node.initializer.pos); emit(node.initializer); } @@ -3091,31 +3106,38 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } function emitExportMemberAssignments(name: Identifier) { + if (compilerOptions.module === ModuleKind.System) { + return; + } + if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { for (let specifier of exportSpecifiers[name.text]) { writeLine(); - if (compilerOptions.module === ModuleKind.System) { - emitStart(specifier.name); - write(`${exportFunctionForFile}("`); - emitNodeWithoutSourceMap(specifier.name); - write(`", `); - emitExpressionIdentifier(name); - write(")"); - emitEnd(specifier.name); - } - else { - emitStart(specifier.name); - emitContainingModuleName(specifier); - write("."); - emitNodeWithoutSourceMap(specifier.name); - emitEnd(specifier.name); - write(" = "); - emitExpressionIdentifier(name); - } + emitStart(specifier.name); + emitContainingModuleName(specifier); + write("."); + emitNodeWithoutSourceMap(specifier.name); + emitEnd(specifier.name); + write(" = "); + emitExpressionIdentifier(name); write(";"); } } } + + function emitExportSpecifierInSystemModule(specifier: ExportSpecifier): void { + Debug.assert(compilerOptions.module === ModuleKind.System); + + writeLine(); + emitStart(specifier.name); + write(`${exportFunctionForFile}("`); + emitNodeWithoutSourceMap(specifier.name); + write(`", `); + emitExpressionIdentifier(specifier.propertyName || specifier.name); + write(")"); + emitEnd(specifier.name); + write(";"); + } function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) { let emitCount = 0; @@ -3632,8 +3654,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return emitOnlyPinnedOrTripleSlashComments(node); } - if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { - // Methods will emit the comments as part of emitting method declaration + // TODO (yuisu) : we should not have special cases to condition emitting comments + // but have one place to fix check for these conditions. + if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature && + node.parent && node.parent.kind !== SyntaxKind.PropertyAssignment && + node.parent.kind !== SyntaxKind.CallExpression) { + // 1. Methods will emit the comments as part of emitting method declaration + + // 2. If the function is a property of object literal, emitting leading-comments + // is done by emitNodeWithoutSourceMap which then call this function. + // In particular, we would like to avoid emit comments twice in following case: + // For example: + // var obj = { + // id: + // /*comment*/ () => void + // } + + // 3. If the function is an argument in call expression, emitting of comments will be + // taken care of in emit list of arguments inside of emitCallexpression emitLeadingComments(node); } @@ -4945,8 +4983,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ function emitSerializedTypeReferenceNode(node: TypeReferenceNode) { - let typeName = node.typeName; - let result = resolver.getTypeReferenceSerializationKind(node); + let location: Node = node.parent; + while (isDeclaration(location) || isTypeNode(location)) { + location = location.parent; + } + + // Clone the type name and parent it to a location outside of the current declaration. + let typeName = cloneEntityName(node.typeName); + typeName.parent = location; + + let result = resolver.getTypeReferenceSerializationKind(typeName); switch (result) { case TypeReferenceSerializationKind.Unknown: let temp = createAndRecordTempVariable(TempFlags.Auto); @@ -5078,6 +5124,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi argumentsWritten++; } if (shouldEmitParamTypesMetadata(node)) { + debugger; if (writeComma || argumentsWritten) { write(", "); } @@ -6051,7 +6098,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return compilerOptions.module === ModuleKind.System && isExternalModule(currentSourceFile); } - function emitSystemModuleBody(node: SourceFile, startIndex: number): void { + function emitSystemModuleBody(node: SourceFile, dependencyGroups: DependencyGroup[], startIndex: number): void { // shape of the body in system modules: // function (exports) { // @@ -6096,7 +6143,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("return {"); increaseIndent(); writeLine(); - emitSetters(exportStarFunction); + emitSetters(exportStarFunction, dependencyGroups); writeLine(); emitExecute(node, startIndex); decreaseIndent(); @@ -6105,115 +6152,90 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitTempDeclarations(/*newLine*/ true); } - function emitSetters(exportStarFunction: string) { + function emitSetters(exportStarFunction: string, dependencyGroups: DependencyGroup[]) { write("setters:["); - for (let i = 0; i < externalImports.length; ++i) { + + for (let i = 0; i < dependencyGroups.length; ++i) { if (i !== 0) { write(","); } writeLine(); increaseIndent(); - let importNode = externalImports[i]; - let importVariableName = getLocalNameForExternalImport(importNode) || ""; - let parameterName = "_" + importVariableName; + + let group = dependencyGroups[i]; + + // derive a unique name for parameter from the first named entry in the group + let parameterName = makeUniqueName(forEach(group, getLocalNameForExternalImport) || ""); write(`function (${parameterName}) {`); + increaseIndent(); + + for(let entry of group) { + let importVariableName = getLocalNameForExternalImport(entry) || ""; + + switch (entry.kind) { + case SyntaxKind.ImportDeclaration: + if (!(entry).importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required + break; + } + // fall-through + case SyntaxKind.ImportEqualsDeclaration: + Debug.assert(importVariableName !== ""); - switch (importNode.kind) { - case SyntaxKind.ImportDeclaration: - if (!(importNode).importClause) { - // 'import "..."' case - // module is imported only for side-effects, setter body will be empty - break; - } - // fall-through - case SyntaxKind.ImportEqualsDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - writeLine(); - // save import into the local - write(`${importVariableName} = ${parameterName};`); - writeLine(); - - let defaultName = - importNode.kind === SyntaxKind.ImportDeclaration - ? (importNode).importClause.name - : (importNode).name; - - if (defaultName) { - // emit re-export for imported default name - // import n1 from 'foo1' - // import n2 = require('foo2') - // export {n1} - // export {n2} - emitExportMemberAssignments(defaultName); writeLine(); - } + // save import into the local + write(`${importVariableName} = ${parameterName};`); + writeLine(); + break; + case SyntaxKind.ExportDeclaration: + Debug.assert(importVariableName !== ""); - if (importNode.kind === SyntaxKind.ImportDeclaration && - (importNode).importClause.namedBindings) { - - let namedBindings = (importNode).importClause.namedBindings; - if (namedBindings.kind === SyntaxKind.NamespaceImport) { - // emit re-export for namespace - // import * as n from 'foo' - // export {n} - emitExportMemberAssignments((namedBindings).name); + if ((entry).exportClause) { + // export {a, b as c} from 'foo' + // emit as: + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); writeLine(); + write(`${exportFunctionForFile}({`); + writeLine(); + increaseIndent(); + for (let i = 0, len = (entry).exportClause.elements.length; i < len; ++i) { + if (i !== 0) { + write(","); + writeLine(); + } + + let e = (entry).exportClause.elements[i]; + write(`"`); + emitNodeWithoutSourceMap(e.name); + write(`": ${parameterName}["`); + emitNodeWithoutSourceMap(e.propertyName || e.name); + write(`"]`); + } + decreaseIndent(); + writeLine(); + write("});") } else { - // emit re-exports for named imports - // import {a, b} from 'foo' - // export {a, b as c} - for (let element of (namedBindings).elements) { - emitExportMemberAssignments(element.name || element.propertyName); - writeLine(); - } - } - } - - decreaseIndent(); - break; - case SyntaxKind.ExportDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - - if ((importNode).exportClause) { - // export {a, b as c} from 'foo' - // emit as: - // var reexports = {} - // reexports['a'] = _foo["a"]; - // reexports['c'] = _foo["b"]; - // exports_(reexports); - let reexportsVariableName = makeUniqueName("reexports"); - writeLine(); - write(`var ${reexportsVariableName} = {};`); - writeLine(); - for (let e of (importNode).exportClause.elements) { - write(`${reexportsVariableName}["`); - emitNodeWithoutSourceMap(e.name); - write(`"] = ${parameterName}["`); - emitNodeWithoutSourceMap(e.propertyName || e.name); - write(`"];`); writeLine(); + // export * from 'foo' + // emit as: + // exportStar(_foo); + write(`${exportStarFunction}(${parameterName});`); } - write(`${exportFunctionForFile}(${reexportsVariableName});`); - } - else { - writeLine(); - // export * from 'foo' - // emit as: - // exportStar(_foo); - write(`${exportStarFunction}(${parameterName});`); - } - writeLine(); - decreaseIndent(); - break; + writeLine(); + break; + } + } + decreaseIndent(); + write("}"); decreaseIndent(); } @@ -6226,26 +6248,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); for (let i = startIndex; i < node.statements.length; ++i) { let statement = node.statements[i]; - // - external module related imports/exports are not emitted for system modules - // - function declarations are not emitted because they were already hoisted switch (statement.kind) { - case SyntaxKind.ExportDeclaration: + // - function declarations are not emitted because they were already hoisted + // - import declarations are not emitted since they are already handled in setters + // - export declarations with module specifiers are not emitted since they were already written in setters + // - export declarations without module specifiers are emitted preserving the order + case SyntaxKind.FunctionDeclaration: case SyntaxKind.ImportDeclaration: - case SyntaxKind.FunctionDeclaration: + continue; + case SyntaxKind.ExportDeclaration: + if (!(statement).moduleSpecifier) { + for (let element of (statement).exportClause.elements) { + // write call to exporter function for every export specifier in exports list + emitExportSpecifierInSystemModule(element); + } + } continue; case SyntaxKind.ImportEqualsDeclaration: if (!isInternalModuleImportEqualsDeclaration(statement)) { + // - import equals declarations that import external modules are not emitted continue; } - } - writeLine(); - emit(statement); + // fall-though for import declarations that import internal modules + default: + writeLine(); + emit(statement); + } } decreaseIndent(); writeLine(); write("}"); // execute } - + + type DependencyGroup = Array; + function emitSystemModule(node: SourceFile, startIndex: number): void { collectExternalModuleInfo(node); // System modules has the following shape @@ -6265,8 +6301,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(`"${node.moduleName}", `); } write("["); + + let groupIndices: Map = {}; + let dependencyGroups: DependencyGroup[] = []; + for (let i = 0; i < externalImports.length; ++i) { let text = getExternalModuleNameText(externalImports[i]); + if (hasProperty(groupIndices, text)) { + // deduplicate/group entries in dependency list by the dependency name + let groupIndex = groupIndices[text]; + dependencyGroups[groupIndex].push(externalImports[i]); + continue; + } + else { + groupIndices[text] = dependencyGroups.length; + dependencyGroups.push([externalImports[i]]); + } + if (i !== 0) { write(", "); } @@ -6277,7 +6328,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi increaseIndent(); emitEmitHelpers(node); emitCaptureThisForNodeIfNecessary(node); - emitSystemModuleBody(node, startIndex); + emitSystemModuleBody(node, dependencyGroups, startIndex); decreaseIndent(); writeLine(); write("});"); @@ -6941,6 +6992,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); } + /** + * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: + * x, /comment1/ y + * ^ => pos; the function will emit "comment1" in the emitJS + */ + function emitTrailingCommentsOfPosition(pos: number) { + let trailingComments = filterComments(getTrailingCommentRanges(currentSourceFile.text, pos), /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments); + + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ + emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + } + function emitLeadingCommentsOfPosition(pos: number) { let leadingComments: CommentRange[]; if (hasDetachedComments(pos)) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 10ebe86368d..def08e81758 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -844,6 +844,10 @@ namespace ts { return token = scanner.scanJsxIdentifier(); } + function scanJsxText(): SyntaxKind { + return token = scanner.scanJsxToken(); + } + function speculationHelper(callback: () => T, isLookAhead: boolean): T { // Keep track of the state we'll need to rollback to if lookahead fails (or if the // caller asked us to always reset our state). @@ -913,9 +917,11 @@ namespace ts { return token > SyntaxKind.LastReservedWord; } - function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean { + function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean { if (token === kind) { - nextToken(); + if (shouldAdvance) { + nextToken(); + } return true; } @@ -3178,7 +3184,7 @@ namespace ts { return parseTypeAssertion(); } if (lookAhead(nextTokenIsIdentifierOrKeyword)) { - return parseJsxElementOrSelfClosingElement(); + return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true); } // Fall through default: @@ -3308,14 +3314,14 @@ namespace ts { return finishNode(node); } - function parseJsxElementOrSelfClosingElement(): JsxElement|JsxSelfClosingElement { - let opening = parseJsxOpeningOrSelfClosingElement(); + function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement { + let opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext); if (opening.kind === SyntaxKind.JsxOpeningElement) { let node = createNode(SyntaxKind.JsxElement, opening.pos); node.openingElement = opening; node.children = parseJsxChildren(node.openingElement.tagName); - node.closingElement = parseJsxClosingElement(); + node.closingElement = parseJsxClosingElement(inExpressionContext); return finishNode(node); } else { @@ -3336,9 +3342,9 @@ namespace ts { case SyntaxKind.JsxText: return parseJsxText(); case SyntaxKind.OpenBraceToken: - return parseJsxExpression(); + return parseJsxExpression(/*inExpressionContext*/ false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElement(); + return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ false); } Debug.fail("Unknown JSX child kind " + token); } @@ -3368,7 +3374,7 @@ namespace ts { return result; } - function parseJsxOpeningOrSelfClosingElement(): JsxOpeningElement|JsxSelfClosingElement { + function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement|JsxSelfClosingElement { let fullStart = scanner.getStartPos(); parseExpected(SyntaxKind.LessThanToken); @@ -3378,12 +3384,22 @@ namespace ts { let attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute); let node: JsxOpeningLikeElement; - if (parseOptional(SyntaxKind.GreaterThanToken)) { + if (token === SyntaxKind.GreaterThanToken) { + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors node = createNode(SyntaxKind.JsxOpeningElement, fullStart); + scanJsxText(); } else { parseExpected(SyntaxKind.SlashToken); - parseExpected(SyntaxKind.GreaterThanToken); + if (inExpressionContext) { + parseExpected(SyntaxKind.GreaterThanToken); + } + else { + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + scanJsxText(); + } node = createNode(SyntaxKind.JsxSelfClosingElement, fullStart); } @@ -3406,14 +3422,20 @@ namespace ts { return elementName; } - function parseJsxExpression(): JsxExpression { + function parseJsxExpression(inExpressionContext: boolean): JsxExpression { let node = createNode(SyntaxKind.JsxExpression); parseExpected(SyntaxKind.OpenBraceToken); if (token !== SyntaxKind.CloseBraceToken) { node.expression = parseExpression(); } - parseExpected(SyntaxKind.CloseBraceToken); + if (inExpressionContext) { + parseExpected(SyntaxKind.CloseBraceToken); + } + else { + parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*advance*/ false); + scanJsxText(); + } return finishNode(node); } @@ -3432,7 +3454,7 @@ namespace ts { node.initializer = parseLiteralNode(); break; default: - node.initializer = parseJsxExpression(); + node.initializer = parseJsxExpression(/*inExpressionContext*/ true); break; } } @@ -3448,11 +3470,17 @@ namespace ts { return finishNode(node); } - function parseJsxClosingElement(): JsxClosingElement { + function parseJsxClosingElement(inExpressionContext: boolean): JsxClosingElement { let node = createNode(SyntaxKind.JsxClosingElement); parseExpected(SyntaxKind.LessThanSlashToken); node.tagName = parseJsxElementName(); - parseExpected(SyntaxKind.GreaterThanToken); + if (inExpressionContext) { + parseExpected(SyntaxKind.GreaterThanToken); + } + else { + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + scanJsxText(); + } return finishNode(node); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 7db8f243192..33003b6e8c2 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -319,14 +319,21 @@ namespace ts { } /* @internal */ + /** + * We assume the first line starts at position 0 and 'position' is non-negative. + */ export function computeLineAndCharacterOfPosition(lineStarts: number[], position: number) { let lineNumber = binarySearch(lineStarts, position); if (lineNumber < 0) { // If the actual position was not found, - // the binary search returns the negative value of the next line start + // the binary search returns the 2's-complement of the next line start // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 - // then the search will return -2 + // then the search will return -2. + // + // We want the index of the previous line start, so we subtract 1. + // Review 2's-complement if this is confusing. lineNumber = ~lineNumber - 1; + Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); } return { line: lineNumber, @@ -552,13 +559,17 @@ namespace ts { return pos; } - // Extract comments from the given source text starting at the given position. If trailing is - // false, whitespace is skipped until the first line break and comments between that location - // and the next token are returned.If trailing is true, comments occurring between the given - // position and the next line break are returned.The return value is an array containing a - // TextRange for each comment. Single-line comment ranges include the beginning '//' characters - // but not the ending line break. Multi - line comment ranges include the beginning '/* and - // ending '*/' characters.The return value is undefined if no comments were found. + /** + * Extract comments from text prefixing the token closest following `pos`. + * The return value is an array containing a TextRange for each comment. + * Single-line comment ranges include the beginning '//' characters but not the ending line break. + * Multi - line comment ranges include the beginning '/* and ending '/' characters. + * The return value is undefined if no comments were found. + * @param trailing + * If false, whitespace is skipped until the first line break and comments between that location + * and the next token are returned. + * If true, comments occurring between the given position and the next line break are returned. + */ function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] { let result: CommentRange[]; let collecting = trailing || pos === 0; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1730e45ee9e..6535bb792ff 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -334,7 +334,9 @@ namespace ts { if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { return getWScriptSystem(); } - else if (typeof module !== "undefined" && module.exports) { + else if (typeof process !== "undefined" && process.nextTick && !process.browser) { + // process and process.nextTick checks if current environment is node-like + // process.browser check excludes webpack and browserify return getNodeSystem(); } else { diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 22bd6d79b0e..c322187fa14 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -363,7 +363,7 @@ namespace ts { // If we didn't have any syntactic errors, then also try getting the global and // semantic errors. if (diagnostics.length === 0) { - diagnostics = program.getGlobalDiagnostics(); + diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); if (diagnostics.length === 0) { diagnostics = program.getSemanticDiagnostics(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 326cd2bacba..066326b0a58 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -587,9 +587,9 @@ namespace ts { * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. * Examples: - * FunctionDeclaration - * MethodDeclaration - * AccessorDeclaration + * - FunctionDeclaration + * - MethodDeclaration + * - AccessorDeclaration */ export interface FunctionLikeDeclaration extends SignatureDeclaration { _functionLikeDeclarationBrand: any; @@ -1592,7 +1592,7 @@ namespace ts { getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a38a72e99b4..a33419ae810 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -416,24 +416,12 @@ namespace ts { } export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { - // If parameter/type parameter, the prev token trailing comments are part of this node too - if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) { - // e.g. (/** blah */ a, /** blah */ b); - - // e.g.: ( - // /** blah */ a, - // /** blah */ b); - return concatenate( - getTrailingCommentRanges(sourceFileOfNode.text, node.pos), - getLeadingCommentRanges(sourceFileOfNode.text, node.pos)); - } - else { - return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); - } + return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { - return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment); + let commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ? concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : getLeadingCommentRangesOfNode(node, sourceFileOfNode); + return filter(commentRanges, isJsDocComment); function isJsDocComment(comment: CommentRange) { // True if the comment starts with '/**' but not if it is '/**/' @@ -1457,6 +1445,22 @@ namespace ts { return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile; } + export function cloneEntityName(node: EntityName): EntityName { + if (node.kind === SyntaxKind.Identifier) { + let clone = createSynthesizedNode(SyntaxKind.Identifier); + clone.text = (node).text; + return clone; + } + else { + let clone = createSynthesizedNode(SyntaxKind.QualifiedName); + clone.left = cloneEntityName((node).left); + clone.left.parent = clone; + clone.right = cloneEntityName((node).right); + clone.right.parent = clone; + return clone; + } + } + export function nodeIsSynthesized(node: Node): boolean { return node.pos === -1; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 121d1938a4a..1d2ad83d98a 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -366,6 +366,7 @@ module FourSlash { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }; @@ -1885,7 +1886,7 @@ module FourSlash { ); assert.equal( expected.join(","), - actual.fileNameList.map( file => { + actual.fileNames.map( file => { return file.replace(this.basePath + "/", ""); }).join(",") ); @@ -1943,6 +1944,32 @@ module FourSlash { } } + public verifyDocCommentTemplate(expected?: ts.TextInsertion) { + const name = "verifyDocCommentTemplate"; + let actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); + + if (expected === undefined) { + if (actual) { + this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" caretOffset: ' + actual.caretOffset + '}'); + } + + return; + } + else { + if (actual === undefined) { + this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" caretOffset: ' + actual.caretOffset + '} but got nothing instead'); + } + + if (actual.newText !== expected.newText) { + this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); + } + + if (actual.caretOffset !== expected.caretOffset) { + this.raiseError(name + ' failed - expected caretOffset: ' + expected.caretOffset + ',\nactual caretOffset:' + actual.caretOffset); + } + } + } + public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { this.taoInvalidReason = "verifyMatchingBracePosition NYI"; @@ -2117,17 +2144,17 @@ module FourSlash { } } - private getOccurancesAtCurrentPosition() { + private getOccurrencesAtCurrentPosition() { return this.languageService.getOccurrencesAtPosition(this.activeFile.fileName, this.currentCaretPosition); } public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { this.taoInvalidReason = "verifyOccurrencesAtPositionListContains NYI"; - let occurrences = this.getOccurancesAtCurrentPosition(); + let occurrences = this.getOccurrencesAtCurrentPosition(); if (!occurrences || occurrences.length === 0) { - this.raiseError('verifyOccurancesAtPositionListContains failed - found 0 references, expected at least one.'); + this.raiseError('verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one.'); } for (let occurrence of occurrences) { @@ -2146,7 +2173,7 @@ module FourSlash { public verifyOccurrencesAtPositionListCount(expectedCount: number) { this.taoInvalidReason = "verifyOccurrencesAtPositionListCount NYI"; - let occurrences = this.getOccurancesAtCurrentPosition(); + let occurrences = this.getOccurrencesAtCurrentPosition(); let actualCount = occurrences ? occurrences.length : 0; if (expectedCount !== actualCount) { this.raiseError(`verifyOccurrencesAtPositionListCount failed - actual: ${actualCount}, expected:${expectedCount}`); @@ -2174,7 +2201,7 @@ module FourSlash { for (let highlight of highlightSpans) { if (highlight && highlight.textSpan.start === start && ts.textSpanEnd(highlight.textSpan) === end) { if (typeof kind !== "undefined" && highlight.kind !== kind) { - this.raiseError('verifyDocumentHighlightsAtPositionListContains failed - item "kind" value does not match, actual: ' + highlight.kind + ', expected: ' + kind + '.'); + this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - item "kind" value does not match, actual: ${highlight.kind}, expected: ${kind}.`); } return; } @@ -2183,7 +2210,7 @@ module FourSlash { } let missingItem = { fileName: fileName, start: start, end: end, kind: kind }; - this.raiseError('verifyOccurancesAtPositionListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(documentHighlights) + ')'); + this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem)} in the returned list: (${JSON.stringify(documentHighlights)})`); } public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) { @@ -2810,4 +2837,4 @@ module FourSlash { fileName: fileName }; } -} \ No newline at end of file +} diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index db388c95610..f228bc862d8 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -411,6 +411,9 @@ module Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } + getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion { + return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position)); + } getEmitOutput(fileName: string): ts.EmitOutput { return unwrapJSONCallResult(this.shim.getEmitOutput(fileName)); } diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 27cb3574473..0fef0779965 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -71,4 +71,4 @@ class TypeWriterWalker { symbol: symbolString }); } -} +} \ No newline at end of file diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 32e8fb45ce4..8eec72f1a4c 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -11962,7 +11962,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window onvolumechange: (ev: Event) => any; onwaiting: (ev: Event) => any; opener: Window; - orientation: string; + orientation: string | number; outerHeight: number; outerWidth: number; pageXOffset: number; @@ -12777,7 +12777,7 @@ declare var onunload: (ev: Event) => any; declare var onvolumechange: (ev: Event) => any; declare var onwaiting: (ev: Event) => any; declare var opener: Window; -declare var orientation: string; +declare var orientation: string | number; declare var outerHeight: number; declare var outerWidth: number; declare var pageXOffset: number; @@ -12952,4 +12952,4 @@ declare function addEventListener(type: "unload", listener: (ev: Event) => any, declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; \ No newline at end of file +declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 5c41869e487..db8b02f34d7 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -806,7 +806,7 @@ interface EventListenerObject { declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject; interface ErrorEventHandler { - (event: Event | string, source?: string, fileno?: number, columnNumber?: number): void; + (message: string, filename?: string, lineno?: number, colno?: number, error?:Error): void; } interface PositionCallback { (position: Position): void; diff --git a/src/server/client.ts b/src/server/client.ts index cc89349b442..ae234750d88 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -183,7 +183,7 @@ namespace ts.server { return { configFileName: response.body.configFileName, - fileNameList: response.body.fileNameList + fileNames: response.body.fileNames }; } @@ -563,6 +563,10 @@ namespace ts.server { getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { throw new Error("Not Implemented Yet."); } + + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { + throw new Error("Not Implemented Yet."); + } getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] { var lineOffset = this.positionToOneBasedLineOffset(fileName, position); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index eec7d475890..14bb7712ce7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -368,7 +368,7 @@ namespace ts.server { return this.projectService.openFile(filename, false); } - getFileNameList() { + getFileNames() { let sourceFiles = this.program.getSourceFiles(); return sourceFiles.map(sourceFile => sourceFile.fileName); } @@ -1054,6 +1054,7 @@ namespace ts.server { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, } diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 8f7237382e5..438b152a1f4 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -123,9 +123,14 @@ declare module NodeJS { export interface ReadWriteStream extends ReadableStream, WritableStream { } + interface WindowSize { + columns: number; + rows: number; + } + export interface Process extends EventEmitter { - stdout: WritableStream; - stderr: WritableStream; + stdout: WritableStream & WindowSize; + stderr: WritableStream & WindowSize; stdin: ReadableStream; argv: string[]; execPath: string; diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 837bce4f99d..2d694025c84 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -116,7 +116,7 @@ declare namespace ts.server.protocol { /** * The list of normalized file name in the project, including 'lib.d.ts' */ - fileNameList?: string[]; + fileNames?: string[]; } /** @@ -452,6 +452,9 @@ declare namespace ts.server.protocol { /** Defines space handling after opening and before closing non empty parenthesis. Default value is false. */ insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; + + /** Defines space handling after opening and before closing non empty brackets. Default value is false. */ + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; /** Defines whether an open brace is put onto a new line for functions or not. Default value is false. */ placeOpenBraceOnNewLineForFunctions?: boolean; @@ -894,6 +897,31 @@ declare namespace ts.server.protocol { export interface SignatureHelpResponse extends Response { body?: SignatureHelpItems; } + + /** + * Arguments for GeterrForProject request. + */ + export interface GeterrForProjectRequestArgs { + /** + * the file requesting project error list + */ + file: string; + + /** + * Delay in milliseconds to wait before starting to compute + * errors for the files in the file list + */ + delay: number; + } + + /** + * GeterrForProjectRequest request; value of command field is + * "geterrForProject". It works similarly with 'Geterr', only + * it request for every file in this project. + */ + export interface GeterrForProjectRequest extends Request { + arguments: GeterrForProjectRequestArgs + } /** * Arguments for geterr messages. diff --git a/src/server/session.ts b/src/server/session.ts index 54e4423d382..108cf4726dc 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -86,6 +86,7 @@ namespace ts.server { export const Format = "format"; export const Formatonkey = "formatonkey"; export const Geterr = "geterr"; + export const GeterrForProject = "geterrForProject"; export const NavBar = "navbar"; export const Navto = "navto"; export const Occurrences = "occurrences"; @@ -235,7 +236,7 @@ namespace ts.server { } private updateErrorCheck(checkList: PendingErrorCheck[], seq: number, - matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200) { + matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200, requireOpen = true) { if (followMs > ms) { followMs = ms; } @@ -250,7 +251,7 @@ namespace ts.server { var checkOne = () => { if (matchSeq(seq)) { var checkSpec = checkList[index++]; - if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, true)) { + if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, requireOpen)) { this.syntacticCheck(checkSpec.fileName, checkSpec.project); this.immediateId = setImmediate(() => { this.semanticCheck(checkSpec.fileName, checkSpec.project); @@ -389,7 +390,7 @@ namespace ts.server { } if (needFileNameList) { - projectInfo.fileNameList = project.getFileNameList(); + projectInfo.fileNames = project.getFileNames(); } return projectInfo; @@ -873,7 +874,53 @@ namespace ts.server { })); } - public exit() { + getDiagnosticsForProject(delay: number, fileName: string) { + let { configFileName, fileNames: fileNamesInProject } = this.getProjectInfo(fileName, true); + // No need to analyze lib.d.ts + fileNamesInProject = fileNamesInProject.filter((value, index, array) => value.indexOf("lib.d.ts") < 0); + + // Sort the file name list to make the recently touched files come first + let highPriorityFiles: string[] = []; + let mediumPriorityFiles: string[] = []; + let lowPriorityFiles: string[] = []; + let veryLowPriorityFiles: string[] = []; + let normalizedFileName = ts.normalizePath(fileName); + let project = this.projectService.getProjectForFile(normalizedFileName); + for (let fileNameInProject of fileNamesInProject) { + if (this.getCanonicalFileName(fileNameInProject) == this.getCanonicalFileName(fileName)) + highPriorityFiles.push(fileNameInProject); + else { + let info = this.projectService.getScriptInfo(fileNameInProject); + if (!info.isOpen) { + if (fileNameInProject.indexOf(".d.ts") > 0) + veryLowPriorityFiles.push(fileNameInProject); + else + lowPriorityFiles.push(fileNameInProject); + } + else + mediumPriorityFiles.push(fileNameInProject); + } + } + + fileNamesInProject = highPriorityFiles.concat(mediumPriorityFiles).concat(lowPriorityFiles).concat(veryLowPriorityFiles); + + if (fileNamesInProject.length > 0) { + let checkList = fileNamesInProject.map((fileName: string) => { + let normalizedFileName = ts.normalizePath(fileName); + return { fileName: normalizedFileName, project }; + }); + // Project level error analysis runs on background files too, therefore + // doesn't require the file to be opened + this.updateErrorCheck(checkList, this.changeSeq, (n) => n == this.changeSeq, delay, 200, /*requireOpen*/ false); + } + } + + getCanonicalFileName(fileName: string) { + let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + return ts.normalizePath(name); + } + + exit() { } private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = { @@ -931,6 +978,10 @@ namespace ts.server { var geterrArgs = request.arguments; return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false}; }, + [CommandNames.GeterrForProject]: (request: protocol.Request) => { + let { file, delay } = request.arguments; + return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false}; + }, [CommandNames.Change]: (request: protocol.Request) => { var changeArgs = request.arguments; this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 1a758886350..d4e096974b7 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -39,12 +39,12 @@ namespace ts.formatting { public SpaceBetweenCloseBraceAndWhile: Rule; public NoSpaceAfterCloseBrace: Rule; - // No space for indexer and dot + // No space for dot public NoSpaceBeforeDot: Rule; public NoSpaceAfterDot: Rule; + + // No space before and after indexer public NoSpaceBeforeOpenBracket: Rule; - public NoSpaceAfterOpenBracket: Rule; - public NoSpaceBeforeCloseBracket: Rule; public NoSpaceAfterCloseBracket: Rule; // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. @@ -135,6 +135,7 @@ namespace ts.formatting { public NoSpaceAfterOpenAngularBracket: Rule; public NoSpaceBeforeCloseAngularBracket: Rule; public NoSpaceAfterCloseAngularBracket: Rule; + public NoSpaceAfterTypeAssertion: Rule; // Remove spaces in empty interface literals. e.g.: x: {} public NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; @@ -190,6 +191,13 @@ namespace ts.formatting { public NoSpaceAfterOpenParen: Rule; public NoSpaceBeforeCloseParen: Rule; + // Insert space after opening and before closing nonempty brackets + public SpaceAfterOpenBracket: Rule; + public SpaceBeforeCloseBracket: Rule; + public NoSpaceBetweenBrackets: Rule; + public NoSpaceAfterOpenBracket: Rule; + public NoSpaceBeforeCloseBracket: Rule; + // Insert space after function keyword for anonymous functions public SpaceAfterAnonymousFunctionKeyword: Rule; public NoSpaceAfterAnonymousFunctionKeyword: Rule; @@ -231,13 +239,13 @@ namespace ts.formatting { this.SpaceBetweenCloseBraceAndWhile = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - // No space for indexer and dot + // No space for dot this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + + // No space before and after indexer this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete)); + this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete)); // Place a space before open brace in a function declaration this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments; @@ -331,12 +339,13 @@ namespace ts.formatting { this.NoSpaceAfterEllipsis = new Rule(RuleDescriptor.create1(SyntaxKind.DotDotDotToken, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceAfterOptionalParameters = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - // generics - this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.TypeNames), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); + // generics and type assertions + this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Delete)); // Remove spaces in empty interface literals. e.g.: x: {} this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), RuleAction.Delete)); @@ -391,6 +400,7 @@ namespace ts.formatting { this.NoSpaceAfterOpenAngularBracket, this.NoSpaceBeforeCloseAngularBracket, this.NoSpaceAfterCloseAngularBracket, + this.NoSpaceAfterTypeAssertion, this.SpaceBeforeAt, this.NoSpaceAfterAt, this.SpaceAfterDecorator, @@ -402,8 +412,8 @@ namespace ts.formatting { this.NoSpaceBeforeSemicolon, this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket, - this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket, + this.NoSpaceBeforeOpenBracket, + this.NoSpaceAfterCloseBracket, this.SpaceAfterSemicolon, this.NoSpaceBeforeOpenParenInFuncDecl, this.SpaceBetweenStatements, this.SpaceAfterTryFinally @@ -448,6 +458,13 @@ namespace ts.formatting { this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + // Insert space after opening and before closing nonempty brackets + this.SpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); + this.SpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); + this.NoSpaceBetweenBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + // Insert space after function keyword for anonymous functions this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Delete)); @@ -704,13 +721,15 @@ namespace ts.formatting { return context.contextNode.kind === SyntaxKind.TypeLiteral;// && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } - static IsTypeArgumentOrParameter(token: TextRangeWithKind, parent: Node): boolean { + static IsTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: Node): boolean { if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) { return false; } switch (parent.kind) { case SyntaxKind.TypeReference: + case SyntaxKind.TypeAssertionExpression: case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: @@ -721,6 +740,7 @@ namespace ts.formatting { case SyntaxKind.ConstructSignature: case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: + case SyntaxKind.ExpressionWithTypeArguments: return true; default: return false; @@ -728,9 +748,13 @@ namespace ts.formatting { } } - static IsTypeArgumentOrParameterContext(context: FormattingContext): boolean { - return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) || - Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent); + static IsTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { + return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || + Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + } + + static IsTypeAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeAssertionExpression; } static IsVoidOpContext(context: FormattingContext): boolean { diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index ac1494571d1..f6cf1de474b 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -71,6 +71,17 @@ namespace ts.formatting { rules.push(this.globalRules.NoSpaceBetweenParens); } + if ( options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets ) { + rules.push( this.globalRules.SpaceAfterOpenBracket ); + rules.push( this.globalRules.SpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + else { + rules.push( this.globalRules.NoSpaceAfterOpenBracket ); + rules.push( this.globalRules.NoSpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + if (options.InsertSpaceAfterSemicolonInForStatements) { rules.push(this.globalRules.SpaceAfterSemicolonInFor); } diff --git a/src/services/services.ts b/src/services/services.ts index 7329910b09b..cea87d34d12 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1049,6 +1049,8 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; + getEmitOutput(fileName: string): EmitOutput; getProgram(): Program; @@ -1095,6 +1097,12 @@ namespace ts { newText: string; } + export interface TextInsertion { + newText: string; + /** The position in newText the caret should point to after the insertion. */ + caretOffset: number; + } + export interface RenameLocation { textSpan: TextSpan; fileName: string; @@ -1150,6 +1158,7 @@ namespace ts { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string; @@ -1569,13 +1578,6 @@ namespace ts { /// Language Service - interface FormattingOptions { - useTabs: boolean; - spacesPerTab: number; - indentSpaces: number; - newLineCharacter: string; - } - // Information about a specific host file. interface HostFileInformation { hostFileName: string; @@ -2569,7 +2571,7 @@ namespace ts { getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, - getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n", + getNewLine: () => getNewLineOrDefaultFromHost(host), getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => host.getCurrentDirectory(), @@ -4669,7 +4671,7 @@ namespace ts { case SyntaxKind.BreakKeyword: case SyntaxKind.ContinueKeyword: if (hasKind(node.parent, SyntaxKind.BreakStatement) || hasKind(node.parent, SyntaxKind.ContinueStatement)) { - return getBreakOrContinueStatementOccurences(node.parent); + return getBreakOrContinueStatementOccurrences(node.parent); } break; case SyntaxKind.ForKeyword: @@ -4995,7 +4997,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); } - function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { let owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { @@ -5535,7 +5537,7 @@ namespace ts { symbolToIndex: number[]): void { let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* token.getStart(); - } + function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean { + return isInCommentHelper(sourceFile, position, isNonReferenceComment); - function isInComment(position: number) { - let token = getTokenAtPosition(sourceFile, position); - if (token && position < token.getStart()) { - // First, we have to see if this position actually landed in a comment. - let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - - // Then we want to make sure that it wasn't in a "///<" directive comment - // We don't want to unintentionally update a file name. - return forEach(commentRanges, c => { - if (c.pos < position && position < c.end) { - let commentText = sourceFile.text.substring(c.pos, c.end); - if (!tripleSlashDirectivePrefixRegex.test(commentText)) { - return true; - } - } - }); + function isNonReferenceComment(c: CommentRange): boolean { + let commentText = sourceFile.text.substring(c.pos, c.end); + return !tripleSlashDirectivePrefixRegex.test(commentText); } - - return false; } } @@ -6866,6 +6851,78 @@ namespace ts { return []; } + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a function declaration. + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { + let start = new Date().getTime(); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + + // Check if in a context where we don't want to perform any insertion + if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { + return undefined; + } + + let tokenAtPos = getTokenAtPosition(sourceFile, position); + let tokenStart = tokenAtPos.getStart() + if (!tokenAtPos || tokenStart < position) { + return undefined; + } + + // TODO: add support for: + // - methods + // - constructors + // - class decls + let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); + + if (!containingFunction || containingFunction.getStart() < position) { + return undefined; + } + + let parameters = containingFunction.parameters; + let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + + let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + + // TODO: call a helper method instead once PR #4133 gets merged in. + const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; + + let docParams = parameters.reduce((prev, cur, index) => + prev + + indentationStr + " * @param " + (cur.name.kind === SyntaxKind.Identifier ? (cur.name).text : "param" + index) + newLine, ""); + + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. + const preamble = "/**" + newLine + + indentationStr + " * "; + let result = + preamble + newLine + + docParams + + indentationStr + " */" + + (tokenStart === position ? newLine + indentationStr : ""); + + return { newText: result, caretOffset: preamble.length }; + } + function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call @@ -7107,6 +7164,7 @@ namespace ts { getFormattingEditsForRange, getFormattingEditsForDocument, getFormattingEditsAfterKeystroke, + getDocCommentTemplateAtPosition, getEmitOutput, getSourceFile, getProgram diff --git a/src/services/shims.ts b/src/services/shims.ts index d298dfe1cb2..e6ec71f368b 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -207,6 +207,11 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string; + /** + * Returns JSON-encoded value of the type TextInsertion. + */ + getDocCommentTemplateAtPosition(fileName: string, position: number): string; + getEmitOutput(fileName: string): string; } @@ -549,7 +554,7 @@ namespace ts { } private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[]{ - var newLine = this.getNewLine(); + var newLine = getNewLineOrDefaultFromHost(this.host); return ts.realizeDiagnostics(diagnostics, newLine); } @@ -591,10 +596,6 @@ namespace ts { }); } - private getNewLine(): string { - return this.host.getNewLine ? this.host.getNewLine() : "\r\n"; - } - public getSyntacticDiagnostics(fileName: string): string { return this.forwardJSONCall( "getSyntacticDiagnostics('" + fileName + "')", @@ -771,7 +772,10 @@ namespace ts { return this.forwardJSONCall( "getDocumentHighlights('" + fileName + "', " + position + ")", () => { - return this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + var results = this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + // workaround for VS document higlighting issue - keep only items from the initial file + let normalizedName = normalizeSlashes(fileName).toLowerCase(); + return filter(results, r => normalizeSlashes(r.fileName).toLowerCase() === normalizedName); }); } @@ -831,6 +835,13 @@ namespace ts { }); } + public getDocCommentTemplateAtPosition(fileName: string, position: number): string { + return this.forwardJSONCall( + "getDocCommentTemplateAtPosition('" + fileName + "', " + position + ")", + () => this.languageService.getDocCommentTemplateAtPosition(fileName, position) + ); + } + /// NAVIGATE TO /** Return a list of symbols that are interesting to navigate to */ diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5f8859c815e..04bfd04057c 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -414,6 +414,60 @@ namespace ts { } } } + + export function isInString(sourceFile: SourceFile, position: number) { + let token = getTokenAtPosition(sourceFile, position); + return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart(); + } + + export function isInComment(sourceFile: SourceFile, position: number) { + return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); + } + + /** + * Returns true if the cursor at position in sourceFile is within a comment that additionally + * satisfies predicate, and false otherwise. + */ + export function isInCommentHelper(sourceFile: SourceFile, position: number, predicate?: (c: CommentRange) => boolean): boolean { + let token = getTokenAtPosition(sourceFile, position); + + if (token && position <= token.getStart()) { + let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + + // The end marker of a single-line comment does not include the newline character. + // In the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + return predicate ? + forEach(commentRanges, c => c.pos < position && + (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && + predicate(c)) : + forEach(commentRanges, c => c.pos < position && + (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end)); + } + + return false; + } + + export function hasDocComment(sourceFile: SourceFile, position: number) { + let token = getTokenAtPosition(sourceFile, position); + + // First, we have to see if this position actually landed in a comment. + let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + + return forEach(commentRanges, jsDocPrefix); + + function jsDocPrefix(c: CommentRange): boolean { + var text = sourceFile.text; + return text.length >= c.pos + 3 && text[c.pos] === '/' && text[c.pos + 1] === '*' && text[c.pos + 2] === '*'; + } + } function nodeHasTokens(n: Node): boolean { // If we have a token or node that has a non-zero width, it must have tokens. @@ -625,6 +679,14 @@ namespace ts { return displayPart(text, SymbolDisplayPartKind.text); } + const carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. + */ + export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; + } + export function lineBreakPart() { return displayPart("\n", SymbolDisplayPartKind.lineBreak); } diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 9d44dfdc03e..4a467a60a84 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -112,7 +112,7 @@ exports.delint = delint; var fileNames = process.argv.slice(2); fileNames.forEach(function (fileName) { // Parse a file - var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), 2 /* ES6 */, true); + var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), 2 /* ES6 */, /*setParentNodes */ true); // delint it delint(sourceFile); }); diff --git a/tests/baselines/reference/aliasesInSystemModule1.js b/tests/baselines/reference/aliasesInSystemModule1.js index 28ac1e9b4ad..05f74aef852 100644 --- a/tests/baselines/reference/aliasesInSystemModule1.js +++ b/tests/baselines/reference/aliasesInSystemModule1.js @@ -22,8 +22,8 @@ System.register(['foo'], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_alias) { - alias = _alias; + function (alias_1) { + alias = alias_1; }], execute: function() { cls = alias.Class; diff --git a/tests/baselines/reference/aliasesInSystemModule2.js b/tests/baselines/reference/aliasesInSystemModule2.js index 0256d03a179..32d663a11e1 100644 --- a/tests/baselines/reference/aliasesInSystemModule2.js +++ b/tests/baselines/reference/aliasesInSystemModule2.js @@ -21,8 +21,8 @@ System.register(["foo"], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { cls = foo_1.alias.Class; diff --git a/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt new file mode 100644 index 00000000000..c6c242396d8 --- /dev/null +++ b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts(7,1): error TS2322: Type 'typeof A' is not assignable to type 'new () => A'. + Cannot assign an abstract constructor type to a non-abstract constructor type. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts(8,1): error TS2322: Type 'string' is not assignable to type 'new () => A'. + + +==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts (2 errors) ==== + abstract class A { } + + // var AA: typeof A; + var AAA: new() => A; + + // AA = A; // okay + AAA = A; // error. + ~~~ +!!! error TS2322: Type 'typeof A' is not assignable to type 'new () => A'. +!!! error TS2322: Cannot assign an abstract constructor type to a non-abstract constructor type. + AAA = "asdf"; + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'new () => A'. \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js new file mode 100644 index 00000000000..3d8fd404afc --- /dev/null +++ b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js @@ -0,0 +1,21 @@ +//// [classAbstractAssignabilityConstructorFunction.ts] +abstract class A { } + +// var AA: typeof A; +var AAA: new() => A; + +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; + +//// [classAbstractAssignabilityConstructorFunction.js] +var A = (function () { + function A() { + } + return A; +})(); +// var AA: typeof A; +var AAA; +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; diff --git a/tests/baselines/reference/commentInMethodCall.js b/tests/baselines/reference/commentInMethodCall.js index 4ad2fc552d7..4cbd4824a82 100644 --- a/tests/baselines/reference/commentInMethodCall.js +++ b/tests/baselines/reference/commentInMethodCall.js @@ -8,4 +8,5 @@ s.map(// do something //// [commentInMethodCall.js] //commment here var s; -s.map(function () { }); +s.map(// do something +function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js new file mode 100644 index 00000000000..4e6d693c5c2 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js @@ -0,0 +1,32 @@ +//// [commentsArgumentsOfCallExpression1.ts] +function foo(/*c1*/ x: any) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( + /*c4*/ + () => { }); +foo( + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ + () => { }); +foo( + /*c7*/ + /*c8*/() => { }); + +//// [commentsArgumentsOfCallExpression1.js] +function foo(/*c1*/ x) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( +/*c4*/ +function () { }); +foo( +/*c5*/ +/*c6*/ +function () { }); +foo(/*c7*/ function () { }); +foo( +/*c7*/ +/*c8*/ function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols b/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols new file mode 100644 index 00000000000..9d8495f948c --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression1.ts === +function foo(/*c1*/ x: any) { } +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) +>x : Symbol(x, Decl(commentsArgumentsOfCallExpression1.ts, 0, 13)) + +foo(/*c2*/ 1); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + +foo(/*c3*/ function () { }); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c4*/ + () => { }); +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + () => { }); +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c7*/ + /*c8*/() => { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.types b/tests/baselines/reference/commentsArgumentsOfCallExpression1.types new file mode 100644 index 00000000000..bcab3e3de36 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.types @@ -0,0 +1,47 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression1.ts === +function foo(/*c1*/ x: any) { } +>foo : (x: any) => void +>x : any + +foo(/*c2*/ 1); +>foo(/*c2*/ 1) : void +>foo : (x: any) => void +>1 : number + +foo(/*c3*/ function () { }); +>foo(/*c3*/ function () { }) : void +>foo : (x: any) => void +>function () { } : () => void + +foo( +>foo( /*c4*/ () => { }) : void +>foo : (x: any) => void + + /*c4*/ + () => { }); +>() => { } : () => void + +foo( +>foo( /*c5*/ /*c6*/ () => { }) : void +>foo : (x: any) => void + + /*c5*/ + /*c6*/ + () => { }); +>() => { } : () => void + +foo(/*c7*/ +>foo(/*c7*/ () => { }) : void +>foo : (x: any) => void + + () => { }); +>() => { } : () => void + +foo( +>foo( /*c7*/ /*c8*/() => { }) : void +>foo : (x: any) => void + + /*c7*/ + /*c8*/() => { }); +>() => { } : () => void + diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js new file mode 100644 index 00000000000..a7065410ff4 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js @@ -0,0 +1,23 @@ +//// [commentsArgumentsOfCallExpression2.ts] +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +var a, b: any; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +foo( + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); + +//// [commentsArgumentsOfCallExpression2.js] +function foo(/*c1*/ x, /*d1*/ y, /*e1*/ w) { } +var a, b; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + b); +foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b)); +foo( +/*c4*/ function () { }, +/*d4*/ function () { }, +/*e4*/ +/*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols b/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols new file mode 100644 index 00000000000..59047dd46c3 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression2.ts === +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>x : Symbol(x, Decl(commentsArgumentsOfCallExpression2.ts, 0, 13)) +>y : Symbol(y, Decl(commentsArgumentsOfCallExpression2.ts, 0, 27)) +>w : Symbol(w, Decl(commentsArgumentsOfCallExpression2.ts, 0, 42)) + +var a, b: any; +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) + + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.types b/tests/baselines/reference/commentsArgumentsOfCallExpression2.types new file mode 100644 index 00000000000..f0a10077e66 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.types @@ -0,0 +1,55 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression2.ts === +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +>foo : (x: any, y: any, w?: any) => void +>x : any +>y : any +>w : any + +var a, b: any; +>a : any +>b : any + +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +>foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b) : void +>foo : (x: any, y: any, w?: any) => void +>1 : number +>1 + 2 : number +>1 : number +>2 : number +>a + b : any +>a : any +>b : any + +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +>foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b) : void +>foo : (x: any, y: any, w?: any) => void +>function () { } : () => void +>() => { } : () => void +>a + /*e3*/ b : any +>a : any +>b : any + +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +>foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)) : void +>foo : (x: any, y: any, w?: any) => void +>function () { } : () => void +>() => { } : () => void +>(a + b) : any +>a + b : any +>a : any +>b : any + +foo( +>foo( /*c4*/ function () { }, /*d4*/() => { }, /*e4*/ /*e5*/ "hello") : void +>foo : (x: any, y: any, w?: any) => void + + /*c4*/ function () { }, +>function () { } : () => void + + /*d4*/() => { }, +>() => { } : () => void + + /*e4*/ + /*e5*/ "hello"); +>"hello" : string + diff --git a/tests/baselines/reference/commentsBeforeFunctionExpression1.js b/tests/baselines/reference/commentsBeforeFunctionExpression1.js index 0e23722faf3..5b250b9c064 100644 --- a/tests/baselines/reference/commentsBeforeFunctionExpression1.js +++ b/tests/baselines/reference/commentsBeforeFunctionExpression1.js @@ -6,5 +6,5 @@ var v = { //// [commentsBeforeFunctionExpression1.js] var v = { - f: function (a) { return 0; } + f: /**own f*/ function (a) { return 0; } }; diff --git a/tests/baselines/reference/commentsInterface.js b/tests/baselines/reference/commentsInterface.js index bff79a02aa5..3deac9871f1 100644 --- a/tests/baselines/reference/commentsInterface.js +++ b/tests/baselines/reference/commentsInterface.js @@ -89,7 +89,7 @@ var i2_i_nc_fnfoo = i2_i.nc_fnfoo; var i2_i_nc_fnfoo_r = i2_i.nc_fnfoo(10); var i3_i; i3_i = { - f: function (/**i3_i a*/ a) { return "Hello" + a; }, + f: /**own f*/ function (/**i3_i a*/ a) { return "Hello" + a; }, l: this.f, /** own x*/ x: this.f(10), diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js new file mode 100644 index 00000000000..fa7790443ac --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js @@ -0,0 +1,29 @@ +//// [commentsOnPropertyOfObjectLiteral1.ts] +var resolve = { + id: /*! @ngInject */ (details: any) => details.id, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ (details: any) => details.id, + id3: + /*! @ngInject */ + (details: any) => details.id, + id4: + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +}; + +//// [commentsOnPropertyOfObjectLiteral1.js] +var resolve = { + id: /*! @ngInject */ function (details) { return details.id; }, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ function (details) { return details.id; }, + id3: + /*! @ngInject */ + function (details) { return details.id; }, + id4: + /*! @ngInject */ + /* C2 */ + function (details) { return details.id; } +}; diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols new file mode 100644 index 00000000000..b48c1fb982c --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols @@ -0,0 +1,37 @@ +=== tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts === +var resolve = { +>resolve : Symbol(resolve, Decl(commentsOnPropertyOfObjectLiteral1.ts, 0, 3)) + + id: /*! @ngInject */ (details: any) => details.id, +>id : Symbol(id, Decl(commentsOnPropertyOfObjectLiteral1.ts, 0, 15)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 26)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 26)) + + id1: /* c1 */ "hello", +>id1 : Symbol(id1, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 54)) + + id2: +>id2 : Symbol(id2, Decl(commentsOnPropertyOfObjectLiteral1.ts, 2, 26)) + + /*! @ngInject */ (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 26)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 26)) + + id3: +>id3 : Symbol(id3, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 54)) + + /*! @ngInject */ + (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 5)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 5)) + + id4: +>id4 : Symbol(id4, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 33)) + + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 11, 5)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 11, 5)) + +}; diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types new file mode 100644 index 00000000000..93ce87558d8 --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types @@ -0,0 +1,51 @@ +=== tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts === +var resolve = { +>resolve : { id: (details: any) => any; id1: string; id2: (details: any) => any; id3: (details: any) => any; id4: (details: any) => any; } +>{ id: /*! @ngInject */ (details: any) => details.id, id1: /* c1 */ "hello", id2: /*! @ngInject */ (details: any) => details.id, id3: /*! @ngInject */ (details: any) => details.id, id4: /*! @ngInject */ /* C2 */ (details: any) => details.id,} : { id: (details: any) => any; id1: string; id2: (details: any) => any; id3: (details: any) => any; id4: (details: any) => any; } + + id: /*! @ngInject */ (details: any) => details.id, +>id : (details: any) => any +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id1: /* c1 */ "hello", +>id1 : string +>"hello" : string + + id2: +>id2 : (details: any) => any + + /*! @ngInject */ (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id3: +>id3 : (details: any) => any + + /*! @ngInject */ + (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id4: +>id4 : (details: any) => any + + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + +}; diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols index 172336603ab..3e23a7812f5 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols @@ -82,5 +82,7 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >IWithCallSignatures : Symbol(IWithCallSignatures, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 9, 1)) >IWithCallSignatures4 : Symbol(IWithCallSignatures4, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 18, 1)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>a.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types index 02dfecf5c08..8e1915d4754 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types @@ -90,10 +90,10 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >x4 : IWithCallSignatures | IWithCallSignatures4 >IWithCallSignatures : IWithCallSignatures >IWithCallSignatures4 : IWithCallSignatures4 ->a => /*here a should be any*/ a.toString() : (a: any) => any ->a : any ->a.toString() : any ->a.toString : any ->a : any ->toString : any +>a => /*here a should be any*/ a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.js b/tests/baselines/reference/declFileObjectLiteralWithAccessors.js index 85897bc2c9d..7886736f7e4 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.js +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.js @@ -20,8 +20,8 @@ function makePoint(x) { }; } ; -var point = makePoint(2); -var x = point.x; +var /*4*/ point = makePoint(2); +var /*2*/ x = point.x; point.x = 30; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js b/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js index dd39a30f7a2..8d79a576b06 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js @@ -16,8 +16,8 @@ function makePoint(x) { }; } ; -var point = makePoint(2); -var x = point.x; +var /*4*/ point = makePoint(2); +var /*2*/ x = point.x; //// [declFileObjectLiteralWithOnlyGetter.d.ts] diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js index e219e885053..f7a48fe810c 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js @@ -17,7 +17,7 @@ function makePoint(x) { }; } ; -var point = makePoint(2); +var /*3*/ point = makePoint(2); point.x = 30; diff --git a/tests/baselines/reference/decoratorMetadata.js b/tests/baselines/reference/decoratorMetadata.js new file mode 100644 index 00000000000..ea776d09910 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.js @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/decorators/decoratorMetadata.ts] //// + +//// [service.ts] +export default class Service { +} +//// [component.ts] +import Service from "./service"; + +declare var decorator: any; + +@decorator +class MyComponent { + constructor(public Service: Service) { + } +} + +//// [service.js] +var Service = (function () { + function Service() { + } + return Service; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Service; +//// [component.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); + switch (arguments.length) { + case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); + case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); + case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); + } +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var MyComponent = (function () { + function MyComponent(Service) { + this.Service = Service; + } + MyComponent = __decorate([ + decorator, + __metadata('design:paramtypes', [service_1.default]) + ], MyComponent); + return MyComponent; +})(); diff --git a/tests/baselines/reference/decoratorMetadata.symbols b/tests/baselines/reference/decoratorMetadata.symbols new file mode 100644 index 00000000000..706f5ace8a9 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/decorators/service.ts === +export default class Service { +>Service : Symbol(Service, Decl(service.ts, 0, 0)) +} +=== tests/cases/conformance/decorators/component.ts === +import Service from "./service"; +>Service : Symbol(Service, Decl(component.ts, 0, 6)) + +declare var decorator: any; +>decorator : Symbol(decorator, Decl(component.ts, 2, 11)) + +@decorator +>decorator : Symbol(decorator, Decl(component.ts, 2, 11)) + +class MyComponent { +>MyComponent : Symbol(MyComponent, Decl(component.ts, 2, 27)) + + constructor(public Service: Service) { +>Service : Symbol(Service, Decl(component.ts, 6, 16)) +>Service : Symbol(Service, Decl(component.ts, 0, 6)) + } +} diff --git a/tests/baselines/reference/decoratorMetadata.types b/tests/baselines/reference/decoratorMetadata.types new file mode 100644 index 00000000000..b0ce80fb1e4 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/decorators/service.ts === +export default class Service { +>Service : Service +} +=== tests/cases/conformance/decorators/component.ts === +import Service from "./service"; +>Service : typeof Service + +declare var decorator: any; +>decorator : any + +@decorator +>decorator : any + +class MyComponent { +>MyComponent : MyComponent + + constructor(public Service: Service) { +>Service : Service +>Service : Service + } +} diff --git a/tests/baselines/reference/extendClassExpressionFromModule.js b/tests/baselines/reference/extendClassExpressionFromModule.js new file mode 100644 index 00000000000..cbd36f7e799 --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.js @@ -0,0 +1,35 @@ +//// [tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts] //// + +//// [foo1.ts] +class x{} + +export = x; + +//// [foo2.ts] +import foo1 = require('./foo1'); +var x = foo1; +class y extends x {} + + +//// [foo1.js] +var x = (function () { + function x() { + } + return x; +})(); +module.exports = x; +//// [foo2.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var foo1 = require('./foo1'); +var x = foo1; +var y = (function (_super) { + __extends(y, _super); + function y() { + _super.apply(this, arguments); + } + return y; +})(x); diff --git a/tests/baselines/reference/extendClassExpressionFromModule.symbols b/tests/baselines/reference/extendClassExpressionFromModule.symbols new file mode 100644 index 00000000000..c131ea8fa28 --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/classExpressions/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +var x = foo1; +>x : Symbol(x, Decl(foo2.ts, 1, 3)) +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +class y extends x {} +>y : Symbol(y, Decl(foo2.ts, 1, 13)) + +=== tests/cases/conformance/classes/classExpressions/foo1.ts === +class x{} +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +export = x; +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + diff --git a/tests/baselines/reference/extendClassExpressionFromModule.types b/tests/baselines/reference/extendClassExpressionFromModule.types new file mode 100644 index 00000000000..d03623d50aa --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/classExpressions/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : typeof foo1 + +var x = foo1; +>x : typeof foo1 +>foo1 : typeof foo1 + +class y extends x {} +>y : y +>x : foo1 + +=== tests/cases/conformance/classes/classExpressions/foo1.ts === +class x{} +>x : x + +export = x; +>x : x + diff --git a/tests/baselines/reference/jsxAndTypeAssertion.js b/tests/baselines/reference/jsxAndTypeAssertion.js index 0b402b43de2..0a493006dc6 100644 --- a/tests/baselines/reference/jsxAndTypeAssertion.js +++ b/tests/baselines/reference/jsxAndTypeAssertion.js @@ -29,21 +29,18 @@ var foo = (function () { return foo; })(); var x; -x = {test}: }; +x = {test} }; x = ; -x = hello {} }; +x = hello {} } -x = }>hello}/>; +x = }>hello}/> -x = }>hello{}}; +x = }>hello{}} x = x, x = ; {{/foo/.test(x) ? : }} : -} - - -}}/>; +}}}/>; diff --git a/tests/baselines/reference/jsxHash.js b/tests/baselines/reference/jsxHash.js new file mode 100644 index 00000000000..04409a56eea --- /dev/null +++ b/tests/baselines/reference/jsxHash.js @@ -0,0 +1,26 @@ +//// [jsxHash.tsx] +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; + + +//// [jsxHash.jsx] +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; diff --git a/tests/baselines/reference/jsxHash.symbols b/tests/baselines/reference/jsxHash.symbols new file mode 100644 index 00000000000..8a6ad0849f0 --- /dev/null +++ b/tests/baselines/reference/jsxHash.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/jsxHash.tsx === +var t02 = {0}#; +>t02 : Symbol(t02, Decl(jsxHash.tsx, 0, 3)) + +var t03 = #{0}; +>t03 : Symbol(t03, Decl(jsxHash.tsx, 1, 3)) + +var t04 = #{0}#; +>t04 : Symbol(t04, Decl(jsxHash.tsx, 2, 3)) + +var t05 = #; +>t05 : Symbol(t05, Decl(jsxHash.tsx, 3, 3)) + +var t06 = #; +>t06 : Symbol(t06, Decl(jsxHash.tsx, 4, 3)) + +var t07 = ##; +>t07 : Symbol(t07, Decl(jsxHash.tsx, 5, 3)) + +var t08 = #; +>t08 : Symbol(t08, Decl(jsxHash.tsx, 6, 3)) + +var t09 = ##; +>t09 : Symbol(t09, Decl(jsxHash.tsx, 7, 3)) + +var t10 = #; +>t10 : Symbol(t10, Decl(jsxHash.tsx, 8, 3)) + +var t11 = #; +>t11 : Symbol(t11, Decl(jsxHash.tsx, 9, 3)) + +var t12 = #; +>t12 : Symbol(t12, Decl(jsxHash.tsx, 10, 3)) + diff --git a/tests/baselines/reference/jsxHash.types b/tests/baselines/reference/jsxHash.types new file mode 100644 index 00000000000..e614ebd3e0b --- /dev/null +++ b/tests/baselines/reference/jsxHash.types @@ -0,0 +1,86 @@ +=== tests/cases/compiler/jsxHash.tsx === +var t02 = {0}#; +>t02 : any +>{0}# : any +>a : any +>a : any + +var t03 = #{0}; +>t03 : any +>#{0} : any +>a : any +>a : any + +var t04 = #{0}#; +>t04 : any +>#{0}# : any +>a : any +>a : any + +var t05 = #; +>t05 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t06 = #; +>t06 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t07 = ##; +>t07 : any +>## : any +>a : any +># : any +>i : any +>i : any +>a : any + +var t08 = #; +>t08 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t09 = ##; +>t09 : any +>## : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t10 = #; +>t10 : any +># : any +>a : any +> : any +>i : any +>a : any + +var t11 = #; +>t11 : any +># : any +>a : any +> : any +>i : any +>a : any + +var t12 = #; +>t12 : any +># : any +>a : any +>a : any + diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt index 99ae5056a4c..02bc56e823e 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt @@ -62,10 +62,8 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(24,15): error TS1003: tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(25,7): error TS1005: '...' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(25,7): error TS2304: Cannot find name 'props'. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(27,17): error TS1005: '>' expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(27,18): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,10): error TS2304: Cannot find name 'props'. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,28): error TS1005: '>' expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,29): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(32,6): error TS1005: '{' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,6): error TS1005: '{' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,7): error TS1109: Expression expected. @@ -73,7 +71,7 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,4): error TS1003: tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002: Expected corresponding JSX closing tag for 'a'. -==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (73 errors) ==== +==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (71 errors) ==== declare var React: any; ; @@ -229,15 +227,11 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002
stuff
; ~ !!! error TS1005: '>' expected. - ~~~ -!!! error TS1109: Expression expected.
stuff
; ~~~~~ !!! error TS2304: Cannot find name 'props'. ~ !!! error TS1005: '>' expected. - ~~~ -!!! error TS1109: Expression expected. >; >; diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js index 13808cc29e0..daf344b08da 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js @@ -65,17 +65,17 @@ a['foo'] > ; ; var x =
one
two
;; var x =
one
/* intervening comment */ /* intervening comment */
two
;; -
{"str"};}; -, id="b" />; -
"app">; +{"str"}}; + id="b" />; +
>;
; -
stuff
{}...props}>; -
stuff
{}...props}>; +
stuff
...props}>; +
stuff
...props}>; >; >; ; ; }; - .../*hai*/asdf/>;; + /*hai*//*hai*/asdf/>;; diff --git a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt index 7445ab85a54..e8649cfb567 100644 --- a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt +++ b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt @@ -1,11 +1,10 @@ -tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(7,30): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(10,30): error TS2345: Argument of type '(number | string)[]' is not assignable to parameter of type 'number[]'. Type 'number | string' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,11): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts (3 errors) ==== +==== tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts (2 errors) ==== function map(xs: T[], f: (x: T) => U) { var ys: U[] = []; xs.forEach(x => ys.push(f(x))); @@ -13,8 +12,6 @@ tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,11): e } var r0 = map([1, ""], (x) => x.toString()); - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. var r5 = map([1, ""], (x) => x.toString()); var r6 = map([1, ""], (x) => x.toString()); var r7 = map([1, ""], (x) => x.toString()); // error diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties2.js b/tests/baselines/reference/objectTypesWithOptionalProperties2.js index cf0d113c244..e5ffbf09c10 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties2.js +++ b/tests/baselines/reference/objectTypesWithOptionalProperties2.js @@ -42,5 +42,6 @@ var C2 = (function () { return C2; })(); var b = { - x: function () { }, 1: // error + x: function () { }, 1: // error + // error }; diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.js b/tests/baselines/reference/paramterDestrcuturingDeclaration.js new file mode 100644 index 00000000000..6920f22b0d4 --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.js @@ -0,0 +1,20 @@ +//// [paramterDestrcuturingDeclaration.ts] + +interface C { + ({p: name}): any; + new ({p: boolean}): any; +} + + +//// [paramterDestrcuturingDeclaration.js] + + +//// [paramterDestrcuturingDeclaration.d.ts] +interface C { + ({p: name}: { + p: any; + }): any; + new ({p: boolean}: { + p: any; + }): any; +} diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols b/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols new file mode 100644 index 00000000000..dd11b302eea --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/paramterDestrcuturingDeclaration.ts === + +interface C { +>C : Symbol(C, Decl(paramterDestrcuturingDeclaration.ts, 0, 0)) + + ({p: name}): any; +>p : Symbol(p) +>name : Symbol(name, Decl(paramterDestrcuturingDeclaration.ts, 2, 6)) + + new ({p: boolean}): any; +>p : Symbol(p) +>boolean : Symbol(boolean, Decl(paramterDestrcuturingDeclaration.ts, 3, 10)) +} + diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.types b/tests/baselines/reference/paramterDestrcuturingDeclaration.types new file mode 100644 index 00000000000..4b49ce22035 --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/paramterDestrcuturingDeclaration.ts === + +interface C { +>C : C + + ({p: name}): any; +>p : any +>name : any + + new ({p: boolean}): any; +>p : any +>boolean : any +} + diff --git a/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt b/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt new file mode 100644 index 00000000000..a6d63ce1754 --- /dev/null +++ b/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,18): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,22): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,23): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,18): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,26): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,27): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + + +==== tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts (6 errors) ==== + var regex1 = / asdf /; + var regex2 = /**// asdf /; + var regex3 = /**///**/ asdf / // should be a comment line + 1; + var regex4 = /**// /**/asdf /; + ~~~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS1109: Expression expected. + ~~~~~~~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + var regex5 = /**// asdf/**/ /; + ~~~~~~~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS1109: Expression expected. + ~~~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. \ No newline at end of file diff --git a/tests/baselines/reference/parseRegularExpressionMixedWithComments.js b/tests/baselines/reference/parseRegularExpressionMixedWithComments.js new file mode 100644 index 00000000000..c7aded33697 --- /dev/null +++ b/tests/baselines/reference/parseRegularExpressionMixedWithComments.js @@ -0,0 +1,14 @@ +//// [parseRegularExpressionMixedWithComments.ts] +var regex1 = / asdf /; +var regex2 = /**// asdf /; +var regex3 = /**///**/ asdf / // should be a comment line +1; +var regex4 = /**// /**/asdf /; +var regex5 = /**// asdf/**/ /; + +//// [parseRegularExpressionMixedWithComments.js] +var regex1 = / asdf /; +var regex2 = / asdf /; +var regex3 = 1; +var regex4 = / / * * /asdf /; +var regex5 = / asdf/ * * / /; diff --git a/tests/baselines/reference/parserindenter.js b/tests/baselines/reference/parserindenter.js index 511e75ea135..a60eadc66a1 100644 --- a/tests/baselines/reference/parserindenter.js +++ b/tests/baselines/reference/parserindenter.js @@ -890,7 +890,7 @@ var Formatting; return result; }; Indenter.GetIndentSizeFromIndentText = function (indentText, editorOptions) { - return GetIndentSizeFromText(indentText, editorOptions, false); + return GetIndentSizeFromText(indentText, editorOptions, /*includeNonIndentChars:*/ false); }; Indenter.GetIndentSizeFromText = function (text, editorOptions, includeNonIndentChars) { var indentSize = 0; @@ -1174,7 +1174,7 @@ var Formatting; return null; var origIndentText = this.snapshot.GetText(new Span(indentEditInfo.OrigIndentPosition, indentEditInfo.OrigIndentLength())); var newIndentText = indentEditInfo.Indentation(); - var origIndentSize = Indenter.GetIndentSizeFromText(origIndentText, this.editorOptions, true); + var origIndentSize = Indenter.GetIndentSizeFromText(origIndentText, this.editorOptions, /*includeNonIndentChars*/ true); var newIndentSize = Indenter.GetIndentSizeFromIndentText(newIndentText, this.editorOptions); // Check the child's position whether it's before the parent position // if so indent the child based on the first token on the line as opposed to the parent position diff --git a/tests/baselines/reference/reexportClassDefinition.js b/tests/baselines/reference/reexportClassDefinition.js new file mode 100644 index 00000000000..5d534f1e3a3 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.js @@ -0,0 +1,45 @@ +//// [tests/cases/conformance/externalModules/reexportClassDefinition.ts] //// + +//// [foo1.ts] +class x{} +export = x; + +//// [foo2.ts] +import foo1 = require('./foo1'); + +export = { + x: foo1 +} + +//// [foo3.ts] +import foo2 = require('./foo2') +class x extends foo2.x {} + + + +//// [foo1.js] +var x = (function () { + function x() { + } + return x; +})(); +module.exports = x; +//// [foo2.js] +var foo1 = require('./foo1'); +module.exports = { + x: foo1 +}; +//// [foo3.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var foo2 = require('./foo2'); +var x = (function (_super) { + __extends(x, _super); + function x() { + _super.apply(this, arguments); + } + return x; +})(foo2.x); diff --git a/tests/baselines/reference/reexportClassDefinition.symbols b/tests/baselines/reference/reexportClassDefinition.symbols new file mode 100644 index 00000000000..52133657985 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/externalModules/foo3.ts === +import foo2 = require('./foo2') +>foo2 : Symbol(foo2, Decl(foo3.ts, 0, 0)) + +class x extends foo2.x {} +>x : Symbol(x, Decl(foo3.ts, 0, 31)) +>foo2 : Symbol(foo2, Decl(foo3.ts, 0, 0)) + + +=== tests/cases/conformance/externalModules/foo1.ts === +class x{} +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +export = x; +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +=== tests/cases/conformance/externalModules/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +export = { + x: foo1 +>x : Symbol(x, Decl(foo2.ts, 2, 10)) +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/reexportClassDefinition.types b/tests/baselines/reference/reexportClassDefinition.types new file mode 100644 index 00000000000..c39bbf9c136 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/externalModules/foo3.ts === +import foo2 = require('./foo2') +>foo2 : { x: typeof x; } + +class x extends foo2.x {} +>x : x +>foo2.x : x +>foo2 : { x: typeof x; } +>x : typeof x + + +=== tests/cases/conformance/externalModules/foo1.ts === +class x{} +>x : x + +export = x; +>x : x + +=== tests/cases/conformance/externalModules/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : typeof foo1 + +export = { +>{ x: foo1} : { x: typeof foo1; } + + x: foo1 +>x : typeof foo1 +>foo1 : typeof foo1 +} + diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index c63b3589085..fcecfc9b0f8 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -14,19 +14,19 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; - exports_1("n", file1_1["default"]); - exports_1("n1", file1_1["default"]); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); + function (n2_1) { + n2 = n2_1; }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1["default"]); + exports_1("n1", file1_1["default"]); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index bdb920414de..a86088a3463 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -14,19 +14,19 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; - exports_1("n", file1_1.default); - exports_1("n1", file1_1.default); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); + function (n2_1) { + n2 = n2_1; }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1.default); + exports_1("n1", file1_1.default); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule11.js b/tests/baselines/reference/systemModule11.js index 34dd0d3df5f..bf9b57c511c 100644 --- a/tests/baselines/reference/systemModule11.js +++ b/tests/baselines/reference/systemModule11.js @@ -59,8 +59,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -82,8 +82,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { exports_1("x", x); @@ -108,14 +108,14 @@ System.register(['a', 'bar'], function(exports_1) { } return { setters:[ - function (_a_1) { - var reexports_1 = {}; - reexports_1["x"] = _a_1["x"]; - reexports_1["z"] = _a_1["y"]; - exports_1(reexports_1); + function (a_1_1) { + exports_1({ + "x": a_1_1["x"], + "z": a_1_1["y"] + }); }, - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -130,11 +130,11 @@ System.register(['a'], function(exports_1) { exports_1("default", default_1); return { setters:[ - function (_a_1) { - var reexports_1 = {}; - reexports_1["s"] = _a_1["s"]; - reexports_1["s2"] = _a_1["s1"]; - exports_1(reexports_1); + function (a_1_1) { + exports_1({ + "s": a_1_1["s"], + "s2": a_1_1["s1"] + }); }], execute: function() { exports_1("z", z); @@ -154,8 +154,8 @@ System.register(['a'], function(exports_1) { } return { setters:[ - function (_a_1) { - exportStar_1(_a_1); + function (a_1_1) { + exportStar_1(a_1_1); }], execute: function() { } diff --git a/tests/baselines/reference/systemModule14.errors.txt b/tests/baselines/reference/systemModule14.errors.txt new file mode 100644 index 00000000000..6ba64896df8 --- /dev/null +++ b/tests/baselines/reference/systemModule14.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/systemModule14.ts(6,17): error TS2307: Cannot find module 'foo'. + + +==== tests/cases/compiler/systemModule14.ts (1 errors) ==== + + function foo() { + return a; + } + + import {a} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {foo} + + var x = 1; + export {foo as b} \ No newline at end of file diff --git a/tests/baselines/reference/systemModule14.js b/tests/baselines/reference/systemModule14.js new file mode 100644 index 00000000000..76906db5980 --- /dev/null +++ b/tests/baselines/reference/systemModule14.js @@ -0,0 +1,31 @@ +//// [systemModule14.ts] + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} + +//// [systemModule14.js] +System.register(["foo"], function(exports_1) { + var foo_1; + var x; + function foo() { + return foo_1.a; + } + return { + setters:[ + function (foo_1_1) { + foo_1 = foo_1_1; + }], + execute: function() { + exports_1("foo", foo); + x = 1; + exports_1("b", foo); + } + } +}); diff --git a/tests/baselines/reference/systemModule15.js b/tests/baselines/reference/systemModule15.js new file mode 100644 index 00000000000..4d5536cbaa1 --- /dev/null +++ b/tests/baselines/reference/systemModule15.js @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/systemModule15.ts] //// + +//// [file1.ts] + + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +//// [file2.ts] + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +//// [file3.ts] + +export var value = "youpi"; +export default value; + +//// [file4.ts] + +export var value2 = "v"; + +//// [file3.js] +System.register([], function(exports_1) { + var value; + return { + setters:[], + execute: function() { + exports_1("value", value = "youpi"); + exports_1("default",value); + } + } +}); +//// [file4.js] +System.register([], function(exports_1) { + var value2; + return { + setters:[], + execute: function() { + exports_1("value2", value2 = "v"); + } + } +}); +//// [file2.js] +System.register(["./file3"], function(exports_1) { + var moduleCStar, file3_1, file3_2; + return { + setters:[ + function (moduleCStar_1) { + moduleCStar = moduleCStar_1; + file3_1 = moduleCStar_1; + file3_2 = moduleCStar_1; + }], + execute: function() { + exports_1("moduleCStar", moduleCStar); + exports_1("moduleC", file3_1["default"]); + exports_1("value", file3_2.value); + } + } +}); +//// [file1.js] +System.register(["./file2"], function(exports_1) { + var moduleB; + return { + setters:[ + function (moduleB_1) { + moduleB = moduleB_1; + }], + execute: function() { + use(moduleB.value); + use(moduleB.moduleC); + use(moduleB.moduleCStar); + } + } +}); diff --git a/tests/baselines/reference/systemModule15.symbols b/tests/baselines/reference/systemModule15.symbols new file mode 100644 index 00000000000..2572950a7f2 --- /dev/null +++ b/tests/baselines/reference/systemModule15.symbols @@ -0,0 +1,66 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) + +declare function use(v: any): void; +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>v : Symbol(v, Decl(file1.ts, 4, 21)) + +use(moduleB.value); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) + +use(moduleB.moduleC); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) + +use(moduleB.moduleCStar); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 1, 6)) + +import {value2} from "./file4" +>value2 : Symbol(value2, Decl(file2.ts, 2, 8)) + +import moduleC from "./file3" +>moduleC : Symbol(moduleC, Decl(file2.ts, 3, 6)) + +import {value} from "./file3" +>value : Symbol(value, Decl(file2.ts, 4, 8)) + +export { + moduleCStar, +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 6, 8)) + + moduleC, +>moduleC : Symbol(moduleC, Decl(file2.ts, 7, 16)) + + value +>value : Symbol(value, Decl(file2.ts, 8, 12)) +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +export default value; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : Symbol(value2, Decl(file4.ts, 1, 10)) + diff --git a/tests/baselines/reference/systemModule15.types b/tests/baselines/reference/systemModule15.types new file mode 100644 index 00000000000..502638dab93 --- /dev/null +++ b/tests/baselines/reference/systemModule15.types @@ -0,0 +1,71 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : typeof moduleB + +declare function use(v: any): void; +>use : (v: any) => void +>v : any + +use(moduleB.value); +>use(moduleB.value) : void +>use : (v: any) => void +>moduleB.value : string +>moduleB : typeof moduleB +>value : string + +use(moduleB.moduleC); +>use(moduleB.moduleC) : void +>use : (v: any) => void +>moduleB.moduleC : string +>moduleB : typeof moduleB +>moduleC : string + +use(moduleB.moduleCStar); +>use(moduleB.moduleCStar) : void +>use : (v: any) => void +>moduleB.moduleCStar : typeof +>moduleB : typeof moduleB +>moduleCStar : typeof + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : typeof moduleCStar + +import {value2} from "./file4" +>value2 : string + +import moduleC from "./file3" +>moduleC : string + +import {value} from "./file3" +>value : string + +export { + moduleCStar, +>moduleCStar : typeof moduleCStar + + moduleC, +>moduleC : string + + value +>value : string +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : string +>"youpi" : string + +export default value; +>value : string + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : string +>"v" : string + diff --git a/tests/baselines/reference/systemModule16.errors.txt b/tests/baselines/reference/systemModule16.errors.txt new file mode 100644 index 00000000000..8c79c9218e4 --- /dev/null +++ b/tests/baselines/reference/systemModule16.errors.txt @@ -0,0 +1,33 @@ +tests/cases/compiler/systemModule16.ts(2,20): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(3,20): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(4,15): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(5,15): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(8,32): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(9,32): error TS2307: Cannot find module 'bar'. + + +==== tests/cases/compiler/systemModule16.ts (6 errors) ==== + + import * as x from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + import * as y from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export * from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export * from "bar" + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export {x} + export {y} + import {a1, b1, c1 as d1} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {a2, b2, c2 as d2} from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + + x,y,a1,b1,d1; + \ No newline at end of file diff --git a/tests/baselines/reference/systemModule16.js b/tests/baselines/reference/systemModule16.js new file mode 100644 index 00000000000..851b941492a --- /dev/null +++ b/tests/baselines/reference/systemModule16.js @@ -0,0 +1,54 @@ +//// [systemModule16.ts] + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1; + + +//// [systemModule16.js] +System.register(["foo", "bar"], function(exports_1) { + var x, y, foo_1; + var exportedNames_1 = { + 'x': true, + 'y': true, + 'a2': true, + 'b2': true, + 'd2': true + }; + function exportStar_1(m) { + var exports = {}; + for(var n in m) { + if (n !== "default"&& !exportedNames_1.hasOwnProperty(n)) exports[n] = m[n]; + } + exports_1(exports); + } + return { + setters:[ + function (x_1) { + x = x_1; + exportStar_1(x_1); + foo_1 = x_1; + }, + function (y_1) { + y = y_1; + exportStar_1(y_1); + exports_1({ + "a2": y_1["a2"], + "b2": y_1["b2"], + "d2": y_1["c2"] + }); + }], + execute: function() { + exports_1("x", x); + exports_1("y", y); + x, y, foo_1.a1, foo_1.b1, foo_1.c1; + } + } +}); diff --git a/tests/baselines/reference/systemModule9.js b/tests/baselines/reference/systemModule9.js index c282a47b686..d7913f2f8b7 100644 --- a/tests/baselines/reference/systemModule9.js +++ b/tests/baselines/reference/systemModule9.js @@ -38,24 +38,24 @@ System.register(['file1', 'file2', 'file3', 'file4', 'file5', 'file6', 'file7'], } return { setters:[ - function (_ns) { - ns = _ns; + function (ns_1) { + ns = ns_1; }, - function (_file2_1) { - file2_1 = _file2_1; + function (file2_1_1) { + file2_1 = file2_1_1; }, - function (_file3_1) { - file3_1 = _file3_1; + function (file3_1_1) { + file3_1 = file3_1_1; }, - function (_) {}, - function (_file5_1) { - file5_1 = _file5_1; + function (_1) {}, + function (file5_1_1) { + file5_1 = file5_1_1; }, - function (_ns3) { - ns3 = _ns3; + function (ns3_1) { + ns3 = ns3_1; }, - function (_file7_1) { - exportStar_1(_file7_1); + function (file7_1_1) { + exportStar_1(file7_1_1); }], execute: function() { ns.f(); diff --git a/tests/baselines/reference/systemModuleWithSuperClass.js b/tests/baselines/reference/systemModuleWithSuperClass.js index 3484606ee0e..9d1e87fbc66 100644 --- a/tests/baselines/reference/systemModuleWithSuperClass.js +++ b/tests/baselines/reference/systemModuleWithSuperClass.js @@ -38,8 +38,8 @@ System.register(['./foo'], function(exports_1) { var Bar; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { Bar = (function (_super) { diff --git a/tests/baselines/reference/tsxErrorRecovery1.errors.txt b/tests/baselines/reference/tsxErrorRecovery1.errors.txt index dc4f4d51afe..7aea986526b 100644 --- a/tests/baselines/reference/tsxErrorRecovery1.errors.txt +++ b/tests/baselines/reference/tsxErrorRecovery1.errors.txt @@ -1,7 +1,10 @@ tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(5,19): error TS1109: Expression expected. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(8,11): error TS2304: Cannot find name 'a'. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(8,12): error TS1005: '}' expected. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(9,1): error TS17002: Expected corresponding JSX closing tag for 'div'. -==== tests/cases/conformance/jsx/tsxErrorRecovery1.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/tsxErrorRecovery1.tsx (4 errors) ==== declare namespace JSX { interface Element { } } @@ -12,4 +15,10 @@ tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(5,19): error TS1109: Expressio } // Shouldn't see any errors down here var y = { a: 1 }; - \ No newline at end of file + ~ +!!! error TS2304: Cannot find name 'a'. + ~ +!!! error TS1005: '}' expected. + + +!!! error TS17002: Expected corresponding JSX closing tag for 'div'. \ No newline at end of file diff --git a/tests/baselines/reference/tsxErrorRecovery1.js b/tests/baselines/reference/tsxErrorRecovery1.js index 8d20951f6ed..62db6b0f012 100644 --- a/tests/baselines/reference/tsxErrorRecovery1.js +++ b/tests/baselines/reference/tsxErrorRecovery1.js @@ -11,7 +11,9 @@ var y = { a: 1 }; //// [tsxErrorRecovery1.jsx] function foo() { - var x =
{}
; + var x =
{}div> +} +// Shouldn't see any errors down here +var y = {a} 1 }; +; } -// Shouldn't see any errors down here -var y = { a: 1 }; diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.js b/tests/baselines/reference/typeAliasDeclarationEmit.js new file mode 100644 index 00000000000..6e82fe4b07d --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.js @@ -0,0 +1,14 @@ +//// [typeAliasDeclarationEmit.ts] + +export type callback = () => T; + +export type CallbackArray = () => T; + +//// [typeAliasDeclarationEmit.js] +define(["require", "exports"], function (require, exports) { +}); + + +//// [typeAliasDeclarationEmit.d.ts] +export declare type callback = () => T; +export declare type CallbackArray = () => T; diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.symbols b/tests/baselines/reference/typeAliasDeclarationEmit.symbols new file mode 100644 index 00000000000..5f98ea75a5a --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.symbols @@ -0,0 +1,13 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit.ts === + +export type callback = () => T; +>callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) + +export type CallbackArray = () => T; +>CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 1, 34)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.types b/tests/baselines/reference/typeAliasDeclarationEmit.types new file mode 100644 index 00000000000..6f9359e36f5 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit.ts === + +export type callback = () => T; +>callback : () => T +>T : T +>T : T + +export type CallbackArray = () => T; +>CallbackArray : () => T +>T : T +>callback : () => T +>T : T + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.js b/tests/baselines/reference/typeAliasDeclarationEmit2.js new file mode 100644 index 00000000000..4bb1bd3efd9 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.js @@ -0,0 +1,13 @@ +//// [typeAliasDeclarationEmit2.ts] + +export type A = { value: a }; + +//// [typeAliasDeclarationEmit2.js] +define(["require", "exports"], function (require, exports) { +}); + + +//// [typeAliasDeclarationEmit2.d.ts] +export declare type A = { + value: a; +}; diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.symbols b/tests/baselines/reference/typeAliasDeclarationEmit2.symbols new file mode 100644 index 00000000000..aebd457d24e --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit2.ts === + +export type A = { value: a }; +>A : Symbol(A, Decl(typeAliasDeclarationEmit2.ts, 0, 0)) +>a : Symbol(a, Decl(typeAliasDeclarationEmit2.ts, 1, 14)) +>value : Symbol(value, Decl(typeAliasDeclarationEmit2.ts, 1, 20)) +>a : Symbol(a, Decl(typeAliasDeclarationEmit2.ts, 1, 14)) + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.types b/tests/baselines/reference/typeAliasDeclarationEmit2.types new file mode 100644 index 00000000000..bc8bd30935e --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit2.ts === + +export type A = { value: a }; +>A : { value: a; } +>a : a +>value : a +>a : a + diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt b/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt deleted file mode 100644 index 37a662e007c..00000000000 --- a/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt +++ /dev/null @@ -1,103 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts(93,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts (1 errors) ==== - // In the true expression of a conditional expression, - // the type of a variable or parameter is narrowed by any type guard in the condition when true, - // provided the true expression contains no assignments to the variable or parameter. - // In the false expression of a conditional expression, - // the type of a variable or parameter is narrowed by any type guard in the condition when false, - // provided the false expression contains no assignments to the variable or parameter. - - function foo(x: number | string) { - return typeof x === "string" - ? x.length // string - : x++; // number - } - function foo2(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - return typeof x === "string" - ? (x = 10 && x)// string | number - : x; // string | number - } - function foo3(x: number | string) { - // x is assigned in the if false branch, the type is not narrowed - // even though assigned using same type as narrowed expression - return typeof x === "string" - ? (x = "Hello" && x) // string | number - : x; // string | number - } - function foo4(x: number | string) { - // false branch updates the variable - so here it is not number - // even though assigned using same type as narrowed expression - return typeof x === "string" - ? x // string | number - : (x = 10 && x); // string | number - } - function foo5(x: number | string) { - // false branch updates the variable - so here it is not number - return typeof x === "string" - ? x // string | number - : (x = "hello" && x); // string | number - } - function foo6(x: number | string) { - // Modify in both branches - return typeof x === "string" - ? (x = 10 && x) // string | number - : (x = "hello" && x); // string | number - } - function foo7(x: number | string | boolean) { - return typeof x === "string" - ? x === "hello" // string - : typeof x === "boolean" - ? x // boolean - : x == 10; // number - } - function foo8(x: number | string | boolean) { - var b: number | boolean; - return typeof x === "string" - ? x === "hello" - : ((b = x) && // number | boolean - (typeof x === "boolean" - ? x // boolean - : x == 10)); // number - } - function foo9(x: number | string) { - var y = 10; - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - return typeof x === "string" - ? ((y = x.length) && x === "hello") // string - : x === 10; // number - } - function foo10(x: number | string | boolean) { - // Mixing typeguards - var b: boolean | number; - return typeof x === "string" - ? x // string - : ((b = x) // x is number | boolean - && typeof x === "number" - && x.toString()); // x is number - } - function foo11(x: number | string | boolean) { - // Mixing typeguards - // Assigning value to x deep inside another guard stops narrowing of type too - var b: number | boolean | string; - return typeof x === "string" - ? x // number | boolean | string - changed in the false branch - : ((b = x) // x is number | boolean | string - because the assignment changed it - && typeof x === "number" - && (x = 10) // assignment to x - && x); // x is number | boolean | string - } - function foo12(x: number | string | boolean) { - // Mixing typeguards - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - var b: number | boolean | string; - return typeof x === "string" - ? (x = 10 && x.toString().length) // number | boolean | string - changed here - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - : ((b = x) // x is number | boolean | string - changed in true branch - && typeof x === "number" - && x); // x is number - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.symbols b/tests/baselines/reference/typeGuardsInConditionalExpression.symbols new file mode 100644 index 00000000000..ac35c1f18b9 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInConditionalExpression.symbols @@ -0,0 +1,251 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts === +// In the true expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when true, +// provided the true expression contains no assignments to the variable or parameter. +// In the false expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when false, +// provided the false expression contains no assignments to the variable or parameter. + +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInConditionalExpression.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) + + ? x.length // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + : x++; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInConditionalExpression.ts, 11, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + // x is assigned in the if true branch, the type is not narrowed + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + ? (x = 10 && x)// string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + : x; // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInConditionalExpression.ts, 17, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + // x is assigned in the if false branch, the type is not narrowed + // even though assigned using same type as narrowed expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + ? (x = "Hello" && x) // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + : x; // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) +} +function foo4(x: number | string) { +>foo4 : Symbol(foo4, Decl(typeGuardsInConditionalExpression.ts, 24, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + // false branch updates the variable - so here it is not number + // even though assigned using same type as narrowed expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + ? x // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + : (x = 10 && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) +} +function foo5(x: number | string) { +>foo5 : Symbol(foo5, Decl(typeGuardsInConditionalExpression.ts, 31, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + // false branch updates the variable - so here it is not number + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + ? x // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + : (x = "hello" && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) +} +function foo6(x: number | string) { +>foo6 : Symbol(foo6, Decl(typeGuardsInConditionalExpression.ts, 37, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + // Modify in both branches + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + ? (x = 10 && x) // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + : (x = "hello" && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInConditionalExpression.ts, 43, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + ? x === "hello" // string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + : typeof x === "boolean" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + : x == 10; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) +} +function foo8(x: number | string | boolean) { +>foo8 : Symbol(foo8, Decl(typeGuardsInConditionalExpression.ts, 50, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + ? x === "hello" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + : ((b = x) && // number | boolean +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + (typeof x === "boolean" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + : x == 10)); // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) +} +function foo9(x: number | string) { +>foo9 : Symbol(foo9, Decl(typeGuardsInConditionalExpression.ts, 59, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + var y = 10; +>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + ? ((y = x.length) && x === "hello") // string +>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + : x === 10; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) +} +function foo10(x: number | string | boolean) { +>foo10 : Symbol(foo10, Decl(typeGuardsInConditionalExpression.ts, 66, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + // Mixing typeguards + var b: boolean | number; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + ? x // string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + : ((b = x) // x is number | boolean +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + && x.toString()); // x is number +>x.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +} +function foo11(x: number | string | boolean) { +>foo11 : Symbol(foo11, Decl(typeGuardsInConditionalExpression.ts, 75, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + // Mixing typeguards + // Assigning value to x deep inside another guard stops narrowing of type too + var b: number | boolean | string; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + ? x // number | boolean | string - changed in the false branch +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + : ((b = x) // x is number | boolean | string - because the assignment changed it +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && (x = 10) // assignment to x +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && x); // x is number | boolean | string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) +} +function foo12(x: number | string | boolean) { +>foo12 : Symbol(foo12, Decl(typeGuardsInConditionalExpression.ts, 86, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + // Mixing typeguards + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + var b: number | boolean | string; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + ? (x = 10 && x.toString().length) // number | boolean | string - changed here +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +>x.toString().length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + : ((b = x) // x is number | boolean | string - changed in true branch +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + && x); // x is number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +} diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.types b/tests/baselines/reference/typeGuardsInConditionalExpression.types new file mode 100644 index 00000000000..ef048fb8562 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInConditionalExpression.types @@ -0,0 +1,388 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts === +// In the true expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when true, +// provided the true expression contains no assignments to the variable or parameter. +// In the false expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when false, +// provided the false expression contains no assignments to the variable or parameter. + +function foo(x: number | string) { +>foo : (x: number | string) => number +>x : number | string + + return typeof x === "string" +>typeof x === "string" ? x.length // string : x++ : number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x.length // string +>x.length : number +>x : string +>length : number + + : x++; // number +>x++ : number +>x : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x)// string | number : x : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = 10 && x)// string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string + + : x; // string | number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if false branch, the type is not narrowed + // even though assigned using same type as narrowed expression + return typeof x === "string" +>typeof x === "string" ? (x = "Hello" && x) // string | number : x : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = "Hello" && x) // string | number +>(x = "Hello" && x) : number | string +>x = "Hello" && x : number | string +>x : number | string +>"Hello" && x : number | string +>"Hello" : string +>x : number | string + + : x; // string | number +>x : number | string +} +function foo4(x: number | string) { +>foo4 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + // even though assigned using same type as narrowed expression + return typeof x === "string" +>typeof x === "string" ? x // string | number : (x = 10 && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x // string | number +>x : number | string + + : (x = 10 && x); // string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string +} +function foo5(x: number | string) { +>foo5 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + return typeof x === "string" +>typeof x === "string" ? x // string | number : (x = "hello" && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x // string | number +>x : number | string + + : (x = "hello" && x); // string | number +>(x = "hello" && x) : number | string +>x = "hello" && x : number | string +>x : number | string +>"hello" && x : number | string +>"hello" : string +>x : number | string +} +function foo6(x: number | string) { +>foo6 : (x: number | string) => number | string +>x : number | string + + // Modify in both branches + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x) // string | number : (x = "hello" && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = 10 && x) // string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string + + : (x = "hello" && x); // string | number +>(x = "hello" && x) : number | string +>x = "hello" && x : number | string +>x : number | string +>"hello" && x : number | string +>"hello" : string +>x : number | string +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x === "string" +>typeof x === "string" ? x === "hello" // string : typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x === "hello" // string +>x === "hello" : boolean +>x : string +>"hello" : string + + : typeof x === "boolean" +>typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + ? x // boolean +>x : boolean + + : x == 10; // number +>x == 10 : boolean +>x : number +>10 : number +} +function foo8(x: number | string | boolean) { +>foo8 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + var b: number | boolean; +>b : number | boolean + + return typeof x === "string" +>typeof x === "string" ? x === "hello" : ((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x === "hello" +>x === "hello" : boolean +>x : string +>"hello" : string + + : ((b = x) && // number | boolean +>((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean +>(b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10) : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean + + (typeof x === "boolean" +>(typeof x === "boolean" ? x // boolean : x == 10) : boolean +>typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + ? x // boolean +>x : boolean + + : x == 10)); // number +>x == 10 : boolean +>x : number +>10 : number +} +function foo9(x: number | string) { +>foo9 : (x: number | string) => boolean +>x : number | string + + var y = 10; +>y : number +>10 : number + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + return typeof x === "string" +>typeof x === "string" ? ((y = x.length) && x === "hello") // string : x === 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? ((y = x.length) && x === "hello") // string +>((y = x.length) && x === "hello") : boolean +>(y = x.length) && x === "hello" : boolean +>(y = x.length) : number +>y = x.length : number +>y : number +>x.length : number +>x : string +>length : number +>x === "hello" : boolean +>x : string +>"hello" : string + + : x === 10; // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo10(x: number | string | boolean) { +>foo10 : (x: number | string | boolean) => string +>x : number | string | boolean + + // Mixing typeguards + var b: boolean | number; +>b : boolean | number + + return typeof x === "string" +>typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x // string +>x : string + + : ((b = x) // x is number | boolean +>((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string +>(b = x) // x is number | boolean && typeof x === "number" && x.toString() : string +>(b = x) // x is number | boolean && typeof x === "number" : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : boolean | number +>x : number | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x.toString()); // x is number +>x.toString() : string +>x.toString : (radix?: number) => string +>x : number +>toString : (radix?: number) => string +} +function foo11(x: number | string | boolean) { +>foo11 : (x: number | string | boolean) => number | string | boolean +>x : number | string | boolean + + // Mixing typeguards + // Assigning value to x deep inside another guard stops narrowing of type too + var b: number | boolean | string; +>b : number | boolean | string + + return typeof x === "string" +>typeof x === "string" ? x // number | boolean | string - changed in the false branch : ((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x // number | boolean | string - changed in the false branch +>x : number | string | boolean + + : ((b = x) // x is number | boolean | string - because the assignment changed it +>((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x : number | string | boolean +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) : number +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" : boolean +>(b = x) : number | string | boolean +>b = x : number | string | boolean +>b : number | boolean | string +>x : number | string | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + && (x = 10) // assignment to x +>(x = 10) : number +>x = 10 : number +>x : number | string | boolean +>10 : number + + && x); // x is number | boolean | string +>x : number | string | boolean +} +function foo12(x: number | string | boolean) { +>foo12 : (x: number | string | boolean) => number +>x : number | string | boolean + + // Mixing typeguards + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + var b: number | boolean | string; +>b : number | boolean | string + + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x.toString().length) // number | boolean | string - changed here : ((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? (x = 10 && x.toString().length) // number | boolean | string - changed here +>(x = 10 && x.toString().length) : number +>x = 10 && x.toString().length : number +>x : number | string | boolean +>10 && x.toString().length : number +>10 : number +>x.toString().length : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +>length : number + + : ((b = x) // x is number | boolean | string - changed in true branch +>((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number +>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x : number +>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" : boolean +>(b = x) : number | string | boolean +>b = x : number | string | boolean +>b : number | boolean | string +>x : number | string | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + && x); // x is number +>x : number +} diff --git a/tests/baselines/reference/typeGuardsInIfStatement.errors.txt b/tests/baselines/reference/typeGuardsInIfStatement.errors.txt deleted file mode 100644 index e675daffd6e..00000000000 --- a/tests/baselines/reference/typeGuardsInIfStatement.errors.txt +++ /dev/null @@ -1,160 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(127,23): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(131,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(139,16): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts (3 errors) ==== - // In the true branch statement of an �if� statement, - // the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, - // provided the true branch statement contains no assignments to the variable or parameter. - // In the false branch statement of an �if� statement, - // the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, - // provided the false branch statement contains no assignments to the variable or parameter - function foo(x: number | string) { - if (typeof x === "string") { - return x.length; // string - } - else { - return x++; // number - } - } - function foo2(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - if (typeof x === "string") { - x = 10; - return x; // string | number - } - else { - return x; // string | number - } - } - function foo3(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - if (typeof x === "string") { - x = "Hello"; // even though assigned using same type as narrowed expression - return x; // string | number - } - else { - return x; // string | number - } - } - function foo4(x: number | string) { - // false branch updates the variable - so here it is not number - if (typeof x === "string") { - return x; // string | number - } - else { - x = 10; // even though assigned number - this should result in x to be string | number - return x; // string | number - } - } - function foo5(x: number | string) { - // false branch updates the variable - so here it is not number - if (typeof x === "string") { - return x; // string | number - } - else { - x = "hello"; - return x; // string | number - } - } - function foo6(x: number | string) { - // Modify in both branches - if (typeof x === "string") { - x = 10; - return x; // string | number - } - else { - x = "hello"; - return x; // string | number - } - } - function foo7(x: number | string | boolean) { - if (typeof x === "string") { - return x === "hello"; // string - } - else if (typeof x === "boolean") { - return x; // boolean - } - else { - return x == 10; // number - } - } - function foo8(x: number | string | boolean) { - if (typeof x === "string") { - return x === "hello"; // string - } - else { - var b: number | boolean = x; // number | boolean - if (typeof x === "boolean") { - return x; // boolean - } - else { - return x == 10; // number - } - } - } - function foo9(x: number | string) { - var y = 10; - if (typeof x === "string") { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - y = x.length; - return x === "hello"; // string - } - else { - return x == 10; // number - } - } - function foo10(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - if (typeof x === "string") { - return x === "hello"; // string - } - else { - var y: boolean | string; - var b = x; // number | boolean - return typeof x === "number" - ? x === 10 // number - : x; // x should be boolean - } - } - function foo11(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - // Assigning value to x deep inside another guard stops narrowing of type too - if (typeof x === "string") { - return x; // string | number | boolean - x changed in else branch - } - else { - var y: number| boolean | string; - var b = x; // number | boolean | string - because below we are changing value of x in if statement - return typeof x === "number" - ? ( - // change value of x - x = 10 && x.toString() // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - ) - : ( - // do not change value - y = x && x.toString() // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - ); - } - } - function foo12(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - if (typeof x === "string") { - return x.toString(); // string | number | boolean - x changed in else branch - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - else { - x = 10; - var b = x; // number | boolean | string - return typeof x === "number" - ? x.toString() // number - : x.toString(); // boolean | string - } - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInIfStatement.symbols b/tests/baselines/reference/typeGuardsInIfStatement.symbols new file mode 100644 index 00000000000..d940e10e066 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInIfStatement.symbols @@ -0,0 +1,304 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts === +// In the true branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, +// provided the true branch statement contains no assignments to the variable or parameter. +// In the false branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, +// provided the false branch statement contains no assignments to the variable or parameter +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInIfStatement.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + + return x.length; // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + } + else { + return x++; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + } +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInIfStatement.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + } + else { + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + } +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInIfStatement.ts, 23, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + x = "Hello"; // even though assigned using same type as narrowed expression +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + } + else { + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + } +} +function foo4(x: number | string) { +>foo4 : Symbol(foo4, Decl(typeGuardsInIfStatement.ts, 33, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + } + else { + x = 10; // even though assigned number - this should result in x to be string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + } +} +function foo5(x: number | string) { +>foo5 : Symbol(foo5, Decl(typeGuardsInIfStatement.ts, 43, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + } + else { + x = "hello"; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + } +} +function foo6(x: number | string) { +>foo6 : Symbol(foo6, Decl(typeGuardsInIfStatement.ts, 53, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + // Modify in both branches + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + } + else { + x = "hello"; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + } +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInIfStatement.ts, 64, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } + else if (typeof x === "boolean") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + return x; // boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } +} +function foo8(x: number | string | boolean) { +>foo8 : Symbol(foo8, Decl(typeGuardsInIfStatement.ts, 75, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + else { + var b: number | boolean = x; // number | boolean +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 81, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + if (typeof x === "boolean") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + return x; // boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + } +} +function foo9(x: number | string) { +>foo9 : Symbol(foo9, Decl(typeGuardsInIfStatement.ts, 89, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + + var y = 10; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + y = x.length; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + } +} +function foo10(x: number | string | boolean) { +>foo10 : Symbol(foo10, Decl(typeGuardsInIfStatement.ts, 100, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + } + else { + var y: boolean | string; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 107, 11)) + + var b = x; // number | boolean +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 108, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + ? x === 10 // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + : x; // x should be boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + } +} +function foo11(x: number | string | boolean) { +>foo11 : Symbol(foo11, Decl(typeGuardsInIfStatement.ts, 113, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x deep inside another guard stops narrowing of type too + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + return x; // string | number | boolean - x changed in else branch +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + } + else { + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11)) + + var b = x; // number | boolean | string - because below we are changing value of x in if statement +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 122, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + ? ( + // change value of x + x = 10 && x.toString() // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + ) + : ( + // do not change value + y = x && x.toString() // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + ); + } +} +function foo12(x: number | string | boolean) { +>foo12 : Symbol(foo12, Decl(typeGuardsInIfStatement.ts, 133, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + return x.toString(); // string | number | boolean - x changed in else branch +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + } + else { + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + var b = x; // number | boolean | string +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 142, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + ? x.toString() // number +>x.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) + + : x.toString(); // boolean | string +>x.toString : Symbol(toString, Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + } +} diff --git a/tests/baselines/reference/typeGuardsInIfStatement.types b/tests/baselines/reference/typeGuardsInIfStatement.types new file mode 100644 index 00000000000..e049d318a02 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInIfStatement.types @@ -0,0 +1,405 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts === +// In the true branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, +// provided the true branch statement contains no assignments to the variable or parameter. +// In the false branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, +// provided the false branch statement contains no assignments to the variable or parameter +function foo(x: number | string) { +>foo : (x: number | string) => number +>x : number | string + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x.length; // string +>x.length : number +>x : string +>length : number + } + else { + return x++; // number +>x++ : number +>x : number + } +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = 10; +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } + else { + return x; // string | number +>x : number | string + } +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = "Hello"; // even though assigned using same type as narrowed expression +>x = "Hello" : string +>x : number | string +>"Hello" : string + + return x; // string | number +>x : number | string + } + else { + return x; // string | number +>x : number | string + } +} +function foo4(x: number | string) { +>foo4 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x; // string | number +>x : number | string + } + else { + x = 10; // even though assigned number - this should result in x to be string | number +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } +} +function foo5(x: number | string) { +>foo5 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x; // string | number +>x : number | string + } + else { + x = "hello"; +>x = "hello" : string +>x : number | string +>"hello" : string + + return x; // string | number +>x : number | string + } +} +function foo6(x: number | string) { +>foo6 : (x: number | string) => number | string +>x : number | string + + // Modify in both branches + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = 10; +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } + else { + x = "hello"; +>x = "hello" : string +>x : number | string +>"hello" : string + + return x; // string | number +>x : number | string + } +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + return x; // boolean +>x : boolean + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } +} +function foo8(x: number | string | boolean) { +>foo8 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + var b: number | boolean = x; // number | boolean +>b : number | boolean +>x : number | boolean + + if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + return x; // boolean +>x : boolean + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } + } +} +function foo9(x: number | string) { +>foo9 : (x: number | string) => boolean +>x : number | string + + var y = 10; +>y : number +>10 : number + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + y = x.length; +>y = x.length : number +>y : number +>x.length : number +>x : string +>length : number + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } +} +function foo10(x: number | string | boolean) { +>foo10 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + var y: boolean | string; +>y : boolean | string + + var b = x; // number | boolean +>b : number | boolean +>x : number | boolean + + return typeof x === "number" +>typeof x === "number" ? x === 10 // number : x : boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x === 10 // number +>x === 10 : boolean +>x : number +>10 : number + + : x; // x should be boolean +>x : boolean + } +} +function foo11(x: number | string | boolean) { +>foo11 : (x: number | string | boolean) => number | string | boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x deep inside another guard stops narrowing of type too + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x; // string | number | boolean - x changed in else branch +>x : number | string | boolean + } + else { + var y: number| boolean | string; +>y : number | boolean | string + + var b = x; // number | boolean | string - because below we are changing value of x in if statement +>b : number | string | boolean +>x : number | string | boolean + + return typeof x === "number" +>typeof x === "number" ? ( // change value of x x = 10 && x.toString() // number | boolean | string ) : ( // do not change value y = x && x.toString() // number | boolean | string ) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + ? ( +>( // change value of x x = 10 && x.toString() // number | boolean | string ) : string + + // change value of x + x = 10 && x.toString() // number | boolean | string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + ) + : ( +>( // do not change value y = x && x.toString() // number | boolean | string ) : string + + // do not change value + y = x && x.toString() // number | boolean | string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + ); + } +} +function foo12(x: number | string | boolean) { +>foo12 : (x: number | string | boolean) => string +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x.toString(); // string | number | boolean - x changed in else branch +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + } + else { + x = 10; +>x = 10 : number +>x : number | string | boolean +>10 : number + + var b = x; // number | boolean | string +>b : number | string | boolean +>x : number | string | boolean + + return typeof x === "number" +>typeof x === "number" ? x.toString() // number : x.toString() : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + ? x.toString() // number +>x.toString() : string +>x.toString : (radix?: number) => string +>x : number +>toString : (radix?: number) => string + + : x.toString(); // boolean | string +>x.toString() : string +>x.toString : () => string +>x : string | boolean +>toString : () => string + } +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt deleted file mode 100644 index f44e433a2c8..00000000000 --- a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt +++ /dev/null @@ -1,64 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts(43,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts(45,21): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts (2 errors) ==== - // In the right operand of a && operation, - // the type of a variable or parameter is narrowed by any type guard in the left operand when true, - // provided the right operand contains no assignments to the variable or parameter. - function foo(x: number | string) { - return typeof x === "string" && x.length === 10; // string - } - function foo2(x: number | string) { - // modify x in right hand operand - return typeof x === "string" && ((x = 10) && x); // string | number - } - function foo3(x: number | string) { - // modify x in right hand operand with string type itself - return typeof x === "string" && ((x = "hello") && x); // string | number - } - function foo4(x: number | string | boolean) { - return typeof x !== "string" // string | number | boolean - && typeof x !== "number" // number | boolean - && x; // boolean - } - function foo5(x: number | string | boolean) { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - var b: number | boolean; - return typeof x !== "string" // string | number | boolean - && ((b = x) && (typeof x !== "number" // number | boolean - && x)); // boolean - } - function foo6(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - return typeof x !== "string" // string | number | boolean - && (typeof x !== "number" // number | boolean - ? x // boolean - : x === 10) // number - } - function foo7(x: number | string | boolean) { - var y: number| boolean | string; - var z: number| boolean | string; - // Mixing typeguard narrowing - // Assigning value to x deep inside another guard stops narrowing of type too - return typeof x !== "string" - && ((z = x) // string | number | boolean - x changed deeper in conditional expression - && (typeof x === "number" - // change value of x - ? (x = 10 && x.toString()) // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - // do not change value - : (y = x && x.toString()))); // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - function foo8(x: number | string) { - // Mixing typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - return typeof x !== "string" - && (x = 10) // change x - number| string - && (typeof x === "number" - ? x // number - : x.length); // string - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols new file mode 100644 index 00000000000..59f51d21e71 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts === +// In the right operand of a && operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when true, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) + + return typeof x === "string" && x.length === 10; // string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) + + // modify x in right hand operand + return typeof x === "string" && ((x = 10) && x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) + + // modify x in right hand operand with string type itself + return typeof x === "string" && ((x = "hello") && x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +} +function foo4(x: number | string | boolean) { +>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + && typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + && x; // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) +} +function foo5(x: number | string | boolean) { +>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7)) + + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + && ((b = x) && (typeof x !== "number" // number | boolean +>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + && x)); // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) +} +function foo6(x: number | string | boolean) { +>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + && (typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + : x === 10) // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7)) + + var z: number| boolean | string; +>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7)) + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x !== "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + && ((z = x) // string | number | boolean - x changed deeper in conditional expression +>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + && (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +} +function foo8(x: number | string) { +>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 45, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x !== "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + && (x = 10) // change x - number| string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + && (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + ? x // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + : x.length); // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types new file mode 100644 index 00000000000..b69c80ff55a --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types @@ -0,0 +1,234 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts === +// In the right operand of a && operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when true, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : (x: number | string) => boolean +>x : number | string + + return typeof x === "string" && x.length === 10; // string +>typeof x === "string" && x.length === 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>x.length === 10 : boolean +>x.length : number +>x : string +>length : number +>10 : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // modify x in right hand operand + return typeof x === "string" && ((x = 10) && x); // string | number +>typeof x === "string" && ((x = 10) && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = 10) && x) : number | string +>(x = 10) && x : number | string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // modify x in right hand operand with string type itself + return typeof x === "string" && ((x = "hello") && x); // string | number +>typeof x === "string" && ((x = "hello") && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = "hello") && x) : number | string +>(x = "hello") && x : number | string +>(x = "hello") : string +>x = "hello" : string +>x : number | string +>"hello" : string +>x : number | string +} +function foo4(x: number | string | boolean) { +>foo4 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && typeof x !== "number" // number | boolean && x : boolean +>typeof x !== "string" // string | number | boolean && typeof x !== "number" : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && typeof x !== "number" // number | boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x; // boolean +>x : boolean +} +function foo5(x: number | string | boolean) { +>foo5 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : number | boolean + + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && ((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && ((b = x) && (typeof x !== "number" // number | boolean +>((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean +>(b = x) && (typeof x !== "number" // number | boolean && x) : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean +>(typeof x !== "number" // number | boolean && x) : boolean +>typeof x !== "number" // number | boolean && x : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x)); // boolean +>x : boolean +} +function foo6(x: number | string | boolean) { +>foo6 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && (typeof x !== "number" // number | boolean +>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x // boolean +>x : boolean + + : x === 10) // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => string +>x : number | string | boolean + + var y: number| boolean | string; +>y : number | boolean | string + + var z: number| boolean | string; +>z : number | boolean | string + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x !== "string" +>typeof x !== "string" && ((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && ((z = x) // string | number | boolean - x changed deeper in conditional expression +>((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string +>(z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>(z = x) : number | string | boolean +>z = x : number | string | boolean +>z : number | boolean | string +>x : number | string | boolean + + && (typeof x === "number" +>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>(x = 10 && x.toString()) : string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>(y = x && x.toString()) : string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +} +function foo8(x: number | string) { +>foo8 : (x: number | string) => number +>x : number | string + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x !== "string" +>typeof x !== "string" && (x = 10) // change x - number| string && (typeof x === "number" ? x // number : x.length) : number +>typeof x !== "string" && (x = 10) : number +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + && (x = 10) // change x - number| string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number + + && (typeof x === "number" +>(typeof x === "number" ? x // number : x.length) : number +>typeof x === "number" ? x // number : x.length : number +>typeof x === "number" : boolean +>typeof x : string +>x : number | string +>"number" : string + + ? x // number +>x : number + + : x.length); // string +>x.length : number +>x : string +>length : number +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt deleted file mode 100644 index f34d035fa40..00000000000 --- a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt +++ /dev/null @@ -1,64 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts(43,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts(45,21): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts (2 errors) ==== - // In the right operand of a || operation, - // the type of a variable or parameter is narrowed by any type guard in the left operand when false, - // provided the right operand contains no assignments to the variable or parameter. - function foo(x: number | string) { - return typeof x !== "string" || x.length === 10; // string - } - function foo2(x: number | string) { - // modify x in right hand operand - return typeof x !== "string" || ((x = 10) || x); // string | number - } - function foo3(x: number | string) { - // modify x in right hand operand with string type itself - return typeof x !== "string" || ((x = "hello") || x); // string | number - } - function foo4(x: number | string | boolean) { - return typeof x === "string" // string | number | boolean - || typeof x === "number" // number | boolean - || x; // boolean - } - function foo5(x: number | string | boolean) { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - var b: number | boolean; - return typeof x === "string" // string | number | boolean - || ((b = x) || (typeof x === "number" // number | boolean - || x)); // boolean - } - function foo6(x: number | string | boolean) { - // Mixing typeguard - return typeof x === "string" // string | number | boolean - || (typeof x !== "number" // number | boolean - ? x // boolean - : x === 10) // number - } - function foo7(x: number | string | boolean) { - var y: number| boolean | string; - var z: number| boolean | string; - // Mixing typeguard narrowing - // Assigning value to x deep inside another guard stops narrowing of type too - return typeof x === "string" - || ((z = x) // string | number | boolean - x changed deeper in conditional expression - || (typeof x === "number" - // change value of x - ? (x = 10 && x.toString()) // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - // do not change value - : (y = x && x.toString()))); // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - function foo8(x: number | string) { - // Mixing typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - return typeof x === "string" - || (x = 10) // change x - number| string - || (typeof x === "number" - ? x // number - : x.length); // string - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols new file mode 100644 index 00000000000..d33f0b6877b --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts === +// In the right operand of a || operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when false, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) + + return typeof x !== "string" || x.length === 10; // string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 5, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) + + // modify x in right hand operand + return typeof x !== "string" || ((x = 10) || x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 9, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) + + // modify x in right hand operand with string type itself + return typeof x !== "string" || ((x = "hello") || x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +} +function foo4(x: number | string | boolean) { +>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + || typeof x === "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + || x; // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) +} +function foo5(x: number | string | boolean) { +>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 18, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 21, 7)) + + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + || ((b = x) || (typeof x === "number" // number | boolean +>b : Symbol(b, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 21, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + || x)); // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) +} +function foo6(x: number | string | boolean) { +>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 25, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + // Mixing typeguard + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + || (typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + : x === 10) // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 32, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 34, 7)) + + var z: number| boolean | string; +>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7)) + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + || ((z = x) // string | number | boolean - x changed deeper in conditional expression +>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + || (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 34, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +} +function foo8(x: number | string) { +>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 45, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + || (x = 10) // change x - number| string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + || (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + ? x // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + : x.length); // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types new file mode 100644 index 00000000000..b2f5401e843 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types @@ -0,0 +1,234 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts === +// In the right operand of a || operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when false, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : (x: number | string) => boolean +>x : number | string + + return typeof x !== "string" || x.length === 10; // string +>typeof x !== "string" || x.length === 10 : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>x.length === 10 : boolean +>x.length : number +>x : string +>length : number +>10 : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => boolean | number | string +>x : number | string + + // modify x in right hand operand + return typeof x !== "string" || ((x = 10) || x); // string | number +>typeof x !== "string" || ((x = 10) || x) : boolean | number | string +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = 10) || x) : number | string +>(x = 10) || x : number | string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => boolean | string | number +>x : number | string + + // modify x in right hand operand with string type itself + return typeof x !== "string" || ((x = "hello") || x); // string | number +>typeof x !== "string" || ((x = "hello") || x) : boolean | string | number +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = "hello") || x) : string | number +>(x = "hello") || x : string | number +>(x = "hello") : string +>x = "hello" : string +>x : number | string +>"hello" : string +>x : number | string +} +function foo4(x: number | string | boolean) { +>foo4 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || typeof x === "number" // number | boolean || x : boolean +>typeof x === "string" // string | number | boolean || typeof x === "number" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || typeof x === "number" // number | boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + || x; // boolean +>x : boolean +} +function foo5(x: number | string | boolean) { +>foo5 : (x: number | string | boolean) => boolean | number +>x : number | string | boolean + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : number | boolean + + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || ((b = x) || (typeof x === "number" // number | boolean || x)) : boolean | number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || ((b = x) || (typeof x === "number" // number | boolean +>((b = x) || (typeof x === "number" // number | boolean || x)) : number | boolean +>(b = x) || (typeof x === "number" // number | boolean || x) : number | boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean +>(typeof x === "number" // number | boolean || x) : boolean +>typeof x === "number" // number | boolean || x : boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + || x)); // boolean +>x : boolean +} +function foo6(x: number | string | boolean) { +>foo6 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || (typeof x !== "number" // number | boolean +>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x // boolean +>x : boolean + + : x === 10) // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean | number | string +>x : number | string | boolean + + var y: number| boolean | string; +>y : number | boolean | string + + var z: number| boolean | string; +>z : number | boolean | string + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x === "string" +>typeof x === "string" || ((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : boolean | number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || ((z = x) // string | number | boolean - x changed deeper in conditional expression +>((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : number | string | boolean +>(z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : number | string | boolean +>(z = x) : number | string | boolean +>z = x : number | string | boolean +>z : number | boolean | string +>x : number | string | boolean + + || (typeof x === "number" +>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>(x = 10 && x.toString()) : string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>(y = x && x.toString()) : string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +} +function foo8(x: number | string) { +>foo8 : (x: number | string) => boolean | number +>x : number | string + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x === "string" +>typeof x === "string" || (x = 10) // change x - number| string || (typeof x === "number" ? x // number : x.length) : boolean | number +>typeof x === "string" || (x = 10) : boolean | number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + || (x = 10) // change x - number| string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number + + || (typeof x === "number" +>(typeof x === "number" ? x // number : x.length) : number +>typeof x === "number" ? x // number : x.length : number +>typeof x === "number" : boolean +>typeof x : string +>x : number | string +>"number" : string + + ? x // number +>x : number + + : x.length); // string +>x.length : number +>x : string +>length : number +} diff --git a/tests/baselines/reference/unionTypeCallSignatures.errors.txt b/tests/baselines/reference/unionTypeCallSignatures.errors.txt index c25a2bf9f84..ebe38a589ee 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeCallSignatures.errors.txt @@ -12,29 +12,25 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(30,1): error TS23 tests/cases/conformance/types/union/unionTypeCallSignatures.ts(31,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(36,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(41,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(46,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(55,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(60,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(66,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (34 errors) ==== +==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (30 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -80,7 +76,7 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 ~~~~~~~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; + var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. @@ -91,7 +87,7 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; + var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -104,30 +100,26 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 var unionWithOptionalParameter2: { (a: string, b?: number): string; } | { (a: string, b: number): number }; strOrNum = unionWithOptionalParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = unionWithOptionalParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; - strOrNum = unionWithOptionalParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter1: { (a: string, ...b: number[]): string; } | { (a: string, ...b: number[]): number }; strOrNum = unionWithRestParameter1('hello'); @@ -143,33 +135,31 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 var unionWithRestParameter2: { (a: string, ...b: number[]): string; } | { (a: string, b: number): number }; strOrNum = unionWithRestParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = unionWithRestParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; - strOrNum = unionWithRestParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. \ No newline at end of file +!!! error TS2346: Supplied parameters do not match any signature of call target. + + \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeCallSignatures.js b/tests/baselines/reference/unionTypeCallSignatures.js index a4000038ce6..fc3dfc8ebbc 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.js +++ b/tests/baselines/reference/unionTypeCallSignatures.js @@ -26,12 +26,12 @@ unionOfDifferentNumberOfSignatures(); // error - no call signatures unionOfDifferentNumberOfSignatures(10); // error - no call signatures unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature unionWithDifferentParameterCount("hello");// no call signature unionWithDifferentParameterCount("hello", 10);// no call signature - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -44,7 +44,7 @@ strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signa strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -64,11 +64,13 @@ strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature -strOrNum = unionWithRestParameter3(); // error no call signature +strOrNum = unionWithRestParameter3(); // error no call signature + + //// [unionTypeCallSignatures.js] var numOrDate; @@ -108,7 +110,7 @@ strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -125,7 +127,7 @@ strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature diff --git a/tests/baselines/reference/unionTypeCallSignatures2.js b/tests/baselines/reference/unionTypeCallSignatures2.js new file mode 100644 index 00000000000..7ec5180972a --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.js @@ -0,0 +1,51 @@ +//// [unionTypeCallSignatures2.ts] +interface A { + (x: number): number; + (x: string, y?: string): boolean; + (x: Date): void; + (x: T[]): T[]; +} + +interface B { + (x: number): number; + (x: string): string; + (x: Date): void; + (x: T[]): T[]; +} + +interface C { + (x: string, ...y: string[]): number; + (x: number, s?: string): number; + (x: T[]): T[]; +} + +var f1: A | B | C; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] + +var f2: C | B | A; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] + +var f3: B | A | C; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] + + + +//// [unionTypeCallSignatures2.js] +var f1; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] +var f2; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] +var f3; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] diff --git a/tests/baselines/reference/unionTypeCallSignatures2.symbols b/tests/baselines/reference/unionTypeCallSignatures2.symbols new file mode 100644 index 00000000000..35ba9464df0 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.symbols @@ -0,0 +1,115 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures2.ts === +interface A { +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) + + (x: number): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 1, 5)) + + (x: string, y?: string): boolean; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 2, 5)) +>y : Symbol(y, Decl(unionTypeCallSignatures2.ts, 2, 15)) + + (x: Date): void; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 3, 5)) +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 4, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +} + +interface B { +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) + + (x: number): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 8, 5)) + + (x: string): string; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 9, 5)) + + (x: Date): void; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 10, 5)) +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 11, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +} + +interface C { +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + + (x: string, ...y: string[]): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 15, 5)) +>y : Symbol(y, Decl(unionTypeCallSignatures2.ts, 15, 15)) + + (x: number, s?: string): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 16, 5)) +>s : Symbol(s, Decl(unionTypeCallSignatures2.ts, 16, 15)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 17, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +} + +var f1: A | B | C; +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + +var n1 = f1(42); // number +>n1 : Symbol(n1, Decl(unionTypeCallSignatures2.ts, 21, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var s1 = f1("abc"); // boolean | string | number +>s1 : Symbol(s1, Decl(unionTypeCallSignatures2.ts, 22, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var a1 = f1([true, false]); // boolean[] +>a1 : Symbol(a1, Decl(unionTypeCallSignatures2.ts, 23, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var f2: C | B | A; +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) + +var n2 = f2(42); // number +>n2 : Symbol(n2, Decl(unionTypeCallSignatures2.ts, 26, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var s2 = f2("abc"); // number | string | boolean +>s2 : Symbol(s2, Decl(unionTypeCallSignatures2.ts, 27, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var a2 = f2([true, false]); // boolean[] +>a2 : Symbol(a2, Decl(unionTypeCallSignatures2.ts, 28, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var f3: B | A | C; +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + +var n3 = f3(42); // number +>n3 : Symbol(n3, Decl(unionTypeCallSignatures2.ts, 31, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) + +var s3 = f3("abc"); // string | boolean | number +>s3 : Symbol(s3, Decl(unionTypeCallSignatures2.ts, 32, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) + +var a3 = f3([true, false]); // boolean[] +>a3 : Symbol(a3, Decl(unionTypeCallSignatures2.ts, 33, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) + + diff --git a/tests/baselines/reference/unionTypeCallSignatures2.types b/tests/baselines/reference/unionTypeCallSignatures2.types new file mode 100644 index 00000000000..64295c1b452 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.types @@ -0,0 +1,139 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures2.ts === +interface A { +>A : A + + (x: number): number; +>x : number + + (x: string, y?: string): boolean; +>x : string +>y : string + + (x: Date): void; +>x : Date +>Date : Date + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +interface B { +>B : B + + (x: number): number; +>x : number + + (x: string): string; +>x : string + + (x: Date): void; +>x : Date +>Date : Date + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +interface C { +>C : C + + (x: string, ...y: string[]): number; +>x : string +>y : string[] + + (x: number, s?: string): number; +>x : number +>s : string + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +var f1: A | B | C; +>f1 : A | B | C +>A : A +>B : B +>C : C + +var n1 = f1(42); // number +>n1 : number +>f1(42) : number +>f1 : A | B | C +>42 : number + +var s1 = f1("abc"); // boolean | string | number +>s1 : boolean | string | number +>f1("abc") : boolean | string | number +>f1 : A | B | C +>"abc" : string + +var a1 = f1([true, false]); // boolean[] +>a1 : boolean[] +>f1([true, false]) : boolean[] +>f1 : A | B | C +>[true, false] : boolean[] +>true : boolean +>false : boolean + +var f2: C | B | A; +>f2 : C | B | A +>C : C +>B : B +>A : A + +var n2 = f2(42); // number +>n2 : number +>f2(42) : number +>f2 : C | B | A +>42 : number + +var s2 = f2("abc"); // number | string | boolean +>s2 : number | string | boolean +>f2("abc") : number | string | boolean +>f2 : C | B | A +>"abc" : string + +var a2 = f2([true, false]); // boolean[] +>a2 : boolean[] +>f2([true, false]) : boolean[] +>f2 : C | B | A +>[true, false] : boolean[] +>true : boolean +>false : boolean + +var f3: B | A | C; +>f3 : B | A | C +>B : B +>A : A +>C : C + +var n3 = f3(42); // number +>n3 : number +>f3(42) : number +>f3 : B | A | C +>42 : number + +var s3 = f3("abc"); // string | boolean | number +>s3 : string | boolean | number +>f3("abc") : string | boolean | number +>f3 : B | A | C +>"abc" : string + +var a3 = f3([true, false]); // boolean[] +>a3 : boolean[] +>f3([true, false]) : boolean[] +>f3 : B | A | C +>[true, false] : boolean[] +>true : boolean +>false : boolean + + diff --git a/tests/baselines/reference/unionTypeCallSignatures3.js b/tests/baselines/reference/unionTypeCallSignatures3.js new file mode 100644 index 00000000000..2dae152e474 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.js @@ -0,0 +1,39 @@ +//// [unionTypeCallSignatures3.ts] +function f1(s: string) { } +function f2(s?: string) { } +function f3(...s: string[]) { } +function f4(s: string, s2?: string) { } +function f5(s?: string, n?: number) { } +function f6(s?: string, ...n: number[]) { } +function f7(s: string, ...sRest: string[]) { } + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; + +fUnion(""); // All constituents can be called by passing a single string. + + +//// [unionTypeCallSignatures3.js] +function f1(s) { } +function f2(s) { } +function f3() { + var s = []; + for (var _i = 0; _i < arguments.length; _i++) { + s[_i - 0] = arguments[_i]; + } +} +function f4(s, s2) { } +function f5(s, n) { } +function f6(s) { + var n = []; + for (var _i = 1; _i < arguments.length; _i++) { + n[_i - 1] = arguments[_i]; + } +} +function f7(s) { + var sRest = []; + for (var _i = 1; _i < arguments.length; _i++) { + sRest[_i - 1] = arguments[_i]; + } +} +var fUnion; +fUnion(""); // All constituents can be called by passing a single string. diff --git a/tests/baselines/reference/unionTypeCallSignatures3.symbols b/tests/baselines/reference/unionTypeCallSignatures3.symbols new file mode 100644 index 00000000000..45dffe2d821 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.symbols @@ -0,0 +1,46 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures3.ts === +function f1(s: string) { } +>f1 : Symbol(f1, Decl(unionTypeCallSignatures3.ts, 0, 0)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 0, 12)) + +function f2(s?: string) { } +>f2 : Symbol(f2, Decl(unionTypeCallSignatures3.ts, 0, 26)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 1, 12)) + +function f3(...s: string[]) { } +>f3 : Symbol(f3, Decl(unionTypeCallSignatures3.ts, 1, 27)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 2, 12)) + +function f4(s: string, s2?: string) { } +>f4 : Symbol(f4, Decl(unionTypeCallSignatures3.ts, 2, 31)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 3, 12)) +>s2 : Symbol(s2, Decl(unionTypeCallSignatures3.ts, 3, 22)) + +function f5(s?: string, n?: number) { } +>f5 : Symbol(f5, Decl(unionTypeCallSignatures3.ts, 3, 39)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 4, 12)) +>n : Symbol(n, Decl(unionTypeCallSignatures3.ts, 4, 23)) + +function f6(s?: string, ...n: number[]) { } +>f6 : Symbol(f6, Decl(unionTypeCallSignatures3.ts, 4, 39)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 5, 12)) +>n : Symbol(n, Decl(unionTypeCallSignatures3.ts, 5, 23)) + +function f7(s: string, ...sRest: string[]) { } +>f7 : Symbol(f7, Decl(unionTypeCallSignatures3.ts, 5, 43)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 6, 12)) +>sRest : Symbol(sRest, Decl(unionTypeCallSignatures3.ts, 6, 22)) + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; +>fUnion : Symbol(fUnion, Decl(unionTypeCallSignatures3.ts, 8, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures3.ts, 0, 0)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures3.ts, 0, 26)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures3.ts, 1, 27)) +>f4 : Symbol(f4, Decl(unionTypeCallSignatures3.ts, 2, 31)) +>f5 : Symbol(f5, Decl(unionTypeCallSignatures3.ts, 3, 39)) +>f6 : Symbol(f6, Decl(unionTypeCallSignatures3.ts, 4, 39)) +>f7 : Symbol(f7, Decl(unionTypeCallSignatures3.ts, 5, 43)) + +fUnion(""); // All constituents can be called by passing a single string. +>fUnion : Symbol(fUnion, Decl(unionTypeCallSignatures3.ts, 8, 3)) + diff --git a/tests/baselines/reference/unionTypeCallSignatures3.types b/tests/baselines/reference/unionTypeCallSignatures3.types new file mode 100644 index 00000000000..52aae993e4a --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures3.ts === +function f1(s: string) { } +>f1 : (s: string) => void +>s : string + +function f2(s?: string) { } +>f2 : (s?: string) => void +>s : string + +function f3(...s: string[]) { } +>f3 : (...s: string[]) => void +>s : string[] + +function f4(s: string, s2?: string) { } +>f4 : (s: string, s2?: string) => void +>s : string +>s2 : string + +function f5(s?: string, n?: number) { } +>f5 : (s?: string, n?: number) => void +>s : string +>n : number + +function f6(s?: string, ...n: number[]) { } +>f6 : (s?: string, ...n: number[]) => void +>s : string +>n : number[] + +function f7(s: string, ...sRest: string[]) { } +>f7 : (s: string, ...sRest: string[]) => void +>s : string +>sRest : string[] + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; +>fUnion : ((s: string) => void) | ((s?: string) => void) | ((...s: string[]) => void) | ((s: string, s2?: string) => void) | ((s?: string, n?: number) => void) | ((s?: string, ...n: number[]) => void) | ((s: string, ...sRest: string[]) => void) +>f1 : (s: string) => void +>f2 : (s?: string) => void +>f3 : (...s: string[]) => void +>f4 : (s: string, s2?: string) => void +>f5 : (s?: string, n?: number) => void +>f6 : (s?: string, ...n: number[]) => void +>f7 : (s: string, ...sRest: string[]) => void + +fUnion(""); // All constituents can be called by passing a single string. +>fUnion("") : void +>fUnion : ((s: string) => void) | ((s?: string) => void) | ((...s: string[]) => void) | ((s: string, s2?: string) => void) | ((s?: string, n?: number) => void) | ((s?: string, ...n: number[]) => void) | ((s: string, ...sRest: string[]) => void) +>"" : string + diff --git a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt index cbdcc9ed12a..0332aa61110 100644 --- a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt @@ -12,29 +12,25 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(30,1): error tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(31,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(36,53): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(41,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(46,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,53): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(55,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(60,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(66,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (34 errors) ==== +==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (30 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -104,30 +100,26 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithOptionalParameter2: { new (a: string, b?: number): string; } | { new (a: string, b: number): number }; strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = new unionWithOptionalParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter1: { new (a: string, ...b: number[]): string; } | { new (a: string, ...b: number[]): number }; strOrNum = new unionWithRestParameter1('hello'); @@ -143,33 +135,29 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithRestParameter2: { new (a: string, ...b: number[]): string; } | { new (a: string, b: number): number }; strOrNum = new unionWithRestParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = new unionWithRestParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; strOrNum = new unionWithRestParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. \ No newline at end of file +!!! error TS2346: Supplied parameters do not match any signature of call target. \ No newline at end of file diff --git a/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts b/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts new file mode 100644 index 00000000000..4dfab371d62 --- /dev/null +++ b/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts @@ -0,0 +1,15 @@ +function foo(/*c1*/ x: any) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( + /*c4*/ + () => { }); +foo( + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ + () => { }); +foo( + /*c7*/ + /*c8*/() => { }); \ No newline at end of file diff --git a/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts b/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts new file mode 100644 index 00000000000..65350880b5d --- /dev/null +++ b/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts @@ -0,0 +1,10 @@ +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +var a, b: any; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +foo( + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); \ No newline at end of file diff --git a/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts b/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts new file mode 100644 index 00000000000..6ecf7a754bd --- /dev/null +++ b/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts @@ -0,0 +1,13 @@ +var resolve = { + id: /*! @ngInject */ (details: any) => details.id, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ (details: any) => details.id, + id3: + /*! @ngInject */ + (details: any) => details.id, + id4: + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +}; \ No newline at end of file diff --git a/tests/cases/compiler/jsxHash.tsx b/tests/cases/compiler/jsxHash.tsx new file mode 100644 index 00000000000..ddd6c7e928f --- /dev/null +++ b/tests/cases/compiler/jsxHash.tsx @@ -0,0 +1,12 @@ +//@jsx: preserve +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; diff --git a/tests/cases/compiler/paramterDestrcuturingDeclaration.ts b/tests/cases/compiler/paramterDestrcuturingDeclaration.ts new file mode 100644 index 00000000000..d05d6076bf0 --- /dev/null +++ b/tests/cases/compiler/paramterDestrcuturingDeclaration.ts @@ -0,0 +1,6 @@ +// @declaration: true + +interface C { + ({p: name}): any; + new ({p: boolean}): any; +} diff --git a/tests/cases/compiler/systemModule14.ts b/tests/cases/compiler/systemModule14.ts new file mode 100644 index 00000000000..91192cec74a --- /dev/null +++ b/tests/cases/compiler/systemModule14.ts @@ -0,0 +1,12 @@ +// @module: system +// @isolatedModules: true + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} \ No newline at end of file diff --git a/tests/cases/compiler/systemModule15.ts b/tests/cases/compiler/systemModule15.ts new file mode 100644 index 00000000000..2c29f0a5d20 --- /dev/null +++ b/tests/cases/compiler/systemModule15.ts @@ -0,0 +1,34 @@ +// @module: system +// @isolatedModules: true + +// @filename: file1.ts + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +// @filename: file2.ts + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +// @filename: file3.ts + +export var value = "youpi"; +export default value; + +// @filename: file4.ts + +export var value2 = "v"; \ No newline at end of file diff --git a/tests/cases/compiler/systemModule16.ts b/tests/cases/compiler/systemModule16.ts new file mode 100644 index 00000000000..ba64bd32b59 --- /dev/null +++ b/tests/cases/compiler/systemModule16.ts @@ -0,0 +1,13 @@ +// @module: system +// @isolatedModules: true + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1; diff --git a/tests/cases/compiler/typeAliasDeclarationEmit.ts b/tests/cases/compiler/typeAliasDeclarationEmit.ts new file mode 100644 index 00000000000..be7e40453f6 --- /dev/null +++ b/tests/cases/compiler/typeAliasDeclarationEmit.ts @@ -0,0 +1,7 @@ +// @target: ES5 +// @module: AMD +// @declaration: true + +export type callback = () => T; + +export type CallbackArray = () => T; \ No newline at end of file diff --git a/tests/cases/compiler/typeAliasDeclarationEmit2.ts b/tests/cases/compiler/typeAliasDeclarationEmit2.ts new file mode 100644 index 00000000000..33aecd7d5c9 --- /dev/null +++ b/tests/cases/compiler/typeAliasDeclarationEmit2.ts @@ -0,0 +1,5 @@ +// @target: ES5 +// @module: AMD +// @declaration: true + +export type A = { value: a }; \ No newline at end of file diff --git a/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts b/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts new file mode 100644 index 00000000000..4a6f6cc3d61 --- /dev/null +++ b/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts @@ -0,0 +1,8 @@ +abstract class A { } + +// var AA: typeof A; +var AAA: new() => A; + +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; \ No newline at end of file diff --git a/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts b/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts new file mode 100644 index 00000000000..d4d25743333 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts @@ -0,0 +1,10 @@ +// @module: commonjs +// @Filename: foo1.ts +class x{} + +export = x; + +// @Filename: foo2.ts +import foo1 = require('./foo1'); +var x = foo1; +class y extends x {} diff --git a/tests/cases/conformance/decorators/decoratorMetadata.ts b/tests/cases/conformance/decorators/decoratorMetadata.ts new file mode 100644 index 00000000000..3f622909309 --- /dev/null +++ b/tests/cases/conformance/decorators/decoratorMetadata.ts @@ -0,0 +1,17 @@ +// @experimentalDecorators: true +// @emitDecoratorMetadata: true +// @target: es5 +// @module: commonjs +// @filename: service.ts +export default class Service { +} +// @filename: component.ts +import Service from "./service"; + +declare var decorator: any; + +@decorator +class MyComponent { + constructor(public Service: Service) { + } +} \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/reexportClassDefinition.ts b/tests/cases/conformance/externalModules/reexportClassDefinition.ts new file mode 100644 index 00000000000..31d90fd7fd2 --- /dev/null +++ b/tests/cases/conformance/externalModules/reexportClassDefinition.ts @@ -0,0 +1,16 @@ +// @module: commonjs +// @Filename: foo1.ts +class x{} +export = x; + +// @Filename: foo2.ts +import foo1 = require('./foo1'); + +export = { + x: foo1 +} + +// @Filename: foo3.ts +import foo2 = require('./foo2') +class x extends foo2.x {} + diff --git a/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts b/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts new file mode 100644 index 00000000000..5e5c2e85485 --- /dev/null +++ b/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts @@ -0,0 +1,6 @@ +var regex1 = / asdf /; +var regex2 = /**// asdf /; +var regex3 = /**///**/ asdf / // should be a comment line +1; +var regex4 = /**// /**/asdf /; +var regex5 = /**// asdf/**/ /; \ No newline at end of file diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts index 1261de3299e..ca599329743 100644 --- a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts @@ -25,12 +25,12 @@ unionOfDifferentNumberOfSignatures(); // error - no call signatures unionOfDifferentNumberOfSignatures(10); // error - no call signatures unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature unionWithDifferentParameterCount("hello");// no call signature unionWithDifferentParameterCount("hello", 10);// no call signature - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -43,7 +43,7 @@ strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signa strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -63,8 +63,9 @@ strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature -strOrNum = unionWithRestParameter3(); // error no call signature \ No newline at end of file +strOrNum = unionWithRestParameter3(); // error no call signature + diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts new file mode 100644 index 00000000000..2fa5190cc35 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts @@ -0,0 +1,35 @@ +interface A { + (x: number): number; + (x: string, y?: string): boolean; + (x: Date): void; + (x: T[]): T[]; +} + +interface B { + (x: number): number; + (x: string): string; + (x: Date): void; + (x: T[]): T[]; +} + +interface C { + (x: string, ...y: string[]): number; + (x: number, s?: string): number; + (x: T[]): T[]; +} + +var f1: A | B | C; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] + +var f2: C | B | A; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] + +var f3: B | A | C; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] + diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts new file mode 100644 index 00000000000..8549315a319 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts @@ -0,0 +1,11 @@ +function f1(s: string) { } +function f2(s?: string) { } +function f3(...s: string[]) { } +function f4(s: string, s2?: string) { } +function f5(s?: string, n?: number) { } +function f6(s?: string, ...n: number[]) { } +function f7(s: string, ...sRest: string[]) { } + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; + +fUnion(""); // All constituents can be called by passing a single string. diff --git a/tests/cases/fourslash/completionEntryForUnionProperty2.ts b/tests/cases/fourslash/completionEntryForUnionProperty2.ts index 0b2d50fc130..aa5bc40b5e3 100644 --- a/tests/cases/fourslash/completionEntryForUnionProperty2.ts +++ b/tests/cases/fourslash/completionEntryForUnionProperty2.ts @@ -15,6 +15,6 @@ ////x.commonProperty./**/ goTo.marker(); -verify.memberListContains("toString", "(property) toString: ((radix?: number) => string) | (() => string)"); +verify.memberListContains("toString", "(method) toString(): string"); verify.memberListContains("valueOf", "(method) valueOf(): number | string"); verify.memberListCount(2); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateEmptyFile.ts b/tests/cases/fourslash/docCommentTemplateEmptyFile.ts new file mode 100644 index 00000000000..76e888ea2cb --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateEmptyFile.ts @@ -0,0 +1,7 @@ +/// + +// @Filename: emptyFile.ts +/////*0*/ + +goTo.marker("0"); +verify.noDocCommentTemplate(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts new file mode 100644 index 00000000000..f4410d5d454 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: functionWithParams.ts +/////*0*/ +//// /*1*/ +//// function foo(x: number, y: string): boolean {} + +const noIndentScaffolding = "/**\r\n * \r\n * @param x\r\n * @param y\r\n */"; +const oneIndentScaffolding = "/**\r\n * \r\n * @param x\r\n * @param y\r\n */"; +const noIndentOffset = 8; +const oneIndentOffset = noIndentOffset + 4; + +goTo.marker("0"); +verify.DocCommentTemplate(noIndentScaffolding, noIndentOffset); + +goTo.marker("1"); +verify.DocCommentTemplate(oneIndentScaffolding, oneIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts b/tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts new file mode 100644 index 00000000000..131f722a9af --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts @@ -0,0 +1,7 @@ +/// + +// @Filename: justAComment.ts +//// /* /*0*/ */ + +goTo.marker("0"); +verify.noDocCommentTemplate(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts b/tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts new file mode 100644 index 00000000000..52925870a66 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts @@ -0,0 +1,14 @@ +/// + +// @Filename: justAComment.ts +//// // We want to check off-by-one errors in assessing the end of the comment, so we check twice, +//// // first with a trailing space and then without. +//// // /*0*/ +//// // /*1*/ +//// // We also want to check EOF handling at the end of a comment +//// // /*2*/ + +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentTemplate(); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateIndentation.ts b/tests/cases/fourslash/docCommentTemplateIndentation.ts new file mode 100644 index 00000000000..db7e48dab2e --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateIndentation.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: indents.ts +/////*0*/ +//// /*1*/ +//// /*2*/function foo() { } + +const noIndentEmptyScaffolding = "/**\r\n * \r\n */"; +const oneIndentEmptyScaffolding = "/**\r\n * \r\n */"; +const twoIndentEmptyScaffolding = "/**\r\n * \r\n */\r\n "; +const noIndentOffset = 8; +const oneIndentOffset = noIndentOffset + 4; +const twoIndentOffset = oneIndentOffset + 4; + +goTo.marker("0"); +verify.DocCommentTemplate(noIndentEmptyScaffolding, noIndentOffset); + +goTo.marker("1"); +verify.DocCommentTemplate(oneIndentEmptyScaffolding, oneIndentOffset); + +goTo.marker("2"); +verify.DocCommentTemplate(twoIndentEmptyScaffolding, twoIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts b/tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts new file mode 100644 index 00000000000..9c803301526 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts @@ -0,0 +1,9 @@ +/// + +// @Filename: functionDecl.ts +////f/*0*/unction /*1*/foo/*2*/(/*3*/) /*4*/{ /*5*/} + +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentTemplate(); +}); diff --git a/tests/cases/fourslash/docCommentTemplateRegex.ts b/tests/cases/fourslash/docCommentTemplateRegex.ts new file mode 100644 index 00000000000..0bf50f5e85a --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateRegex.ts @@ -0,0 +1,9 @@ +/// + +// @Filename: regex.ts +////var regex = /*0*///*1*/asdf/*2*/ /*3*///*4*/; + +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentTemplate(); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingOptionsChange.ts b/tests/cases/fourslash/formattingOptionsChange.ts index d84e876f06b..cdd8f61a215 100644 --- a/tests/cases/fourslash/formattingOptionsChange.ts +++ b/tests/cases/fourslash/formattingOptionsChange.ts @@ -6,6 +6,7 @@ /////*InsertSpaceAfterKeywordsInControlFlowStatements*/if (true) { } /////*InsertSpaceAfterFunctionKeywordForAnonymousFunctions*/(function () { }) /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis*/(1 ) +/////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ]; [ ]; []; [,] /////*PlaceOpenBraceOnNewLineForFunctions*/class foo { ////} /////*PlaceOpenBraceOnNewLineForControlBlocks*/if (true) { @@ -17,6 +18,7 @@ runTest("InsertSpaceBeforeAndAfterBinaryOperators", "1 + 2 - 3", "1+2-3"); runTest("InsertSpaceAfterKeywordsInControlFlowStatements", "if (true) { }", "if(true) { }"); runTest("InsertSpaceAfterFunctionKeywordForAnonymousFunctions", "(function () { })", "(function() { })"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", " ( 1 )", " (1)"); +runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ];[];[];[ , ]", "[1];[];[];[, ]"); runTest("PlaceOpenBraceOnNewLineForFunctions", "class foo", "class foo {"); runTest("PlaceOpenBraceOnNewLineForControlBlocks", "if ( true )", "if ( true ) {"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 44ce4525754..42cfc1248b0 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -90,6 +90,7 @@ module FourSlashInterface { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string; @@ -286,10 +287,10 @@ module FourSlashInterface { } /** - Compiles the current file and evaluates 'expr' in a context containing - the emitted output, then compares (using ===) the result of that expression - to 'value'. Do not use this function with external modules as it is not supported. - */ + * Compiles the current file and evaluates 'expr' in a context containing + * the emitted output, then compares (using ===) the result of that expression + * to 'value'. Do not use this function with external modules as it is not supported. + */ public eval(expr: string, value: any) { FourSlash.currentTestState.verifyEval(expr, value); } @@ -378,6 +379,14 @@ module FourSlashInterface { FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition); } + public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { + FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); + } + + public noDocCommentTemplate() { + this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); + } + public getScriptLexicalStructureListCount(count: number) { FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count); } diff --git a/tests/cases/fourslash/genericsFormatting.ts b/tests/cases/fourslash/genericsFormatting.ts index 36833cadd10..f5e44522a8e 100644 --- a/tests/cases/fourslash/genericsFormatting.ts +++ b/tests/cases/fourslash/genericsFormatting.ts @@ -5,6 +5,7 @@ //// } ////} /////*typeArguments*/var foo = new Foo < number, Array < number > > ( ); +/////*typeArgumentsWithTypeLiterals*/foo = new Foo < { bar : number }, Array < { baz : string } > > ( ); //// ////interface IFoo { /////*inNewSignature*/new < T > ( a: T); @@ -13,6 +14,13 @@ //// ////foo()(); ////(a + b)(); +//// +////function bar() { +/////*inClassExpression*/ return class < T2 > { +//// } +////} +/////*expressionWithTypeArguments*/class A < T > extends bar < T >( ) < T > { +////} format.document(); @@ -25,9 +33,17 @@ verify.currentLineContentIs(" public method(a: T1, b: Array): Map goTo.marker("typeArguments"); verify.currentLineContentIs("var foo = new Foo>();"); +goTo.marker("typeArgumentsWithTypeLiterals"); +verify.currentLineContentIs("foo = new Foo<{ bar: number }, Array<{ baz: string }>>();"); goTo.marker("inNewSignature"); verify.currentLineContentIs(" new (a: T);"); goTo.marker("inOptionalMethodSignature"); -verify.currentLineContentIs(" op?(a: T, b: M);"); \ No newline at end of file +verify.currentLineContentIs(" op?(a: T, b: M);"); + +goTo.marker("inClassExpression"); +verify.currentLineContentIs(" return class {"); + +goTo.marker("expressionWithTypeArguments"); +verify.currentLineContentIs("class A extends bar() {"); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesIfElse5.ts b/tests/cases/fourslash/getOccurrencesIfElse5.ts index b0519630b7b..7360a803027 100644 --- a/tests/cases/fourslash/getOccurrencesIfElse5.ts +++ b/tests/cases/fourslash/getOccurrencesIfElse5.ts @@ -22,21 +22,21 @@ ////} ////else/*13*/ { } -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 7); -verifyOccurencesAtMarker("2", 2); -verifyOccurencesAtMarker("3", 2); -verifyOccurencesAtMarker("4", 2); -verifyOccurencesAtMarker("5", 2); -verifyOccurencesAtMarker("6", 1); -verifyOccurencesAtMarker("7", 1); -verifyOccurencesAtMarker("8", 7); -verifyOccurencesAtMarker("9", 7); -verifyOccurencesAtMarker("10", 7); -verifyOccurencesAtMarker("11", 7); -verifyOccurencesAtMarker("12", 7); -verifyOccurencesAtMarker("13", 7); +verifyOccurrencesAtMarker("1", 7); +verifyOccurrencesAtMarker("2", 2); +verifyOccurrencesAtMarker("3", 2); +verifyOccurrencesAtMarker("4", 2); +verifyOccurrencesAtMarker("5", 2); +verifyOccurrencesAtMarker("6", 1); +verifyOccurrencesAtMarker("7", 1); +verifyOccurrencesAtMarker("8", 7); +verifyOccurrencesAtMarker("9", 7); +verifyOccurrencesAtMarker("10", 7); +verifyOccurrencesAtMarker("11", 7); +verifyOccurrencesAtMarker("12", 7); +verifyOccurrencesAtMarker("13", 7); diff --git a/tests/cases/fourslash/getOccurrencesReturn4.ts b/tests/cases/fourslash/getOccurrencesReturn4.ts index 4e25162f80f..4066b093f3d 100644 --- a/tests/cases/fourslash/getOccurrencesReturn4.ts +++ b/tests/cases/fourslash/getOccurrencesReturn4.ts @@ -19,15 +19,15 @@ //// return/*7*/ true; ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 4); -verifyOccurencesAtMarker("2", 4); -verifyOccurencesAtMarker("3", 4); -verifyOccurencesAtMarker("4", 4); -verifyOccurencesAtMarker("5", 1); -verifyOccurencesAtMarker("6", 3); -verifyOccurencesAtMarker("7", 3); \ No newline at end of file +verifyOccurrencesAtMarker("1", 4); +verifyOccurrencesAtMarker("2", 4); +verifyOccurrencesAtMarker("3", 4); +verifyOccurrencesAtMarker("4", 4); +verifyOccurrencesAtMarker("5", 1); +verifyOccurrencesAtMarker("6", 3); +verifyOccurrencesAtMarker("7", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts index 162c2e1a94f..3c6d5374ce6 100644 --- a/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts +++ b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts @@ -18,23 +18,23 @@ //// case 16/*14*/: ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 9); -verifyOccurencesAtMarker("2", 9); -verifyOccurencesAtMarker("3", 9); -verifyOccurencesAtMarker("4", 9); -verifyOccurencesAtMarker("5", 9); -verifyOccurencesAtMarker("6", 6); -verifyOccurencesAtMarker("7", 6); -verifyOccurencesAtMarker("8", 6); -verifyOccurencesAtMarker("9", 6); -verifyOccurencesAtMarker("10", 6); -verifyOccurencesAtMarker("11", 9); -verifyOccurencesAtMarker("12", 9); -verifyOccurencesAtMarker("13", 9); -verifyOccurencesAtMarker("14", 0); +verifyOccurrencesAtMarker("1", 9); +verifyOccurrencesAtMarker("2", 9); +verifyOccurrencesAtMarker("3", 9); +verifyOccurrencesAtMarker("4", 9); +verifyOccurrencesAtMarker("5", 9); +verifyOccurrencesAtMarker("6", 6); +verifyOccurrencesAtMarker("7", 6); +verifyOccurrencesAtMarker("8", 6); +verifyOccurrencesAtMarker("9", 6); +verifyOccurrencesAtMarker("10", 6); +verifyOccurrencesAtMarker("11", 9); +verifyOccurrencesAtMarker("12", 9); +verifyOccurrencesAtMarker("13", 9); +verifyOccurrencesAtMarker("14", 0); diff --git a/tests/cases/fourslash/getOccurrencesThis6.ts b/tests/cases/fourslash/getOccurrencesThis6.ts index 6ff779c0b46..e9a5c545f23 100644 --- a/tests/cases/fourslash/getOccurrencesThis6.ts +++ b/tests/cases/fourslash/getOccurrencesThis6.ts @@ -142,14 +142,14 @@ ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 2); -verifyOccurencesAtMarker("2", 6); -verifyOccurencesAtMarker("3", 1); -verifyOccurencesAtMarker("4", 1); -verifyOccurencesAtMarker("5", 1); -verifyOccurencesAtMarker("6", 0); \ No newline at end of file +verifyOccurrencesAtMarker("1", 2); +verifyOccurrencesAtMarker("2", 6); +verifyOccurrencesAtMarker("3", 1); +verifyOccurrencesAtMarker("4", 1); +verifyOccurrencesAtMarker("5", 1); +verifyOccurrencesAtMarker("6", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts index dc6b0540312..3d97bd319ea 100644 --- a/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts +++ b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts @@ -15,16 +15,16 @@ ////} ////finally/*7*/ { ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 3); -verifyOccurencesAtMarker("2", 2); -verifyOccurencesAtMarker("3", 2); -verifyOccurencesAtMarker("4", 2); -verifyOccurencesAtMarker("5", 2); -verifyOccurencesAtMarker("6", 3); -verifyOccurencesAtMarker("7", 3); -verifyOccurencesAtMarker("8", 0); \ No newline at end of file +verifyOccurrencesAtMarker("1", 3); +verifyOccurrencesAtMarker("2", 2); +verifyOccurrencesAtMarker("3", 2); +verifyOccurrencesAtMarker("4", 2); +verifyOccurrencesAtMarker("5", 2); +verifyOccurrencesAtMarker("6", 3); +verifyOccurrencesAtMarker("7", 3); +verifyOccurrencesAtMarker("8", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/typeAssertionsFormatting.ts b/tests/cases/fourslash/typeAssertionsFormatting.ts new file mode 100644 index 00000000000..3f3ab070fec --- /dev/null +++ b/tests/cases/fourslash/typeAssertionsFormatting.ts @@ -0,0 +1,13 @@ +/// + +////( < any > publisher);/*1*/ +//// < any > 3;/*2*/ + + +format.document(); + +goTo.marker("1"); +verify.currentLineContentIs("(publisher);"); + +goTo.marker("2"); +verify.currentLineContentIs("3;"); \ No newline at end of file