mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge remote-tracking branch 'tsupstream/master'
This commit is contained in:
commit
35331bde87
312 files changed
+7285
-2510
No files matched your search
+245
-123
@@ -1439,9 +1439,8 @@ namespace ts {
|
||||
// May be an untyped module. If so, ignore resolutionDiagnostic.
|
||||
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) {
|
||||
if (isForAugmentation) {
|
||||
Debug.assert(!!moduleNotFoundError);
|
||||
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
|
||||
error(errorNode, diag, moduleName, resolvedModule.resolvedFileName);
|
||||
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
|
||||
}
|
||||
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
|
||||
error(errorNode,
|
||||
@@ -1742,7 +1741,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] {
|
||||
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] {
|
||||
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable) {
|
||||
return getAccessibleSymbolChainFromSymbolTableWorker(symbols, []);
|
||||
}
|
||||
|
||||
function getAccessibleSymbolChainFromSymbolTableWorker(symbols: SymbolTable, visitedSymbolTables: SymbolTable[]): Symbol[] {
|
||||
if (contains(visitedSymbolTables, symbols)) {
|
||||
return undefined;
|
||||
}
|
||||
visitedSymbolTables.push(symbols);
|
||||
const result = trySymbolTable(symbols);
|
||||
visitedSymbolTables.pop();
|
||||
return result;
|
||||
|
||||
function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
|
||||
// If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
|
||||
if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
|
||||
@@ -1764,34 +1775,36 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// If symbol is directly available by its name in the symbol table
|
||||
if (isAccessible(symbols[symbol.name])) {
|
||||
return [symbol];
|
||||
}
|
||||
function trySymbolTable(symbols: SymbolTable) {
|
||||
// If symbol is directly available by its name in the symbol table
|
||||
if (isAccessible(symbols[symbol.name])) {
|
||||
return [symbol];
|
||||
}
|
||||
|
||||
// Check if symbol is any of the alias
|
||||
return forEachProperty(symbols, symbolFromSymbolTable => {
|
||||
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
|
||||
&& symbolFromSymbolTable.name !== "export="
|
||||
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
|
||||
if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
|
||||
// Is this external alias, then use it to name
|
||||
ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
|
||||
// Check if symbol is any of the alias
|
||||
return forEachProperty(symbols, symbolFromSymbolTable => {
|
||||
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
|
||||
&& symbolFromSymbolTable.name !== "export="
|
||||
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
|
||||
if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
|
||||
// Is this external alias, then use it to name
|
||||
ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
|
||||
|
||||
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
|
||||
if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
|
||||
return [symbolFromSymbolTable];
|
||||
}
|
||||
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
|
||||
if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
|
||||
return [symbolFromSymbolTable];
|
||||
}
|
||||
|
||||
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
|
||||
// but only if the symbolFromSymbolTable can be qualified
|
||||
const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
|
||||
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
|
||||
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
|
||||
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
|
||||
// but only if the symbolFromSymbolTable can be qualified
|
||||
const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTableWorker(resolvedImportedSymbol.exports, visitedSymbolTables) : undefined;
|
||||
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
|
||||
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol) {
|
||||
@@ -2673,7 +2686,7 @@ namespace ts {
|
||||
}
|
||||
Debug.assert(bindingElement.kind === SyntaxKind.BindingElement);
|
||||
if (bindingElement.propertyName) {
|
||||
writer.writeSymbol(getTextOfNode(bindingElement.propertyName), bindingElement.symbol);
|
||||
writer.writeProperty(getTextOfNode(bindingElement.propertyName));
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
@@ -3472,20 +3485,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!popTypeResolution()) {
|
||||
if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
|
||||
// Variable has type annotation that circularly references the variable itself
|
||||
type = unknownType;
|
||||
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
|
||||
symbolToString(symbol));
|
||||
}
|
||||
else {
|
||||
// Variable has initializer that circularly references the variable itself
|
||||
type = anyType;
|
||||
if (compilerOptions.noImplicitAny) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
|
||||
symbolToString(symbol));
|
||||
}
|
||||
}
|
||||
type = reportCircularityError(symbol);
|
||||
}
|
||||
links.type = type;
|
||||
}
|
||||
@@ -3619,11 +3619,33 @@ namespace ts {
|
||||
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
|
||||
if (!popTypeResolution()) {
|
||||
type = reportCircularityError(symbol);
|
||||
}
|
||||
links.type = type;
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
|
||||
function reportCircularityError(symbol: Symbol) {
|
||||
// Check if variable has type annotation that circularly references the variable itself
|
||||
if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
|
||||
symbolToString(symbol));
|
||||
return unknownType;
|
||||
}
|
||||
// Otherwise variable has initializer that circularly references the variable itself
|
||||
if (compilerOptions.noImplicitAny) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
|
||||
symbolToString(symbol));
|
||||
}
|
||||
return anyType;
|
||||
}
|
||||
|
||||
function getTypeOfSymbol(symbol: Symbol): Type {
|
||||
if (symbol.flags & SymbolFlags.Instantiated) {
|
||||
return getTypeOfInstantiatedSymbol(symbol);
|
||||
@@ -4512,18 +4534,17 @@ namespace ts {
|
||||
// Resolve upfront such that recursive references see an empty object type.
|
||||
setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
// In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
|
||||
// and T as the template type. If K is of the form 'keyof S', the mapped type and S are
|
||||
// homomorphic and we copy property modifiers from corresponding properties in S.
|
||||
// and T as the template type.
|
||||
const typeParameter = getTypeParameterFromMappedType(type);
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
const homomorphicType = getHomomorphicTypeFromMappedType(type);
|
||||
const templateType = getTemplateTypeFromMappedType(type);
|
||||
const modifiersType = getModifiersTypeFromMappedType(type);
|
||||
const templateReadonly = !!type.declaration.readonlyToken;
|
||||
const templateOptional = !!type.declaration.questionToken;
|
||||
// First, if the constraint type is a type parameter, obtain the base constraint. Then,
|
||||
// if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
|
||||
// Finally, iterate over the constituents of the resulting iteration type.
|
||||
const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentType(constraintType) : constraintType;
|
||||
const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentType(constraintType) : constraintType;
|
||||
const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType;
|
||||
forEachType(iterationType, t => {
|
||||
// Create a mapper from T to the current iteration type constituent. Then, if the
|
||||
@@ -4536,11 +4557,11 @@ namespace ts {
|
||||
// Otherwise, for type string create a string index signature.
|
||||
if (t.flags & TypeFlags.StringLiteral) {
|
||||
const propName = (<LiteralType>t).text;
|
||||
const homomorphicProp = homomorphicType && getPropertyOfType(homomorphicType, propName);
|
||||
const isOptional = templateOptional || !!(homomorphicProp && homomorphicProp.flags & SymbolFlags.Optional);
|
||||
const modifiersProp = getPropertyOfType(modifiersType, propName);
|
||||
const isOptional = templateOptional || !!(modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
|
||||
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
|
||||
prop.type = propType;
|
||||
prop.isReadonly = templateReadonly || homomorphicProp && isReadonlySymbol(homomorphicProp);
|
||||
prop.isReadonly = templateReadonly || modifiersProp && isReadonlySymbol(modifiersProp);
|
||||
members[propName] = prop;
|
||||
}
|
||||
else if (t.flags & TypeFlags.String) {
|
||||
@@ -4567,9 +4588,26 @@ namespace ts {
|
||||
unknownType);
|
||||
}
|
||||
|
||||
function getHomomorphicTypeFromMappedType(type: MappedType) {
|
||||
const constraint = getConstraintDeclaration(getTypeParameterFromMappedType(type));
|
||||
return constraint.kind === SyntaxKind.TypeOperator ? instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraint).type), type.mapper || identityMapper) : undefined;
|
||||
function getModifiersTypeFromMappedType(type: MappedType) {
|
||||
if (!type.modifiersType) {
|
||||
const constraintDeclaration = type.declaration.typeParameter.constraint;
|
||||
if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
|
||||
// If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
|
||||
// AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
|
||||
// 'keyof T' to a literal union type and we can't recover T from that type.
|
||||
type.modifiersType = instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraintDeclaration).type), type.mapper || identityMapper);
|
||||
}
|
||||
else {
|
||||
// Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
|
||||
// get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
|
||||
// the modifiers type is T. Otherwise, the modifiers type is {}.
|
||||
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
|
||||
const constraint = getConstraintTypeFromMappedType(declaredType);
|
||||
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
|
||||
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
|
||||
}
|
||||
}
|
||||
return type.modifiersType;
|
||||
}
|
||||
|
||||
function getErasedTemplateTypeFromMappedType(type: MappedType) {
|
||||
@@ -4579,7 +4617,7 @@ namespace ts {
|
||||
function isGenericMappedType(type: Type) {
|
||||
if (getObjectFlags(type) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
|
||||
return !!(constraintType.flags & (TypeFlags.TypeParameter | TypeFlags.Index));
|
||||
return maybeTypeOfKind(constraintType, TypeFlags.TypeVariable | TypeFlags.Index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -4667,33 +4705,24 @@ namespace ts {
|
||||
* The apparent type of a type parameter is the base constraint instantiated with the type parameter
|
||||
* as the type argument for the 'this' type.
|
||||
*/
|
||||
function getApparentTypeOfTypeParameter(type: TypeParameter) {
|
||||
function getApparentTypeOfTypeVariable(type: TypeVariable) {
|
||||
if (!type.resolvedApparentType) {
|
||||
let constraintType = getConstraintOfTypeParameter(type);
|
||||
let constraintType = getConstraintOfTypeVariable(type);
|
||||
while (constraintType && constraintType.flags & TypeFlags.TypeParameter) {
|
||||
constraintType = getConstraintOfTypeParameter(<TypeParameter>constraintType);
|
||||
constraintType = getConstraintOfTypeVariable(<TypeVariable>constraintType);
|
||||
}
|
||||
type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type);
|
||||
}
|
||||
return type.resolvedApparentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The apparent type of an indexed access T[K] is the type of T's string index signature, if any.
|
||||
*/
|
||||
function getApparentTypeOfIndexedAccess(type: IndexedAccessType) {
|
||||
return getIndexTypeOfType(getApparentType(type.objectType), IndexKind.String) || type;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a type parameter, return the base constraint of the type parameter. For the string, number,
|
||||
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
|
||||
* type itself. Note that the apparent type of a union type is the union type itself.
|
||||
*/
|
||||
function getApparentType(type: Type): Type {
|
||||
const t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>type) :
|
||||
type.flags & TypeFlags.IndexedAccess ? getApparentTypeOfIndexedAccess(<IndexedAccessType>type) :
|
||||
type;
|
||||
const t = type.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(<TypeVariable>type) : type;
|
||||
return t.flags & TypeFlags.StringLike ? globalStringType :
|
||||
t.flags & TypeFlags.NumberLike ? globalNumberType :
|
||||
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
|
||||
@@ -5279,6 +5308,12 @@ namespace ts {
|
||||
return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint;
|
||||
}
|
||||
|
||||
function getConstraintOfTypeVariable(type: TypeVariable): Type {
|
||||
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
|
||||
type.flags & TypeFlags.IndexedAccess ? (<IndexedAccessType>type).constraint :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol {
|
||||
return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter).parent);
|
||||
}
|
||||
@@ -5912,7 +5947,7 @@ namespace ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getIndexTypeForTypeVariable(type: TypeVariable) {
|
||||
function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType) {
|
||||
if (!type.resolvedIndexType) {
|
||||
type.resolvedIndexType = <IndexType>createType(TypeFlags.Index);
|
||||
type.resolvedIndexType.type = type;
|
||||
@@ -5931,7 +5966,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getIndexType(type: Type): Type {
|
||||
return type.flags & TypeFlags.TypeVariable ? getIndexTypeForTypeVariable(<TypeVariable>type) :
|
||||
return maybeTypeOfKind(type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType(<TypeVariable | UnionOrIntersectionType>type) :
|
||||
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
|
||||
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
|
||||
getLiteralTypeFromPropertyNames(type);
|
||||
@@ -5954,6 +5989,24 @@ namespace ts {
|
||||
const type = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
|
||||
type.objectType = objectType;
|
||||
type.indexType = indexType;
|
||||
// We eagerly compute the constraint of the indexed access type such that circularity
|
||||
// errors are immediately caught and reported. For example, class C { x: this["x"] }
|
||||
// becomes an error only when the constraint is eagerly computed.
|
||||
if (type.objectType.flags & TypeFlags.StructuredType) {
|
||||
// The constraint of T[K], where T is an object, union, or intersection type,
|
||||
// is the type of the string index signature of T, if any.
|
||||
type.constraint = getIndexTypeOfType(type.objectType, IndexKind.String);
|
||||
}
|
||||
else if (type.objectType.flags & TypeFlags.TypeVariable) {
|
||||
// The constraint of T[K], where T is a type variable, is A[K], where A is the
|
||||
// apparent type of T.
|
||||
const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>type.objectType);
|
||||
if (apparentType !== emptyObjectType) {
|
||||
type.constraint = isTypeOfKind((<IndexedAccessType>type).indexType, TypeFlags.StringLike) ?
|
||||
getIndexedAccessType(apparentType, (<IndexedAccessType>type).indexType) :
|
||||
getIndexTypeOfType(apparentType, IndexKind.String);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -6032,14 +6085,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
|
||||
if (indexType.flags & TypeFlags.TypeVariable ||
|
||||
objectType.flags & TypeFlags.TypeVariable && indexType.flags & TypeFlags.Index ||
|
||||
// If the index type is generic, if the object type is generic and doesn't originate in an expression,
|
||||
// or if the object type is a mapped type with a generic constraint, we are performing a higher-order
|
||||
// index access where we cannot meaningfully access the properties of the object type. Note that for a
|
||||
// generic T and a non-generic K, we eagerly resolve T[K] if it originates in an expression. This is to
|
||||
// preserve backwards compatibility. For example, an element access 'this["foo"]' has always been resolved
|
||||
// eagerly using the constraint type of 'this' at the given location.
|
||||
if (maybeTypeOfKind(indexType, TypeFlags.TypeVariable | TypeFlags.Index) ||
|
||||
maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) ||
|
||||
isGenericMappedType(objectType)) {
|
||||
// If the object type is a type variable (a type parameter or another indexed access type), if the
|
||||
// index type is a type variable or an index type, or if the object type is a mapped type with a
|
||||
// generic constraint, we are performing a higher-order index access where we cannot meaningfully
|
||||
// access the properties of the object type. In those cases, we first check that the index type is
|
||||
// assignable to 'keyof T' for the object type.
|
||||
if (objectType.flags & TypeFlags.Any) {
|
||||
return objectType;
|
||||
}
|
||||
// We first check that the index type is assignable to 'keyof T' for the object type.
|
||||
if (accessNode) {
|
||||
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
|
||||
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
|
||||
@@ -6056,6 +6114,7 @@ namespace ts {
|
||||
const id = objectType.id + "," + indexType.id;
|
||||
return indexedAccessTypes[id] || (indexedAccessTypes[id] = createIndexedAccessType(objectType, indexType));
|
||||
}
|
||||
// In the following we resolve T[K] to the type of the property in T selected by K.
|
||||
const apparentObjectType = getApparentType(objectType);
|
||||
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Primitive)) {
|
||||
const propTypes: Type[] = [];
|
||||
@@ -6539,7 +6598,7 @@ namespace ts {
|
||||
// union type A | undefined, we produce { [P in keyof A]: X } | undefined.
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
if (constraintType.flags & TypeFlags.Index) {
|
||||
const typeVariable = <TypeParameter>(<IndexType>constraintType).type;
|
||||
const typeVariable = (<IndexType>constraintType).type;
|
||||
const mappedTypeVariable = instantiateType(typeVariable, mapper);
|
||||
if (typeVariable !== mappedTypeVariable) {
|
||||
return mapType(mappedTypeVariable, t => {
|
||||
@@ -7162,6 +7221,25 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
|
||||
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
|
||||
return false;
|
||||
}
|
||||
// at this point we know that this is union or intersection type possibly with nullable constituents.
|
||||
// check if we still will have compound type if we ignore nullable components.
|
||||
let seenNonNullable = false;
|
||||
for (const t of (<UnionOrIntersectionType>type).types) {
|
||||
if (t.flags & TypeFlags.Nullable) {
|
||||
continue;
|
||||
}
|
||||
if (seenNonNullable) {
|
||||
return true;
|
||||
}
|
||||
seenNonNullable = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare two types and return
|
||||
// Ternary.True if they are related with no assumptions,
|
||||
// Ternary.Maybe if they are related with assumptions of other relationships, or
|
||||
@@ -7194,7 +7272,7 @@ namespace ts {
|
||||
// and intersection types are further deconstructed on the target side, we don't want to
|
||||
// make the check again (as it might fail for a partial target type). Therefore we obtain
|
||||
// the regular source type and proceed with that.
|
||||
if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target)) {
|
||||
source = getRegularTypeOfObjectLiteral(source);
|
||||
}
|
||||
}
|
||||
@@ -7243,8 +7321,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
else if (target.flags & TypeFlags.TypeParameter) {
|
||||
// A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P].
|
||||
if (getObjectFlags(source) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(<MappedType>source) === getIndexType(target)) {
|
||||
if (!(<MappedType>source).declaration.questionToken) {
|
||||
@@ -7273,10 +7350,10 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Given a type parameter T with a constraint C, a type S is assignable to
|
||||
// Given a type variable T with a constraint C, a type S is assignable to
|
||||
// keyof T if S is assignable to keyof C.
|
||||
if ((<IndexType>target).type.flags & TypeFlags.TypeParameter) {
|
||||
const constraint = getConstraintOfTypeParameter(<TypeParameter>(<IndexType>target).type);
|
||||
if ((<IndexType>target).type.flags & TypeFlags.TypeVariable) {
|
||||
const constraint = getConstraintOfTypeVariable(<TypeVariable>(<IndexType>target).type);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
|
||||
return result;
|
||||
@@ -7292,6 +7369,14 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
|
||||
// A is the apparent type of S.
|
||||
if ((<IndexedAccessType>target).constraint) {
|
||||
if (result = isRelatedTo(source, (<IndexedAccessType>target).constraint, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.TypeParameter) {
|
||||
@@ -7300,6 +7385,7 @@ namespace ts {
|
||||
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(<MappedType>target));
|
||||
const templateType = getTemplateTypeFromMappedType(<MappedType>target);
|
||||
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -7321,6 +7407,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
|
||||
// A is the apparent type of S.
|
||||
if ((<IndexedAccessType>source).constraint) {
|
||||
if (result = isRelatedTo((<IndexedAccessType>source).constraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if relationship holds for all type arguments
|
||||
@@ -8708,12 +8804,15 @@ namespace ts {
|
||||
if (constraintType.flags & TypeFlags.Index) {
|
||||
// We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X },
|
||||
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
|
||||
// type and then infer from that type to T.
|
||||
// type and then make a secondary inference from that type to T. We make a secondary inference
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const index = indexOf(typeVariables, (<IndexType>constraintType).type);
|
||||
if (index >= 0 && !typeInferences[index].isFixed) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (inferredType) {
|
||||
inferiority++;
|
||||
inferFromTypes(inferredType, typeVariables[index]);
|
||||
inferiority--;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -10404,6 +10503,29 @@ namespace ts {
|
||||
return baseConstructorType === nullWideningType;
|
||||
}
|
||||
|
||||
function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) {
|
||||
const containingClassDecl = <ClassDeclaration>container.parent;
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
|
||||
|
||||
// If a containing class does not have extends clause or the class extends null
|
||||
// skip checking whether super statement is called before "this" accessing.
|
||||
if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
|
||||
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
|
||||
|
||||
// We should give an error in the following cases:
|
||||
// - No super-call
|
||||
// - "this" is accessing before super-call.
|
||||
// i.e super(this)
|
||||
// this.x; super();
|
||||
// We want to make sure that super-call is done before accessing "this" so that
|
||||
// "this" is not accessed as a parameter of the super-call.
|
||||
if (!superCall || superCall.end > node.pos) {
|
||||
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
|
||||
error(node, diagnosticMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkThisExpression(node: Node): Type {
|
||||
// Stop at the first arrow function so that we can
|
||||
// tell whether 'this' needs to be captured.
|
||||
@@ -10411,26 +10533,7 @@ namespace ts {
|
||||
let needToCaptureLexicalThis = false;
|
||||
|
||||
if (container.kind === SyntaxKind.Constructor) {
|
||||
const containingClassDecl = <ClassDeclaration>container.parent;
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
|
||||
|
||||
// If a containing class does not have extends clause or the class extends null
|
||||
// skip checking whether super statement is called before "this" accessing.
|
||||
if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
|
||||
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
|
||||
|
||||
// We should give an error in the following cases:
|
||||
// - No super-call
|
||||
// - "this" is accessing before super-call.
|
||||
// i.e super(this)
|
||||
// this.x; super();
|
||||
// We want to make sure that super-call is done before accessing "this" so that
|
||||
// "this" is not accessed as a parameter of the super-call.
|
||||
if (!superCall || superCall.end > node.pos) {
|
||||
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
|
||||
error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
|
||||
}
|
||||
}
|
||||
checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
|
||||
}
|
||||
|
||||
// Now skip arrow functions to get the "real" owner of 'this'.
|
||||
@@ -10578,6 +10681,10 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (!isCallExpression && container.kind === SyntaxKind.Constructor) {
|
||||
checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class);
|
||||
}
|
||||
|
||||
if ((getModifierFlags(container) & ModifierFlags.Static) || isCallExpression) {
|
||||
nodeCheckFlag = NodeCheckFlags.SuperStatic;
|
||||
}
|
||||
@@ -11243,13 +11350,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type {
|
||||
// It is usually not safe to call checkExpressionCached if we can be contextually typing.
|
||||
// You can tell that we are contextually typing because of the contextualMapper parameter.
|
||||
// While it is true that a spread element can have a contextual type, it does not do anything
|
||||
// with this type. It is neither affected by it, nor does it propagate it to its operand.
|
||||
// So the fact that contextualMapper is passed is not important, because the operand of a spread
|
||||
// element is not contextually typed.
|
||||
const arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
|
||||
const arrayOrIterableType = checkExpression(node.expression, contextualMapper);
|
||||
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
|
||||
}
|
||||
|
||||
@@ -11539,8 +11640,11 @@ namespace ts {
|
||||
if (propertiesArray.length > 0) {
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), /*isFromObjectLiteral*/ true);
|
||||
}
|
||||
spread.flags |= propagatedFlags;
|
||||
spread.symbol = node.symbol;
|
||||
if (spread.flags & TypeFlags.Object) {
|
||||
// only set the symbol and flags if this is a (fresh) object type
|
||||
spread.flags |= propagatedFlags;
|
||||
spread.symbol = node.symbol;
|
||||
}
|
||||
return spread;
|
||||
}
|
||||
|
||||
@@ -13466,13 +13570,14 @@ namespace ts {
|
||||
const containingClass = getContainingClass(node);
|
||||
if (containingClass) {
|
||||
const containingType = getTypeOfNode(containingClass);
|
||||
const baseTypes = getBaseTypes(<InterfaceType>containingType);
|
||||
if (baseTypes.length) {
|
||||
let baseTypes = getBaseTypes(containingType as InterfaceType);
|
||||
while (baseTypes.length) {
|
||||
const baseType = baseTypes[0];
|
||||
if (modifiers & ModifierFlags.Protected &&
|
||||
baseType.symbol === declaration.parent.symbol) {
|
||||
return true;
|
||||
}
|
||||
baseTypes = getBaseTypes(baseType as InterfaceType);
|
||||
}
|
||||
}
|
||||
if (modifiers & ModifierFlags.Private) {
|
||||
@@ -14980,8 +15085,8 @@ namespace ts {
|
||||
|
||||
function isLiteralContextualType(contextualType: Type) {
|
||||
if (contextualType) {
|
||||
if (contextualType.flags & TypeFlags.TypeParameter) {
|
||||
const apparentType = getApparentTypeOfTypeParameter(<TypeParameter>contextualType);
|
||||
if (contextualType.flags & TypeFlags.TypeVariable) {
|
||||
const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>contextualType);
|
||||
// If the type parameter is constrained to the base primitive type we're checking for,
|
||||
// consider this a literal context. For example, given a type parameter 'T extends string',
|
||||
// this causes us to infer string literal types for T.
|
||||
@@ -15816,7 +15921,7 @@ namespace ts {
|
||||
checkSourceElement(node.type);
|
||||
const type = <MappedType>getTypeFromMappedTypeNode(node);
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>constraintType) : constraintType;
|
||||
const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(<TypeVariable>constraintType) : constraintType;
|
||||
checkTypeAssignableTo(keyType, stringType, node.typeParameter.constraint);
|
||||
}
|
||||
|
||||
@@ -16198,7 +16303,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefined);
|
||||
const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull);
|
||||
if (isTypeAny(onfulfilledParameterType)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -16481,6 +16586,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode {
|
||||
return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type;
|
||||
}
|
||||
|
||||
/** Check the decorators of a node */
|
||||
function checkDecorators(node: Node): void {
|
||||
if (!node.decorators) {
|
||||
@@ -16512,7 +16621,7 @@ namespace ts {
|
||||
const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
if (constructor) {
|
||||
for (const parameter of constructor.parameters) {
|
||||
markTypeNodeAsReferenced(parameter.type);
|
||||
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -16521,15 +16630,17 @@ namespace ts {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
|
||||
markTypeNodeAsReferenced(parameter.type);
|
||||
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
|
||||
}
|
||||
|
||||
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
|
||||
break;
|
||||
case SyntaxKind.Parameter:
|
||||
markTypeNodeAsReferenced((<PropertyDeclaration | ParameterDeclaration>node).type);
|
||||
markTypeNodeAsReferenced((<PropertyDeclaration>node).type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -16692,6 +16803,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isRemovedPropertyFromObjectSpread(node: Node) {
|
||||
if (isBindingElement(node) && isObjectBindingPattern(node.parent)) {
|
||||
const lastElement = lastOrUndefined(node.parent.elements);
|
||||
return lastElement !== node && !!lastElement.dotDotDotToken;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function errorUnusedLocal(node: Node, name: string) {
|
||||
if (isIdentifierThatStartsWithUnderScore(node)) {
|
||||
const declaration = getRootDeclaration(node.parent);
|
||||
@@ -16701,7 +16820,10 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(node, Diagnostics._0_is_declared_but_never_used, name);
|
||||
|
||||
if (!isRemovedPropertyFromObjectSpread(node.kind === SyntaxKind.Identifier ? node.parent : node)) {
|
||||
error(node, Diagnostics._0_is_declared_but_never_used, name);
|
||||
}
|
||||
}
|
||||
|
||||
function parameterNameStartsWithUnderscore(parameterName: DeclarationName) {
|
||||
@@ -17989,7 +18111,7 @@ namespace ts {
|
||||
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
if (languageVersion < ScriptTarget.ES2015 && !isInAmbientContext(node)) {
|
||||
checkExternalEmitHelpers(baseTypeNode.parent, ExternalEmitHelpers.Extends);
|
||||
}
|
||||
|
||||
|
||||
@@ -549,14 +549,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
const key = trimString((value || "")).toLowerCase();
|
||||
const map = opt.type;
|
||||
if (key in map) {
|
||||
return map[key];
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnosticForInvalidCustomType(opt));
|
||||
}
|
||||
return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -848,7 +841,7 @@ namespace ts {
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = []): ParsedCommandLine {
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = [], extraFileExtensions: FileExtensionInfo[] = []): ParsedCommandLine {
|
||||
const errors: Diagnostic[] = [];
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName);
|
||||
@@ -988,7 +981,7 @@ namespace ts {
|
||||
includeSpecs = ["**/*"];
|
||||
}
|
||||
|
||||
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
|
||||
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors, extraFileExtensions);
|
||||
|
||||
if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
|
||||
errors.push(
|
||||
@@ -1192,7 +1185,7 @@ namespace ts {
|
||||
* @param host The host used to resolve files and directories.
|
||||
* @param errors An array for diagnostic reporting.
|
||||
*/
|
||||
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[]): ExpandResult {
|
||||
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], extraFileExtensions: FileExtensionInfo[]): ExpandResult {
|
||||
basePath = normalizePath(basePath);
|
||||
|
||||
// The exclude spec list is converted into a regular expression, which allows us to quickly
|
||||
@@ -1226,7 +1219,7 @@ namespace ts {
|
||||
|
||||
// Rather than requery this for each file and filespec, we query the supported extensions
|
||||
// once and store it on the expansion context.
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
const supportedExtensions = getSupportedExtensions(options, extraFileExtensions);
|
||||
|
||||
// Literal files are always included verbatim. An "include" or "exclude" specification cannot
|
||||
// remove a literal file.
|
||||
|
||||
@@ -156,6 +156,9 @@ namespace ts {
|
||||
|
||||
if (!skipTrailingComments) {
|
||||
emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true);
|
||||
if (hasWrittenComment && !writer.isAtStartOfLine()) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
|
||||
+14
-22
@@ -863,24 +863,6 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties defined on a map-like (but not from its prototype chain).
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* reduceProperties instead as it offers better performance.
|
||||
*
|
||||
* @param map The map-like to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a shallow equality comparison of the contents of two map-likes.
|
||||
*
|
||||
@@ -1942,8 +1924,18 @@ namespace ts {
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions): string[] {
|
||||
return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]): string[] {
|
||||
const needAllExtensions = options && options.allowJs;
|
||||
if (!extraFileExtensions || extraFileExtensions.length === 0) {
|
||||
return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
}
|
||||
const extensions = (needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions).slice(0);
|
||||
for (const extInfo of extraFileExtensions) {
|
||||
if (needAllExtensions || extInfo.scriptKind === ScriptKind.TS) {
|
||||
extensions.push(extInfo.extension);
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
export function hasJavaScriptFileExtension(fileName: string) {
|
||||
@@ -1954,10 +1946,10 @@ namespace ts {
|
||||
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions) {
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]) {
|
||||
if (!fileName) { return false; }
|
||||
|
||||
for (const extension of getSupportedExtensions(compilerOptions)) {
|
||||
for (const extension of getSupportedExtensions(compilerOptions, extraFileExtensions)) {
|
||||
if (fileExtensionIs(fileName, extension)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,7 @@ namespace ts {
|
||||
writer.writeSpace = writer.write;
|
||||
writer.writeStringLiteral = writer.writeLiteral;
|
||||
writer.writeParameter = writer.write;
|
||||
writer.writeProperty = writer.write;
|
||||
writer.writeSymbol = writer.write;
|
||||
setWriter(writer);
|
||||
}
|
||||
|
||||
@@ -3165,6 +3165,10 @@
|
||||
"category": "Error",
|
||||
"code": 17010
|
||||
},
|
||||
"'super' must be called before accessing a property of 'super' in the constructor of a derived class.": {
|
||||
"category": "Error",
|
||||
"code": 17011
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -6337,7 +6337,7 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.AsteriskToken:
|
||||
const asterisk = scanner.getTokenText();
|
||||
if (state === JSDocState.SawAsterisk) {
|
||||
if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) {
|
||||
// If we've already seen an asterisk, then we can no longer parse a tag on this line
|
||||
state = JSDocState.SavingComments;
|
||||
pushComment(asterisk);
|
||||
@@ -6358,7 +6358,10 @@ namespace ts {
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
// only collect whitespace if we're already saving comments or have just crossed the comment indent margin
|
||||
const whitespace = scanner.getTokenText();
|
||||
if (state === JSDocState.SavingComments || margin !== undefined && indent + whitespace.length > margin) {
|
||||
if (state === JSDocState.SavingComments) {
|
||||
comments.push(whitespace);
|
||||
}
|
||||
else if (margin !== undefined && indent + whitespace.length > margin) {
|
||||
comments.push(whitespace.slice(margin - indent - 1));
|
||||
}
|
||||
indent += whitespace.length;
|
||||
@@ -6366,6 +6369,8 @@ namespace ts {
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break;
|
||||
default:
|
||||
// anything other than whitespace or asterisk at the beginning of the line starts the comment text
|
||||
state = JSDocState.SavingComments;
|
||||
pushComment(scanner.getTokenText());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ namespace ts {
|
||||
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return stringify({
|
||||
return JSON.stringify({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
|
||||
@@ -2286,14 +2286,19 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
startLexicalEnvironment();
|
||||
let loopBody = visitNode(node.statement, visitor, isStatement);
|
||||
const lexicalEnvironment = endLexicalEnvironment();
|
||||
|
||||
const currentState = convertedLoopState;
|
||||
convertedLoopState = outerConvertedLoopState;
|
||||
|
||||
if (loopOutParameters.length) {
|
||||
if (loopOutParameters.length || lexicalEnvironment) {
|
||||
const statements = isBlock(loopBody) ? (<Block>loopBody).statements.slice() : [loopBody];
|
||||
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
|
||||
if (loopOutParameters.length) {
|
||||
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
|
||||
}
|
||||
addRange(statements, lexicalEnvironment)
|
||||
loopBody = createBlock(statements, /*location*/ undefined, /*multiline*/ true);
|
||||
}
|
||||
|
||||
@@ -2837,7 +2842,6 @@ namespace ts {
|
||||
// _super.call(this, a)
|
||||
// _super.m.call(this, a)
|
||||
// _super.prototype.m.call(this, a)
|
||||
|
||||
resultingCall = createFunctionCall(
|
||||
visitNode(target, visitor, isExpression),
|
||||
visitNode(thisArg, visitor, isExpression),
|
||||
|
||||
@@ -101,20 +101,21 @@ namespace ts {
|
||||
// So the helper will be emit at the correct position instead of at the top of the source-file
|
||||
const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions);
|
||||
const dependencies = createArrayLiteral(map(dependencyGroups, dependencyGroup => dependencyGroup.name));
|
||||
const updated = updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("System"), "register"),
|
||||
const updated = setEmitFlags(
|
||||
updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("System"), "register"),
|
||||
/*typeArguments*/ undefined,
|
||||
moduleName
|
||||
? [moduleName, dependencies, moduleBodyFunction]
|
||||
: [dependencies, moduleBodyFunction]
|
||||
moduleName
|
||||
? [moduleName, dependencies, moduleBodyFunction]
|
||||
: [dependencies, moduleBodyFunction]
|
||||
)
|
||||
)
|
||||
)
|
||||
], node.statements)
|
||||
);
|
||||
], node.statements)
|
||||
), EmitFlags.NoTrailingComments);
|
||||
|
||||
if (!(compilerOptions.outFile || compilerOptions.out)) {
|
||||
moveEmitHelpers(updated, moduleBodyBlock, helper => !helper.scoped);
|
||||
|
||||
@@ -1223,11 +1223,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
const { firstAccessor, secondAccessor, setAccessor } = getAllAccessorDeclarations(node.members, accessor);
|
||||
if (accessor !== firstAccessor) {
|
||||
const firstAccessorWithDecorators = firstAccessor.decorators ? firstAccessor : secondAccessor && secondAccessor.decorators ? secondAccessor : undefined;
|
||||
if (!firstAccessorWithDecorators || accessor !== firstAccessorWithDecorators) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const decorators = firstAccessor.decorators || (secondAccessor && secondAccessor.decorators);
|
||||
const decorators = firstAccessorWithDecorators.decorators;
|
||||
const parameters = getDecoratorsOfParameters(setAccessor);
|
||||
if (!decorators && !parameters) {
|
||||
return undefined;
|
||||
@@ -1276,7 +1277,7 @@ namespace ts {
|
||||
* @param node The declaration node.
|
||||
* @param allDecorators An object containing all of the decorators for the declaration.
|
||||
*/
|
||||
function transformAllDecoratorsOfDeclaration(node: Declaration, allDecorators: AllDecorators) {
|
||||
function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators) {
|
||||
if (!allDecorators) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1284,7 +1285,7 @@ namespace ts {
|
||||
const decoratorExpressions: Expression[] = [];
|
||||
addRange(decoratorExpressions, map(allDecorators.decorators, transformDecorator));
|
||||
addRange(decoratorExpressions, flatMap(allDecorators.parameters, transformDecoratorsOfParameter));
|
||||
addTypeMetadata(node, decoratorExpressions);
|
||||
addTypeMetadata(node, container, decoratorExpressions);
|
||||
return decoratorExpressions;
|
||||
}
|
||||
|
||||
@@ -1333,7 +1334,7 @@ namespace ts {
|
||||
*/
|
||||
function generateClassElementDecorationExpression(node: ClassExpression | ClassDeclaration, member: ClassElement) {
|
||||
const allDecorators = getAllDecoratorsOfClassElement(node, member);
|
||||
const decoratorExpressions = transformAllDecoratorsOfDeclaration(member, allDecorators);
|
||||
const decoratorExpressions = transformAllDecoratorsOfDeclaration(member, node, allDecorators);
|
||||
if (!decoratorExpressions) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1414,7 +1415,7 @@ namespace ts {
|
||||
*/
|
||||
function generateConstructorDecorationExpression(node: ClassExpression | ClassDeclaration) {
|
||||
const allDecorators = getAllDecoratorsOfConstructor(node);
|
||||
const decoratorExpressions = transformAllDecoratorsOfDeclaration(node, allDecorators);
|
||||
const decoratorExpressions = transformAllDecoratorsOfDeclaration(node, node, allDecorators);
|
||||
if (!decoratorExpressions) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1467,22 +1468,22 @@ namespace ts {
|
||||
* @param node The declaration node.
|
||||
* @param decoratorExpressions The destination array to which to add new decorator expressions.
|
||||
*/
|
||||
function addTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
function addTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
|
||||
if (USE_NEW_TYPE_METADATA_FORMAT) {
|
||||
addNewTypeMetadata(node, decoratorExpressions);
|
||||
addNewTypeMetadata(node, container, decoratorExpressions);
|
||||
}
|
||||
else {
|
||||
addOldTypeMetadata(node, decoratorExpressions);
|
||||
addOldTypeMetadata(node, container, decoratorExpressions);
|
||||
}
|
||||
}
|
||||
|
||||
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
function addOldTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:type", serializeTypeOfNode(node)));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:paramtypes", serializeParameterTypesOfNode(node, container)));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
@@ -1490,14 +1491,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function addNewTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
function addNewTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
let properties: ObjectLiteralElementLike[];
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node))));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node))));
|
||||
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node, container))));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
|
||||
@@ -1542,12 +1543,16 @@ namespace ts {
|
||||
* @param node The node to test.
|
||||
*/
|
||||
function shouldAddParamTypesMetadata(node: Declaration): boolean {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ClassDeclaration
|
||||
|| kind === SyntaxKind.ClassExpression
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
return getFirstConstructorWithBody(<ClassLikeDeclaration>node) !== undefined;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1572,30 +1577,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most likely element type for a TypeNode. This is not an exhaustive test
|
||||
* as it assumes a rest argument can only be an array type (either T[], or Array<T>).
|
||||
*
|
||||
* @param node The type node.
|
||||
*/
|
||||
function getRestParameterElementType(node: TypeNode) {
|
||||
if (node && node.kind === SyntaxKind.ArrayType) {
|
||||
return (<ArrayTypeNode>node).elementType;
|
||||
}
|
||||
else if (node && node.kind === SyntaxKind.TypeReference) {
|
||||
return singleOrUndefined((<TypeReferenceNode>node).typeArguments);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the types of the parameters of a node for use with decorator type metadata.
|
||||
*
|
||||
* @param node The node that should have its parameter types serialized.
|
||||
*/
|
||||
function serializeParameterTypesOfNode(node: Node): Expression {
|
||||
function serializeParameterTypesOfNode(node: Node, container: ClassLikeDeclaration): Expression {
|
||||
const valueDeclaration =
|
||||
isClassLike(node)
|
||||
? getFirstConstructorWithBody(node)
|
||||
@@ -1605,7 +1592,7 @@ namespace ts {
|
||||
|
||||
const expressions: Expression[] = [];
|
||||
if (valueDeclaration) {
|
||||
const parameters = valueDeclaration.parameters;
|
||||
const parameters = getParametersOfDecoratedDeclaration(valueDeclaration, container);
|
||||
const numParameters = parameters.length;
|
||||
for (let i = 0; i < numParameters; i++) {
|
||||
const parameter = parameters[i];
|
||||
@@ -1624,6 +1611,16 @@ namespace ts {
|
||||
return createArrayLiteral(expressions);
|
||||
}
|
||||
|
||||
function getParametersOfDecoratedDeclaration(node: FunctionLikeDeclaration, container: ClassLikeDeclaration) {
|
||||
if (container && node.kind === SyntaxKind.GetAccessor) {
|
||||
const { setAccessor } = getAllAccessorDeclarations(container.members, <AccessorDeclaration>node);
|
||||
if (setAccessor) {
|
||||
return setAccessor.parameters;
|
||||
}
|
||||
}
|
||||
return node.parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the return type of a node for use with decorator type metadata.
|
||||
*
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
"stripInternal": true,
|
||||
"target": "es5",
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
"noUnusedParameters": true,
|
||||
"types": [ ]
|
||||
},
|
||||
"files": [
|
||||
"core.ts",
|
||||
|
||||
+14
-3
@@ -2407,6 +2407,7 @@ namespace ts {
|
||||
writeSpace(text: string): void;
|
||||
writeStringLiteral(text: string): void;
|
||||
writeParameter(text: string): void;
|
||||
writeProperty(text: string): void;
|
||||
writeSymbol(text: string, symbol: Symbol): void;
|
||||
writeLine(): void;
|
||||
increaseIndent(): void;
|
||||
@@ -2908,6 +2909,8 @@ namespace ts {
|
||||
/* @internal */
|
||||
resolvedProperties: SymbolTable; // Cache of resolved properties
|
||||
/* @internal */
|
||||
resolvedIndexType: IndexType;
|
||||
/* @internal */
|
||||
couldContainTypeVariables: boolean;
|
||||
}
|
||||
|
||||
@@ -2930,6 +2933,7 @@ namespace ts {
|
||||
typeParameter?: TypeParameter;
|
||||
constraintType?: Type;
|
||||
templateType?: Type;
|
||||
modifiersType?: Type;
|
||||
mapper?: TypeMapper; // Instantiation mapper
|
||||
}
|
||||
|
||||
@@ -2965,6 +2969,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface TypeVariable extends Type {
|
||||
/* @internal */
|
||||
resolvedApparentType: Type;
|
||||
/* @internal */
|
||||
resolvedIndexType: IndexType;
|
||||
}
|
||||
@@ -2977,8 +2983,6 @@ namespace ts {
|
||||
/* @internal */
|
||||
mapper?: TypeMapper; // Instantiation mapper
|
||||
/* @internal */
|
||||
resolvedApparentType: Type;
|
||||
/* @internal */
|
||||
isThisType?: boolean;
|
||||
}
|
||||
|
||||
@@ -2987,11 +2991,12 @@ namespace ts {
|
||||
export interface IndexedAccessType extends TypeVariable {
|
||||
objectType: Type;
|
||||
indexType: Type;
|
||||
constraint?: Type;
|
||||
}
|
||||
|
||||
// keyof T types (TypeFlags.Index)
|
||||
export interface IndexType extends Type {
|
||||
type: TypeVariable;
|
||||
type: TypeVariable | UnionOrIntersectionType;
|
||||
}
|
||||
|
||||
export const enum SignatureKind {
|
||||
@@ -3083,6 +3088,12 @@ namespace ts {
|
||||
ThisProperty
|
||||
}
|
||||
|
||||
export interface FileExtensionInfo {
|
||||
extension: string;
|
||||
scriptKind: ScriptKind;
|
||||
isMixedContent: boolean;
|
||||
}
|
||||
|
||||
export interface DiagnosticMessage {
|
||||
key: string;
|
||||
category: DiagnosticCategory;
|
||||
|
||||
+18
-49
@@ -43,6 +43,7 @@ namespace ts {
|
||||
writeSpace: writeText,
|
||||
writeStringLiteral: writeText,
|
||||
writeParameter: writeText,
|
||||
writeProperty: writeText,
|
||||
writeSymbol: writeText,
|
||||
|
||||
// Completely ignore indentation for string writers. And map newlines to
|
||||
@@ -802,6 +803,23 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most likely element type for a TypeNode. This is not an exhaustive test
|
||||
* as it assumes a rest argument can only be an array type (either T[], or Array<T>).
|
||||
*
|
||||
* @param node The type node.
|
||||
*/
|
||||
export function getRestParameterElementType(node: TypeNode) {
|
||||
if (node && node.kind === SyntaxKind.ArrayType) {
|
||||
return (<ArrayTypeNode>node).elementType;
|
||||
}
|
||||
else if (node && node.kind === SyntaxKind.TypeReference) {
|
||||
return singleOrUndefined((<TypeReferenceNode>node).typeArguments);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function isVariableLike(node: Node): node is VariableLikeDeclaration {
|
||||
if (node) {
|
||||
@@ -3188,55 +3206,6 @@ namespace ts {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object graph into a JSON string. This is intended only for use on an acyclic graph
|
||||
* as the fallback implementation does not check for circular references by default.
|
||||
*/
|
||||
export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify
|
||||
? JSON.stringify
|
||||
: stringifyFallback;
|
||||
|
||||
/**
|
||||
* Serialize an object graph into a JSON string.
|
||||
*/
|
||||
function stringifyFallback(value: any): string {
|
||||
// JSON.stringify returns `undefined` here, instead of the string "undefined".
|
||||
return value === undefined ? undefined : stringifyValue(value);
|
||||
}
|
||||
|
||||
function stringifyValue(value: any): string {
|
||||
return typeof value === "string" ? `"${escapeString(value)}"`
|
||||
: typeof value === "number" ? isFinite(value) ? String(value) : "null"
|
||||
: typeof value === "boolean" ? value ? "true" : "false"
|
||||
: typeof value === "object" && value ? isArray(value) ? cycleCheck(stringifyArray, value) : cycleCheck(stringifyObject, value)
|
||||
: /*fallback*/ "null";
|
||||
}
|
||||
|
||||
function cycleCheck(cb: (value: any) => string, value: any) {
|
||||
Debug.assert(!value.hasOwnProperty("__cycle"), "Converting circular structure to JSON");
|
||||
value.__cycle = true;
|
||||
const result = cb(value);
|
||||
delete value.__cycle;
|
||||
return result;
|
||||
}
|
||||
|
||||
function stringifyArray(value: any) {
|
||||
return `[${reduceLeft(value, stringifyElement, "")}]`;
|
||||
}
|
||||
|
||||
function stringifyElement(memo: string, value: any) {
|
||||
return (memo ? memo + "," : memo) + stringifyValue(value);
|
||||
}
|
||||
|
||||
function stringifyObject(value: any) {
|
||||
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
|
||||
}
|
||||
|
||||
function stringifyProperty(memo: string, value: any, key: string) {
|
||||
return value === undefined || typeof value === "function" || key === "__cycle" ? memo
|
||||
: (memo ? memo + "," : memo) + `"${escapeString(key)}":${stringifyValue(value)}`;
|
||||
}
|
||||
|
||||
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user