mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #4910 from Microsoft/polymorphicThisType
Polymorphic 'this' type
This commit is contained in:
+12
-1
@@ -88,6 +88,7 @@ namespace ts {
|
||||
let container: Node;
|
||||
let blockScopeContainer: Node;
|
||||
let lastContainer: Node;
|
||||
let seenThisKeyword: boolean;
|
||||
|
||||
// If this file is an external module, then it is automatically in strict-mode according to
|
||||
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
|
||||
@@ -329,7 +330,14 @@ namespace ts {
|
||||
blockScopeContainer.locals = undefined;
|
||||
}
|
||||
|
||||
forEachChild(node, bind);
|
||||
if (node.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
seenThisKeyword = false;
|
||||
forEachChild(node, bind);
|
||||
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
|
||||
}
|
||||
else {
|
||||
forEachChild(node, bind);
|
||||
}
|
||||
|
||||
container = saveContainer;
|
||||
parent = saveParent;
|
||||
@@ -851,6 +859,9 @@ namespace ts {
|
||||
return checkStrictModePrefixUnaryExpression(<PrefixUnaryExpression>node);
|
||||
case SyntaxKind.WithStatement:
|
||||
return checkStrictModeWithStatement(<WithStatement>node);
|
||||
case SyntaxKind.ThisKeyword:
|
||||
seenThisKeyword = true;
|
||||
return;
|
||||
|
||||
case SyntaxKind.TypeParameter:
|
||||
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
|
||||
+259
-90
@@ -38,6 +38,7 @@ namespace ts {
|
||||
let Signature = objectAllocator.getSignatureConstructor();
|
||||
|
||||
let typeCount = 0;
|
||||
let symbolCount = 0;
|
||||
|
||||
let emptyArray: any[] = [];
|
||||
let emptySymbols: SymbolTable = {};
|
||||
@@ -54,7 +55,7 @@ namespace ts {
|
||||
let checker: TypeChecker = {
|
||||
getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
|
||||
getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
|
||||
getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount"),
|
||||
getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount,
|
||||
getTypeCount: () => typeCount,
|
||||
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
|
||||
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
|
||||
@@ -243,6 +244,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSymbol(flags: SymbolFlags, name: string): Symbol {
|
||||
symbolCount++;
|
||||
return new Symbol(flags, name);
|
||||
}
|
||||
|
||||
@@ -1587,6 +1589,7 @@ namespace ts {
|
||||
|
||||
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
let globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
|
||||
let inObjectTypeLiteral = false;
|
||||
return writeType(type, globalFlags);
|
||||
|
||||
function writeType(type: Type, flags: TypeFormatFlags) {
|
||||
@@ -1597,6 +1600,12 @@ namespace ts {
|
||||
? "any"
|
||||
: (<IntrinsicType>type).intrinsicName);
|
||||
}
|
||||
else if (type.flags & TypeFlags.ThisType) {
|
||||
if (inObjectTypeLiteral) {
|
||||
writer.reportInaccessibleThisError();
|
||||
}
|
||||
writer.writeKeyword("this");
|
||||
}
|
||||
else if (type.flags & TypeFlags.Reference) {
|
||||
writeTypeReference(<TypeReference>type, flags);
|
||||
}
|
||||
@@ -1640,11 +1649,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeSymbolTypeReference(symbol: Symbol, typeArguments: Type[], pos: number, end: number) {
|
||||
// Unnamed function expressions, arrow functions, and unnamed class expressions have reserved names that
|
||||
// we don't want to display
|
||||
if (!isReservedMemberName(symbol.name)) {
|
||||
buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type);
|
||||
function writeSymbolTypeReference(symbol: Symbol, typeArguments: Type[], pos: number, end: number, flags: TypeFormatFlags) {
|
||||
// Unnamed function expressions and arrow functions have reserved names that we don't want to display
|
||||
if (symbol.flags & SymbolFlags.Class || !isReservedMemberName(symbol.name)) {
|
||||
buildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
}
|
||||
if (pos < end) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
@@ -1659,7 +1667,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) {
|
||||
let typeArguments = type.typeArguments;
|
||||
let typeArguments = type.typeArguments || emptyArray;
|
||||
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
|
||||
writeType(typeArguments[0], TypeFormatFlags.InElementType);
|
||||
writePunctuation(writer, SyntaxKind.OpenBracketToken);
|
||||
@@ -1683,12 +1691,13 @@ namespace ts {
|
||||
// When type parameters are their own type arguments for the whole group (i.e. we have
|
||||
// the default outer type arguments), we don't show the group.
|
||||
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
|
||||
writeSymbolTypeReference(parent, typeArguments, start, i);
|
||||
writeSymbolTypeReference(parent, typeArguments, start, i, flags);
|
||||
writePunctuation(writer, SyntaxKind.DotToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
writeSymbolTypeReference(type.symbol, typeArguments, i, typeArguments.length);
|
||||
let typeParameterCount = (type.target.typeParameters || emptyArray).length;
|
||||
writeSymbolTypeReference(type.symbol, typeArguments, i, typeParameterCount, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1811,6 +1820,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
let saveInObjectTypeLiteral = inObjectTypeLiteral;
|
||||
inObjectTypeLiteral = true;
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
@@ -1883,6 +1894,7 @@ namespace ts {
|
||||
}
|
||||
writer.decreaseIndent();
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2884,6 +2896,31 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the interface given by the symbol is free of "this" references. Specifically, the result is
|
||||
// true if the interface itself contains no references to "this" in its body, if all base types are interfaces,
|
||||
// and if none of the base interfaces have a "this" type.
|
||||
function isIndependentInterface(symbol: Symbol): boolean {
|
||||
for (let declaration of symbol.declarations) {
|
||||
if (declaration.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
if (declaration.flags & NodeFlags.ContainsThis) {
|
||||
return false;
|
||||
}
|
||||
let baseTypeNodes = getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration);
|
||||
if (baseTypeNodes) {
|
||||
for (let node of baseTypeNodes) {
|
||||
if (isSupportedExpressionWithTypeArguments(node)) {
|
||||
let baseSymbol = resolveEntityName(node.expression, SymbolFlags.Type, /*ignoreErrors*/ true);
|
||||
if (!baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
|
||||
let links = getSymbolLinks(symbol);
|
||||
if (!links.declaredType) {
|
||||
@@ -2891,7 +2928,12 @@ namespace ts {
|
||||
let type = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
|
||||
let outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol);
|
||||
let localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
|
||||
if (outerTypeParameters || localTypeParameters) {
|
||||
// A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type
|
||||
// because it is not feasible to analyze all members to determine if the "this" type escapes the class (in particular,
|
||||
// property types inferred from initializers and method return types inferred from return statements are very hard
|
||||
// to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of
|
||||
// "this" references.
|
||||
if (outerTypeParameters || localTypeParameters || kind === TypeFlags.Class || !isIndependentInterface(symbol)) {
|
||||
type.flags |= TypeFlags.Reference;
|
||||
type.typeParameters = concatenate(outerTypeParameters, localTypeParameters);
|
||||
type.outerTypeParameters = outerTypeParameters;
|
||||
@@ -2900,6 +2942,9 @@ namespace ts {
|
||||
(<GenericType>type).instantiations[getTypeListId(type.typeParameters)] = <GenericType>type;
|
||||
(<GenericType>type).target = <GenericType>type;
|
||||
(<GenericType>type).typeArguments = type.typeParameters;
|
||||
type.thisType = <TypeParameter>createType(TypeFlags.TypeParameter | TypeFlags.ThisType);
|
||||
type.thisType.symbol = symbol;
|
||||
type.thisType.constraint = getTypeWithThisArgument(type);
|
||||
}
|
||||
}
|
||||
return <InterfaceType>links.declaredType;
|
||||
@@ -2984,6 +3029,82 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// A type reference is considered independent if each type argument is considered independent.
|
||||
function isIndependentTypeReference(node: TypeReferenceNode): boolean {
|
||||
if (node.typeArguments) {
|
||||
for (let typeNode of node.typeArguments) {
|
||||
if (!isIndependentType(typeNode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// A type is considered independent if it the any, string, number, boolean, symbol, or void keyword, a string
|
||||
// literal type, an array with an element type that is considered independent, or a type reference that is
|
||||
// considered independent.
|
||||
function isIndependentType(node: TypeNode): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.NumberKeyword:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return true;
|
||||
case SyntaxKind.ArrayType:
|
||||
return isIndependentType((<ArrayTypeNode>node).elementType);
|
||||
case SyntaxKind.TypeReference:
|
||||
return isIndependentTypeReference(<TypeReferenceNode>node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// A variable-like declaration is considered independent (free of this references) if it has a type annotation
|
||||
// that specifies an independent type, or if it has no type annotation and no initializer (and thus of type any).
|
||||
function isIndependentVariableLikeDeclaration(node: VariableLikeDeclaration): boolean {
|
||||
return node.type && isIndependentType(node.type) || !node.type && !node.initializer;
|
||||
}
|
||||
|
||||
// A function-like declaration is considered independent (free of this references) if it has a return type
|
||||
// annotation that is considered independent and if each parameter is considered independent.
|
||||
function isIndependentFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
|
||||
if (node.kind !== SyntaxKind.Constructor && (!node.type || !isIndependentType(node.type))) {
|
||||
return false;
|
||||
}
|
||||
for (let parameter of node.parameters) {
|
||||
if (!isIndependentVariableLikeDeclaration(parameter)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the class or interface member given by the symbol is free of "this" references. The
|
||||
// function may return false for symbols that are actually free of "this" references because it is not
|
||||
// feasible to perform a complete analysis in all cases. In particular, property members with types
|
||||
// inferred from their initializers and function members with inferred return types are convervatively
|
||||
// assumed not to be free of "this" references.
|
||||
function isIndependentMember(symbol: Symbol): boolean {
|
||||
if (symbol.declarations && symbol.declarations.length === 1) {
|
||||
let declaration = symbol.declarations[0];
|
||||
if (declaration) {
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
return isIndependentVariableLikeDeclaration(<VariableLikeDeclaration>declaration);
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.Constructor:
|
||||
return isIndependentFunctionLikeDeclaration(<FunctionLikeDeclaration>declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createSymbolTable(symbols: Symbol[]): SymbolTable {
|
||||
let result: SymbolTable = {};
|
||||
for (let symbol of symbols) {
|
||||
@@ -2992,10 +3113,12 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper): SymbolTable {
|
||||
// The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true,
|
||||
// we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation.
|
||||
function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper, mappingThisOnly: boolean): SymbolTable {
|
||||
let result: SymbolTable = {};
|
||||
for (let symbol of symbols) {
|
||||
result[symbol.name] = instantiateSymbol(symbol, mapper);
|
||||
result[symbol.name] = mappingThisOnly && isIndependentMember(symbol) ? symbol : instantiateSymbol(symbol, mapper);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -3028,44 +3151,57 @@ namespace ts {
|
||||
return <InterfaceTypeWithDeclaredMembers>type;
|
||||
}
|
||||
|
||||
function resolveClassOrInterfaceMembers(type: InterfaceType): void {
|
||||
let target = resolveDeclaredMembers(type);
|
||||
let members = target.symbol.members;
|
||||
let callSignatures = target.declaredCallSignatures;
|
||||
let constructSignatures = target.declaredConstructSignatures;
|
||||
let stringIndexType = target.declaredStringIndexType;
|
||||
let numberIndexType = target.declaredNumberIndexType;
|
||||
let baseTypes = getBaseTypes(target);
|
||||
function getTypeWithThisArgument(type: ObjectType, thisArgument?: Type) {
|
||||
if (type.flags & TypeFlags.Reference) {
|
||||
return createTypeReference((<TypeReference>type).target,
|
||||
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: TypeParameter[], typeArguments: Type[]) {
|
||||
let mapper = identityMapper;
|
||||
let members = source.symbol.members;
|
||||
let callSignatures = source.declaredCallSignatures;
|
||||
let constructSignatures = source.declaredConstructSignatures;
|
||||
let stringIndexType = source.declaredStringIndexType;
|
||||
let numberIndexType = source.declaredNumberIndexType;
|
||||
if (!rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) {
|
||||
mapper = createTypeMapper(typeParameters, typeArguments);
|
||||
members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
|
||||
callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature);
|
||||
constructSignatures = instantiateList(source.declaredConstructSignatures, mapper, instantiateSignature);
|
||||
stringIndexType = source.declaredStringIndexType ? instantiateType(source.declaredStringIndexType, mapper) : undefined;
|
||||
numberIndexType = source.declaredNumberIndexType ? instantiateType(source.declaredNumberIndexType, mapper) : undefined;
|
||||
}
|
||||
let baseTypes = getBaseTypes(source);
|
||||
if (baseTypes.length) {
|
||||
members = createSymbolTable(target.declaredProperties);
|
||||
if (members === source.symbol.members) {
|
||||
members = createSymbolTable(source.declaredProperties);
|
||||
}
|
||||
let thisArgument = lastOrUndefined(typeArguments);
|
||||
for (let baseType of baseTypes) {
|
||||
addInheritedMembers(members, getPropertiesOfObjectType(baseType));
|
||||
callSignatures = concatenate(callSignatures, getSignaturesOfType(baseType, SignatureKind.Call));
|
||||
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(baseType, SignatureKind.Construct));
|
||||
stringIndexType = stringIndexType || getIndexTypeOfType(baseType, IndexKind.String);
|
||||
numberIndexType = numberIndexType || getIndexTypeOfType(baseType, IndexKind.Number);
|
||||
let instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
|
||||
addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
|
||||
callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
|
||||
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
|
||||
stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.String);
|
||||
numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.Number);
|
||||
}
|
||||
}
|
||||
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||
}
|
||||
|
||||
function resolveClassOrInterfaceMembers(type: InterfaceType): void {
|
||||
resolveObjectTypeMembers(type, resolveDeclaredMembers(type), emptyArray, emptyArray);
|
||||
}
|
||||
|
||||
function resolveTypeReferenceMembers(type: TypeReference): void {
|
||||
let target = resolveDeclaredMembers(type.target);
|
||||
let mapper = createTypeMapper(target.typeParameters, type.typeArguments);
|
||||
let members = createInstantiatedSymbolTable(target.declaredProperties, mapper);
|
||||
let callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature);
|
||||
let constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
|
||||
let stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
|
||||
let numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
|
||||
forEach(getBaseTypes(target), baseType => {
|
||||
let instantiatedBaseType = instantiateType(baseType, mapper);
|
||||
addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
|
||||
callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
|
||||
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
|
||||
stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.String);
|
||||
numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.Number);
|
||||
});
|
||||
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||
let source = resolveDeclaredMembers(type.target);
|
||||
let typeParameters = concatenate(source.typeParameters, [source.thisType]);
|
||||
let typeArguments = type.typeArguments && type.typeArguments.length === typeParameters.length ?
|
||||
type.typeArguments : concatenate(type.typeArguments, [type]);
|
||||
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
|
||||
}
|
||||
|
||||
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[],
|
||||
@@ -3120,7 +3256,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function resolveTupleTypeMembers(type: TupleType) {
|
||||
let arrayType = resolveStructuredTypeMembers(createArrayType(getUnionType(type.elementTypes, /*noSubtypeReduction*/ true)));
|
||||
let arrayElementType = getUnionType(type.elementTypes, /*noSubtypeReduction*/ true);
|
||||
// Make the tuple type itself the 'this' type by including an extra type argument
|
||||
let arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, type]));
|
||||
let members = createTupleTypeMemberSymbols(type.elementTypes);
|
||||
addInheritedMembers(members, arrayType.properties);
|
||||
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
||||
@@ -3279,7 +3417,10 @@ namespace ts {
|
||||
|
||||
function resolveStructuredTypeMembers(type: ObjectType): ResolvedType {
|
||||
if (!(<ResolvedType>type).members) {
|
||||
if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
if (type.flags & TypeFlags.Reference) {
|
||||
resolveTypeReferenceMembers(<TypeReference>type);
|
||||
}
|
||||
else if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
resolveClassOrInterfaceMembers(<InterfaceType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Anonymous) {
|
||||
@@ -3294,9 +3435,6 @@ namespace ts {
|
||||
else if (type.flags & TypeFlags.Intersection) {
|
||||
resolveIntersectionTypeMembers(<IntersectionType>type);
|
||||
}
|
||||
else {
|
||||
resolveTypeReferenceMembers(<TypeReference>type);
|
||||
}
|
||||
}
|
||||
return <ResolvedType>type;
|
||||
}
|
||||
@@ -3762,22 +3900,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTypeListId(types: Type[]) {
|
||||
switch (types.length) {
|
||||
case 1:
|
||||
return "" + types[0].id;
|
||||
case 2:
|
||||
return types[0].id + "," + types[1].id;
|
||||
default:
|
||||
let result = "";
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (i > 0) {
|
||||
result += ",";
|
||||
if (types) {
|
||||
switch (types.length) {
|
||||
case 1:
|
||||
return "" + types[0].id;
|
||||
case 2:
|
||||
return types[0].id + "," + types[1].id;
|
||||
default:
|
||||
let result = "";
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (i > 0) {
|
||||
result += ",";
|
||||
}
|
||||
result += types[i].id;
|
||||
}
|
||||
|
||||
result += types[i].id;
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// This function is used to propagate certain flags when creating new object type references and union types.
|
||||
@@ -3796,7 +3936,7 @@ namespace ts {
|
||||
let id = getTypeListId(typeArguments);
|
||||
let type = target.instantiations[id];
|
||||
if (!type) {
|
||||
let flags = TypeFlags.Reference | getPropagatingFlagsOfTypes(typeArguments);
|
||||
let flags = TypeFlags.Reference | (typeArguments ? getPropagatingFlagsOfTypes(typeArguments) : 0);
|
||||
type = target.instantiations[id] = <TypeReference>createObjectType(flags, target.symbol);
|
||||
type.target = target;
|
||||
type.typeArguments = typeArguments;
|
||||
@@ -3855,8 +3995,8 @@ namespace ts {
|
||||
|
||||
// Get type from reference to class or interface
|
||||
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments, symbol: Symbol): Type {
|
||||
let type = getDeclaredTypeOfSymbol(symbol);
|
||||
let typeParameters = (<InterfaceType>type).localTypeParameters;
|
||||
let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
|
||||
let typeParameters = type.localTypeParameters;
|
||||
if (typeParameters) {
|
||||
if (!node.typeArguments || node.typeArguments.length !== typeParameters.length) {
|
||||
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
|
||||
@@ -3865,8 +4005,7 @@ namespace ts {
|
||||
// In a type reference, the outer type parameters of the referenced class or interface are automatically
|
||||
// supplied as type arguments and the type reference only specifies arguments for the local type parameters
|
||||
// of the class or interface.
|
||||
return createTypeReference(<GenericType>type, concatenate((<InterfaceType>type).outerTypeParameters,
|
||||
map(node.typeArguments, getTypeFromTypeNode)));
|
||||
return createTypeReference(<GenericType>type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNode)));
|
||||
}
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
|
||||
@@ -4022,20 +4161,20 @@ namespace ts {
|
||||
/**
|
||||
* Instantiates a global type that is generic with some element type, and returns that instantiation.
|
||||
*/
|
||||
function createTypeFromGenericGlobalType(genericGlobalType: GenericType, elementType: Type): Type {
|
||||
return <ObjectType>genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, [elementType]) : emptyObjectType;
|
||||
function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: Type[]): Type {
|
||||
return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType;
|
||||
}
|
||||
|
||||
function createIterableType(elementType: Type): Type {
|
||||
return createTypeFromGenericGlobalType(globalIterableType, elementType);
|
||||
return createTypeFromGenericGlobalType(globalIterableType, [elementType]);
|
||||
}
|
||||
|
||||
function createIterableIteratorType(elementType: Type): Type {
|
||||
return createTypeFromGenericGlobalType(globalIterableIteratorType, elementType);
|
||||
return createTypeFromGenericGlobalType(globalIterableIteratorType, [elementType]);
|
||||
}
|
||||
|
||||
function createArrayType(elementType: Type): Type {
|
||||
return createTypeFromGenericGlobalType(globalArrayType, elementType);
|
||||
return createTypeFromGenericGlobalType(globalArrayType, [elementType]);
|
||||
}
|
||||
|
||||
function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
|
||||
@@ -4224,6 +4363,26 @@ namespace ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getThisType(node: TypeNode): Type {
|
||||
let container = getThisContainer(node, /*includeArrowFunctions*/ false);
|
||||
let parent = container && container.parent;
|
||||
if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) {
|
||||
if (!(container.flags & NodeFlags.Static)) {
|
||||
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType;
|
||||
}
|
||||
}
|
||||
error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface);
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function getTypeFromThisTypeNode(node: TypeNode): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getThisType(node);
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getTypeFromTypeNode(node: TypeNode): Type {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
@@ -4238,6 +4397,8 @@ namespace ts {
|
||||
return esSymbolType;
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return voidType;
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return getTypeFromThisTypeNode(node);
|
||||
case SyntaxKind.StringLiteral:
|
||||
return getTypeFromStringLiteral(<StringLiteral>node);
|
||||
case SyntaxKind.TypeReference:
|
||||
@@ -4692,7 +4853,7 @@ namespace ts {
|
||||
else {
|
||||
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if relationship holds for all type arguments
|
||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
||||
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -4723,7 +4884,7 @@ namespace ts {
|
||||
if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
|
||||
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if all type arguments are identical
|
||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, /*reportErrors*/ false)) {
|
||||
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, /*reportErrors*/ false)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -4845,9 +5006,14 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function typesRelatedTo(sources: Type[], targets: Type[], reportErrors: boolean): Ternary {
|
||||
function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, reportErrors: boolean): Ternary {
|
||||
let sources = source.typeArguments || emptyArray;
|
||||
let targets = target.typeArguments || emptyArray;
|
||||
if (sources.length !== targets.length && relation === identityRelation) {
|
||||
return Ternary.False;
|
||||
}
|
||||
let result = Ternary.True;
|
||||
for (let i = 0, len = sources.length; i < len; i++) {
|
||||
for (let i = 0; i < targets.length; i++) {
|
||||
let related = isRelatedTo(sources[i], targets[i], reportErrors);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
@@ -5746,9 +5912,10 @@ namespace ts {
|
||||
}
|
||||
else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// If source and target are references to the same generic type, infer from type arguments
|
||||
let sourceTypes = (<TypeReference>source).typeArguments;
|
||||
let targetTypes = (<TypeReference>target).typeArguments;
|
||||
for (let i = 0; i < sourceTypes.length; i++) {
|
||||
let sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
|
||||
let targetTypes = (<TypeReference>target).typeArguments || emptyArray;
|
||||
let count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length;
|
||||
for (let i = 0; i < count; i++) {
|
||||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
}
|
||||
@@ -6450,7 +6617,7 @@ namespace ts {
|
||||
|
||||
if (isClassLike(container.parent)) {
|
||||
let symbol = getSymbolOfNode(container.parent);
|
||||
return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol);
|
||||
return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
|
||||
}
|
||||
return anyType;
|
||||
}
|
||||
@@ -7837,7 +8004,7 @@ namespace ts {
|
||||
let prop = getPropertyOfType(apparentType, right.text);
|
||||
if (!prop) {
|
||||
if (right.text) {
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type.flags & TypeFlags.ThisType ? apparentType : type));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
@@ -7845,7 +8012,7 @@ namespace ts {
|
||||
getNodeLinks(node).resolvedSymbol = prop;
|
||||
|
||||
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
||||
checkClassPropertyAccess(node, left, type, prop);
|
||||
checkClassPropertyAccess(node, left, apparentType, prop);
|
||||
}
|
||||
return getTypeOfSymbol(prop);
|
||||
}
|
||||
@@ -12649,6 +12816,7 @@ namespace ts {
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
let symbol = getSymbolOfNode(node);
|
||||
let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
|
||||
let typeWithThis = getTypeWithThisArgument(type);
|
||||
let staticType = <ObjectType>getTypeOfSymbol(symbol);
|
||||
|
||||
let baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
@@ -12667,7 +12835,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
checkTypeAssignableTo(type, baseType, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
|
||||
@@ -12687,7 +12855,7 @@ namespace ts {
|
||||
|
||||
let implementedTypeNodes = getClassImplementsHeritageClauseElements(node);
|
||||
if (implementedTypeNodes) {
|
||||
forEach(implementedTypeNodes, typeRefNode => {
|
||||
for (let typeRefNode of implementedTypeNodes) {
|
||||
if (!isSupportedExpressionWithTypeArguments(typeRefNode)) {
|
||||
error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
|
||||
}
|
||||
@@ -12697,14 +12865,14 @@ namespace ts {
|
||||
if (t !== unknownType) {
|
||||
let declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
|
||||
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
checkTypeAssignableTo(type, t, node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
|
||||
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(t, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
|
||||
}
|
||||
else {
|
||||
error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (produceDiagnostics) {
|
||||
@@ -12864,7 +13032,7 @@ namespace ts {
|
||||
let ok = true;
|
||||
|
||||
for (let base of baseTypes) {
|
||||
let properties = getPropertiesOfObjectType(base);
|
||||
let properties = getPropertiesOfObjectType(getTypeWithThisArgument(base, type.thisType));
|
||||
for (let prop of properties) {
|
||||
if (!hasProperty(seen, prop.name)) {
|
||||
seen[prop.name] = { prop: prop, containingType: base };
|
||||
@@ -12909,11 +13077,12 @@ namespace ts {
|
||||
// Only check this symbol once
|
||||
if (node === firstInterfaceDecl) {
|
||||
let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
|
||||
let typeWithThis = getTypeWithThisArgument(type);
|
||||
// run subsequent checks only if first set succeeded
|
||||
if (checkInheritedPropertiesAreIdentical(type, node.name)) {
|
||||
forEach(getBaseTypes(type), baseType => {
|
||||
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
|
||||
});
|
||||
for (let baseType of getBaseTypes(type)) {
|
||||
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
|
||||
}
|
||||
checkIndexConstraints(type);
|
||||
}
|
||||
}
|
||||
@@ -14146,7 +14315,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
let type = checkExpression(<Expression>node);
|
||||
let type = isExpression(node) ? checkExpression(<Expression>node) : getTypeFromTypeNode(<TypeNode>node);
|
||||
return type.symbol;
|
||||
|
||||
case SyntaxKind.ConstructorKeyword:
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace ts {
|
||||
let enclosingDeclaration: Node;
|
||||
let currentSourceFile: SourceFile;
|
||||
let reportedDeclarationError = false;
|
||||
let errorNameNode: DeclarationName;
|
||||
let emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
|
||||
let emit = compilerOptions.stripInternal ? stripInternal : emitNode;
|
||||
|
||||
@@ -152,6 +153,7 @@ namespace ts {
|
||||
function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
|
||||
let writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
|
||||
writer.trackSymbol = trackSymbol;
|
||||
writer.reportInaccessibleThisError = reportInaccessibleThisError;
|
||||
writer.writeKeyword = writer.write;
|
||||
writer.writeOperator = writer.write;
|
||||
writer.writePunctuation = writer.write;
|
||||
@@ -257,6 +259,13 @@ namespace ts {
|
||||
handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
|
||||
}
|
||||
|
||||
function reportInaccessibleThisError() {
|
||||
if (errorNameNode) {
|
||||
diagnostics.push(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary,
|
||||
declarationNameToString(errorNameNode)));
|
||||
}
|
||||
}
|
||||
|
||||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
|
||||
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
|
||||
write(": ");
|
||||
@@ -265,7 +274,9 @@ namespace ts {
|
||||
emitType(type);
|
||||
}
|
||||
else {
|
||||
errorNameNode = declaration.name;
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +288,9 @@ namespace ts {
|
||||
emitType(signature.type);
|
||||
}
|
||||
else {
|
||||
errorNameNode = signature.name;
|
||||
resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +339,7 @@ namespace ts {
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return writeTextOfNode(currentSourceFile, type);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
|
||||
@@ -1652,6 +1652,14 @@
|
||||
"category": "Error",
|
||||
"code": 2525
|
||||
},
|
||||
"A 'this' type is available only in a non-static member of a class or interface.": {
|
||||
"category": "Error",
|
||||
"code": 2526
|
||||
},
|
||||
"The inferred type of '{0}' references an inaccessible 'this' type. A type annotation is necessary.": {
|
||||
"category": "Error",
|
||||
"code": 2527
|
||||
},
|
||||
"JSX element attributes type '{0}' must be an object type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
|
||||
@@ -2360,6 +2360,7 @@ namespace ts {
|
||||
let node = tryParse(parseKeywordAndNoDot);
|
||||
return node || parseTypeReferenceOrTypePredicate();
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return parseTokenNode<TypeNode>();
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
return parseTypeQuery();
|
||||
@@ -2382,6 +2383,7 @@ namespace ts {
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
case SyntaxKind.OpenBracketToken:
|
||||
|
||||
+13
-2
@@ -376,6 +376,7 @@ namespace ts {
|
||||
OctalLiteral = 0x00010000, // Octal numeric literal
|
||||
Namespace = 0x00020000, // Namespace declaration
|
||||
ExportContext = 0x00040000, // Export context (initialized by binding)
|
||||
ContainsThis = 0x00080000, // Interface contains references to "this"
|
||||
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async,
|
||||
AccessibilityModifier = Public | Private | Protected,
|
||||
@@ -1496,6 +1497,7 @@ namespace ts {
|
||||
// declaration emitter to help determine if it should patch up the final declaration file
|
||||
// with import statements it previously saw (but chose not to emit).
|
||||
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
reportInaccessibleThisError(): void;
|
||||
}
|
||||
|
||||
export const enum TypeFormatFlags {
|
||||
@@ -1797,6 +1799,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 0x00800000, // Type is or contains object literal type
|
||||
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
|
||||
ThisType = 0x02000000, // This type
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
@@ -1842,6 +1845,7 @@ namespace ts {
|
||||
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
|
||||
outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none)
|
||||
localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none)
|
||||
thisType: TypeParameter; // The "this" type (undefined if none)
|
||||
/* @internal */
|
||||
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
|
||||
/* @internal */
|
||||
@@ -1856,10 +1860,17 @@ namespace ts {
|
||||
declaredNumberIndexType: Type; // Declared numeric index type
|
||||
}
|
||||
|
||||
// Type references (TypeFlags.Reference)
|
||||
// Type references (TypeFlags.Reference). When a class or interface has type parameters or
|
||||
// a "this" type, references to the class or interface are made using type references. The
|
||||
// typeArguments property specififes the types to substitute for the type parameters of the
|
||||
// class or interface and optionally includes an extra element that specifies the type to
|
||||
// substitute for "this" in the resulting instantiation. When no extra argument is present,
|
||||
// the type reference itself is substituted for "this". The typeArguments property is undefined
|
||||
// if the class or interface has no type parameters and the reference isn't specifying an
|
||||
// explicit "this" argument.
|
||||
export interface TypeReference extends ObjectType {
|
||||
target: GenericType; // Type reference target
|
||||
typeArguments: Type[]; // Type reference type arguments
|
||||
typeArguments: Type[]; // Type reference type arguments (undefined if none)
|
||||
}
|
||||
|
||||
// Generic class and interface types
|
||||
|
||||
@@ -65,7 +65,8 @@ namespace ts {
|
||||
increaseIndent: () => { },
|
||||
decreaseIndent: () => { },
|
||||
clear: () => str = "",
|
||||
trackSymbol: () => { }
|
||||
trackSymbol: () => { },
|
||||
reportInaccessibleThisError: () => { }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -468,13 +469,12 @@ namespace ts {
|
||||
else if (node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node) {
|
||||
node = node.parent;
|
||||
}
|
||||
// fall through
|
||||
case SyntaxKind.QualifiedName:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
// At this point, node is either a qualified name or an identifier
|
||||
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression,
|
||||
"'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'.");
|
||||
|
||||
case SyntaxKind.QualifiedName:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
let parent = node.parent;
|
||||
if (parent.kind === SyntaxKind.TypeQuery) {
|
||||
return false;
|
||||
@@ -733,6 +733,9 @@ namespace ts {
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.SourceFile:
|
||||
return node;
|
||||
@@ -895,7 +898,6 @@ namespace ts {
|
||||
|
||||
export function isExpression(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
@@ -928,6 +930,7 @@ namespace ts {
|
||||
case SyntaxKind.JsxElement:
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.YieldExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return true;
|
||||
case SyntaxKind.QualifiedName:
|
||||
while (node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
@@ -941,6 +944,7 @@ namespace ts {
|
||||
// fall through
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
let parent = node.parent;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace ts {
|
||||
}
|
||||
getBaseTypes(): ObjectType[] {
|
||||
return this.flags & (TypeFlags.Class | TypeFlags.Interface)
|
||||
? this.checker.getBaseTypes(<TypeObject & InterfaceType>this)
|
||||
? this.checker.getBaseTypes(<InterfaceType><Type>this)
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
@@ -6252,7 +6252,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
return node.parent.kind === SyntaxKind.TypeReference ||
|
||||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent));
|
||||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent)) ||
|
||||
node.kind === SyntaxKind.ThisKeyword && !isExpression(node);
|
||||
}
|
||||
|
||||
function isNamespaceReference(node: Node): boolean {
|
||||
|
||||
@@ -636,7 +636,8 @@ namespace ts {
|
||||
increaseIndent: () => { indent++; },
|
||||
decreaseIndent: () => { indent--; },
|
||||
clear: resetWriter,
|
||||
trackSymbol: () => { }
|
||||
trackSymbol: () => { },
|
||||
reportInaccessibleThisError: () => { }
|
||||
};
|
||||
|
||||
function writeIndent() {
|
||||
|
||||
Reference in New Issue
Block a user