mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into reuseAndCache
This commit is contained in:
+7
-1
@@ -43,5 +43,11 @@
|
||||
"build:compiler": "jake local",
|
||||
"build:tests": "jake tests",
|
||||
"clean": "jake clean"
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"buffer": false,
|
||||
"fs": false,
|
||||
"os": false,
|
||||
"path": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+115
-70
@@ -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 = (<UnionType>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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(<BindingPattern>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.
|
||||
|
||||
+187
-124
@@ -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) {
|
||||
// <list of local aliases for imports>
|
||||
@@ -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 (!(<ImportDeclaration>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 (!(<ImportDeclaration>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
|
||||
? (<ImportDeclaration>importNode).importClause.name
|
||||
: (<ImportEqualsDeclaration>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 &&
|
||||
(<ImportDeclaration>importNode).importClause.namedBindings) {
|
||||
|
||||
let namedBindings = (<ImportDeclaration>importNode).importClause.namedBindings;
|
||||
if (namedBindings.kind === SyntaxKind.NamespaceImport) {
|
||||
// emit re-export for namespace
|
||||
// import * as n from 'foo'
|
||||
// export {n}
|
||||
emitExportMemberAssignments((<NamespaceImport>namedBindings).name);
|
||||
if ((<ExportDeclaration>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 = (<ExportDeclaration>entry).exportClause.elements.length; i < len; ++i) {
|
||||
if (i !== 0) {
|
||||
write(",");
|
||||
writeLine();
|
||||
}
|
||||
|
||||
let e = (<ExportDeclaration>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 (<NamedImports>namedBindings).elements) {
|
||||
emitExportMemberAssignments(element.name || element.propertyName);
|
||||
writeLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decreaseIndent();
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
Debug.assert(importVariableName !== "");
|
||||
|
||||
increaseIndent();
|
||||
|
||||
if ((<ExportDeclaration>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 (<ExportDeclaration>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 (!(<ExportDeclaration>statement).moduleSpecifier) {
|
||||
for (let element of (<ExportDeclaration>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<ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration>;
|
||||
|
||||
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<number> = {};
|
||||
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)) {
|
||||
|
||||
+44
-16
@@ -844,6 +844,10 @@ namespace ts {
|
||||
return token = scanner.scanJsxIdentifier();
|
||||
}
|
||||
|
||||
function scanJsxText(): SyntaxKind {
|
||||
return token = scanner.scanJsxToken();
|
||||
}
|
||||
|
||||
function speculationHelper<T>(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 = <JsxElement>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 = <JsxOpeningElement>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 = <JsxSelfClosingElement>createNode(SyntaxKind.JsxSelfClosingElement, fullStart);
|
||||
}
|
||||
|
||||
@@ -3406,14 +3422,20 @@ namespace ts {
|
||||
return elementName;
|
||||
}
|
||||
|
||||
function parseJsxExpression(): JsxExpression {
|
||||
function parseJsxExpression(inExpressionContext: boolean): JsxExpression {
|
||||
let node = <JsxExpression>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 = <JsxClosingElement>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);
|
||||
}
|
||||
|
||||
|
||||
+20
-9
@@ -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 '<asterisk>/' 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;
|
||||
|
||||
+3
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+19
-15
@@ -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);
|
||||
@@ -1457,6 +1445,22 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function nodeStartsNewLexicalEnvironment(n: Node): boolean {
|
||||
return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
export function cloneEntityName(node: EntityName): EntityName {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
let clone = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
|
||||
clone.text = (<Identifier>node).text;
|
||||
return clone;
|
||||
}
|
||||
else {
|
||||
let clone = <QualifiedName>createSynthesizedNode(SyntaxKind.QualifiedName);
|
||||
clone.left = cloneEntityName((<QualifiedName>node).left);
|
||||
clone.left.parent = clone;
|
||||
clone.right = <Identifier>cloneEntityName((<QualifiedName>node).right);
|
||||
clone.right.parent = clone;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -71,4 +71,4 @@ class TypeWriterWalker {
|
||||
symbol: symbolString
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+3
-3
@@ -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;
|
||||
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
|
||||
Vendored
+1
-1
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Vendored
+7
-2
@@ -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;
|
||||
|
||||
Vendored
+29
-1
@@ -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.
|
||||
|
||||
+55
-4
@@ -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<PendingErrorCheck>((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 = <protocol.GeterrRequestArgs>request.arguments;
|
||||
return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false};
|
||||
},
|
||||
[CommandNames.GeterrForProject]: (request: protocol.Request) => {
|
||||
let { file, delay } = <protocol.GeterrForProjectRequestArgs>request.arguments;
|
||||
return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false};
|
||||
},
|
||||
[CommandNames.Change]: (request: protocol.Request) => {
|
||||
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
|
||||
this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+93
-35
@@ -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(<BreakOrContinueStatement>node.parent);
|
||||
return getBreakOrContinueStatementOccurrences(<BreakOrContinueStatement>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*</
|
||||
let tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
|
||||
|
||||
let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
|
||||
|
||||
@@ -5551,8 +5553,8 @@ namespace ts {
|
||||
// This wasn't the start of a token. Check to see if it might be a
|
||||
// match in a comment or string if that's what the caller is asking
|
||||
// for.
|
||||
if ((findInStrings && isInString(position)) ||
|
||||
(findInComments && isInComment(position))) {
|
||||
if ((findInStrings && isInString(sourceFile, position)) ||
|
||||
(findInComments && isInNonReferenceComment(sourceFile, position))) {
|
||||
|
||||
// In the case where we're looking inside comments/strings, we don't have
|
||||
// an actual definition. So just use 'undefined' here. Features like
|
||||
@@ -5616,30 +5618,13 @@ namespace ts {
|
||||
return result[index];
|
||||
}
|
||||
|
||||
function isInString(position: number) {
|
||||
let token = getTokenAtPosition(sourceFile, position);
|
||||
return token && token.kind === SyntaxKind.StringLiteral && position > 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 = <FunctionDeclaration>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 ? (<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
|
||||
|
||||
+17
-6
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'.
|
||||
@@ -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";
|
||||
@@ -8,4 +8,5 @@ s.map(// do something
|
||||
//// [commentInMethodCall.js]
|
||||
//commment here
|
||||
var s;
|
||||
s.map(function () { });
|
||||
s.map(// do something
|
||||
function () { });
|
||||
|
||||
@@ -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 () { });
|
||||
@@ -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*/() => { });
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
@@ -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");
|
||||
@@ -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
|
||||
|
||||
@@ -6,5 +6,5 @@ var v = {
|
||||
|
||||
//// [commentsBeforeFunctionExpression1.js]
|
||||
var v = {
|
||||
f: function (a) { return 0; }
|
||||
f: /**own f*/ function (a) { return 0; }
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
@@ -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))
|
||||
|
||||
};
|
||||
@@ -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
|
||||
|
||||
};
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -17,7 +17,7 @@ function makePoint(x) {
|
||||
};
|
||||
}
|
||||
;
|
||||
var point = makePoint(2);
|
||||
var /*3*/ point = makePoint(2);
|
||||
point.x = 30;
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
})();
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -29,21 +29,18 @@ var foo = (function () {
|
||||
return foo;
|
||||
})();
|
||||
var x;
|
||||
x = <any> {test}: <any></any> };
|
||||
x = <any> {test} <any></any> };
|
||||
|
||||
x = <any><any></any>;
|
||||
|
||||
x = <foo>hello {<foo>} </foo>};
|
||||
x = <foo>hello {<foo>} </foo>}
|
||||
|
||||
x = <foo test={<foo>}>hello</foo>}/>;
|
||||
x = <foo test={<foo>}>hello</foo>}/>
|
||||
|
||||
x = <foo test={<foo>}>hello{<foo>}</foo>};
|
||||
x = <foo test={<foo>}>hello{<foo>}</foo>}
|
||||
|
||||
x = <foo>x</foo>, x = <foo />;
|
||||
|
||||
<foo>{<foo><foo>{/foo/.test(x) ? <foo><foo></foo> : <foo><foo></foo>}</foo>}</foo>
|
||||
:
|
||||
}
|
||||
|
||||
|
||||
</></>}</></>}/></></></>;
|
||||
}</></>}</></>}/></></></>;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//// [jsxHash.tsx]
|
||||
var t02 = <a>{0}#</a>;
|
||||
var t03 = <a>#{0}</a>;
|
||||
var t04 = <a>#{0}#</a>;
|
||||
var t05 = <a>#<i></i></a>;
|
||||
var t06 = <a>#<i></i></a>;
|
||||
var t07 = <a>#<i>#</i></a>;
|
||||
var t08 = <a><i></i>#</a>;
|
||||
var t09 = <a>#<i></i>#</a>;
|
||||
var t10 = <a><i/>#</a>;
|
||||
var t11 = <a>#<i/></a>;
|
||||
var t12 = <a>#</a>;
|
||||
|
||||
|
||||
//// [jsxHash.jsx]
|
||||
var t02 = <a>{0}#</a>;
|
||||
var t03 = <a>#{0}</a>;
|
||||
var t04 = <a>#{0}#</a>;
|
||||
var t05 = <a>#<i></i></a>;
|
||||
var t06 = <a>#<i></i></a>;
|
||||
var t07 = <a>#<i>#</i></a>;
|
||||
var t08 = <a><i></i>#</a>;
|
||||
var t09 = <a>#<i></i>#</a>;
|
||||
var t10 = <a><i />#</a>;
|
||||
var t11 = <a>#<i /></a>;
|
||||
var t12 = <a>#</a>;
|
||||
@@ -0,0 +1,34 @@
|
||||
=== tests/cases/compiler/jsxHash.tsx ===
|
||||
var t02 = <a>{0}#</a>;
|
||||
>t02 : Symbol(t02, Decl(jsxHash.tsx, 0, 3))
|
||||
|
||||
var t03 = <a>#{0}</a>;
|
||||
>t03 : Symbol(t03, Decl(jsxHash.tsx, 1, 3))
|
||||
|
||||
var t04 = <a>#{0}#</a>;
|
||||
>t04 : Symbol(t04, Decl(jsxHash.tsx, 2, 3))
|
||||
|
||||
var t05 = <a>#<i></i></a>;
|
||||
>t05 : Symbol(t05, Decl(jsxHash.tsx, 3, 3))
|
||||
|
||||
var t06 = <a>#<i></i></a>;
|
||||
>t06 : Symbol(t06, Decl(jsxHash.tsx, 4, 3))
|
||||
|
||||
var t07 = <a>#<i>#</i></a>;
|
||||
>t07 : Symbol(t07, Decl(jsxHash.tsx, 5, 3))
|
||||
|
||||
var t08 = <a><i></i>#</a>;
|
||||
>t08 : Symbol(t08, Decl(jsxHash.tsx, 6, 3))
|
||||
|
||||
var t09 = <a>#<i></i>#</a>;
|
||||
>t09 : Symbol(t09, Decl(jsxHash.tsx, 7, 3))
|
||||
|
||||
var t10 = <a><i/>#</a>;
|
||||
>t10 : Symbol(t10, Decl(jsxHash.tsx, 8, 3))
|
||||
|
||||
var t11 = <a>#<i/></a>;
|
||||
>t11 : Symbol(t11, Decl(jsxHash.tsx, 9, 3))
|
||||
|
||||
var t12 = <a>#</a>;
|
||||
>t12 : Symbol(t12, Decl(jsxHash.tsx, 10, 3))
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
=== tests/cases/compiler/jsxHash.tsx ===
|
||||
var t02 = <a>{0}#</a>;
|
||||
>t02 : any
|
||||
><a>{0}#</a> : any
|
||||
>a : any
|
||||
>a : any
|
||||
|
||||
var t03 = <a>#{0}</a>;
|
||||
>t03 : any
|
||||
><a>#{0}</a> : any
|
||||
>a : any
|
||||
>a : any
|
||||
|
||||
var t04 = <a>#{0}#</a>;
|
||||
>t04 : any
|
||||
><a>#{0}#</a> : any
|
||||
>a : any
|
||||
>a : any
|
||||
|
||||
var t05 = <a>#<i></i></a>;
|
||||
>t05 : any
|
||||
><a>#<i></i></a> : any
|
||||
>a : any
|
||||
><i></i> : any
|
||||
>i : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t06 = <a>#<i></i></a>;
|
||||
>t06 : any
|
||||
><a>#<i></i></a> : any
|
||||
>a : any
|
||||
><i></i> : any
|
||||
>i : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t07 = <a>#<i>#</i></a>;
|
||||
>t07 : any
|
||||
><a>#<i>#</i></a> : any
|
||||
>a : any
|
||||
><i>#</i> : any
|
||||
>i : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t08 = <a><i></i>#</a>;
|
||||
>t08 : any
|
||||
><a><i></i>#</a> : any
|
||||
>a : any
|
||||
><i></i> : any
|
||||
>i : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t09 = <a>#<i></i>#</a>;
|
||||
>t09 : any
|
||||
><a>#<i></i>#</a> : any
|
||||
>a : any
|
||||
><i></i> : any
|
||||
>i : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t10 = <a><i/>#</a>;
|
||||
>t10 : any
|
||||
><a><i/>#</a> : any
|
||||
>a : any
|
||||
><i/> : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t11 = <a>#<i/></a>;
|
||||
>t11 : any
|
||||
><a>#<i/></a> : any
|
||||
>a : any
|
||||
><i/> : any
|
||||
>i : any
|
||||
>a : any
|
||||
|
||||
var t12 = <a>#</a>;
|
||||
>t12 : any
|
||||
><a>#</a> : any
|
||||
>a : any
|
||||
>a : any
|
||||
|
||||
@@ -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
|
||||
<div>stuff</div {...props}>;
|
||||
~
|
||||
!!! error TS1005: '>' expected.
|
||||
~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
<div {...props}>stuff</div {...props}>;
|
||||
~~~~~
|
||||
!!! error TS2304: Cannot find name 'props'.
|
||||
~
|
||||
!!! error TS1005: '>' expected.
|
||||
~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
|
||||
<a>></a>;
|
||||
<a> ></a>;
|
||||
|
||||
@@ -65,17 +65,17 @@ a['foo'] > ;
|
||||
<a b=>;
|
||||
var x = <div>one</div><div>two</div>;;
|
||||
var x = <div>one</div> /* intervening comment */ /* intervening comment */ <div>two</div>;;
|
||||
<a>{"str"};}</a>;
|
||||
<span className="a"/>, id="b" />;
|
||||
<div className=/>"app">;
|
||||
<a>{"str"}}</a>;
|
||||
<span className="a"/> id="b" />;
|
||||
<div className=/>>;
|
||||
<div {...props}/>;
|
||||
|
||||
<div>stuff</div> {}...props}>;
|
||||
<div {...props}>stuff</div> {}...props}>;
|
||||
<div>stuff</div>...props}>;
|
||||
<div {...props}>stuff</div>...props}>;
|
||||
|
||||
<a>></a>;
|
||||
<a> ></a>;
|
||||
<a b=>;
|
||||
<a b={ < }>;
|
||||
<a>}</a>;
|
||||
<a /> .../*hai*/asdf/>;</></></></>;
|
||||
<a /> /*hai*//*hai*/asdf/>;</></></></>;
|
||||
|
||||
@@ -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<T, U>(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<any, any>([1, ""], (x) => x.toString());
|
||||
var r6 = map<Object, Object>([1, ""], (x) => x.toString());
|
||||
var r7 = map<number, string>([1, ""], (x) => x.toString()); // error
|
||||
|
||||
@@ -42,5 +42,6 @@ var C2 = (function () {
|
||||
return C2;
|
||||
})();
|
||||
var b = {
|
||||
x: function () { }, 1: // error
|
||||
x: function () { }, 1: // error
|
||||
// error
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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/ * * / /;
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 };
|
||||
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
~
|
||||
!!! error TS1005: '}' expected.
|
||||
|
||||
|
||||
!!! error TS17002: Expected corresponding JSX closing tag for 'div'.
|
||||
@@ -11,7 +11,9 @@ var y = { a: 1 };
|
||||
|
||||
//// [tsxErrorRecovery1.jsx]
|
||||
function foo() {
|
||||
var x = <div> {} </div>;
|
||||
var x = <div> {}div>
|
||||
}
|
||||
// Shouldn't see any errors down here
|
||||
var y = {a} 1 };
|
||||
</>;
|
||||
}
|
||||
// Shouldn't see any errors down here
|
||||
var y = { a: 1 };
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//// [typeAliasDeclarationEmit.ts]
|
||||
|
||||
export type callback<T> = () => T;
|
||||
|
||||
export type CallbackArray<T extends callback> = () => T;
|
||||
|
||||
//// [typeAliasDeclarationEmit.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
});
|
||||
|
||||
|
||||
//// [typeAliasDeclarationEmit.d.ts]
|
||||
export declare type callback<T> = () => T;
|
||||
export declare type CallbackArray<T extends callback> = () => T;
|
||||
@@ -0,0 +1,13 @@
|
||||
=== tests/cases/compiler/typeAliasDeclarationEmit.ts ===
|
||||
|
||||
export type callback<T> = () => 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 extends callback> = () => 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))
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
=== tests/cases/compiler/typeAliasDeclarationEmit.ts ===
|
||||
|
||||
export type callback<T> = () => T;
|
||||
>callback : () => T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
export type CallbackArray<T extends callback> = () => T;
|
||||
>CallbackArray : () => T
|
||||
>T : T
|
||||
>callback : () => T
|
||||
>T : T
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//// [typeAliasDeclarationEmit2.ts]
|
||||
|
||||
export type A<a> = { value: a };
|
||||
|
||||
//// [typeAliasDeclarationEmit2.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
});
|
||||
|
||||
|
||||
//// [typeAliasDeclarationEmit2.d.ts]
|
||||
export declare type A<a> = {
|
||||
value: a;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
=== tests/cases/compiler/typeAliasDeclarationEmit2.ts ===
|
||||
|
||||
export type A<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))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
=== tests/cases/compiler/typeAliasDeclarationEmit2.ts ===
|
||||
|
||||
export type A<a> = { value: a };
|
||||
>A : { value: a; }
|
||||
>a : a
|
||||
>value : a
|
||||
>a : a
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user