use NodeBuilderContext
This commit is contained in:
parent
85986ddaee
commit
a94f874b06
|
@ -2204,369 +2204,403 @@ namespace ts {
|
||||||
|
|
||||||
function createNodeBuilder(): NodeBuilder {
|
function createNodeBuilder(): NodeBuilder {
|
||||||
|
|
||||||
let encounteredError = false;
|
interface NodeBuilderContext {
|
||||||
|
readonly enclosingDeclaration: Node | undefined;
|
||||||
|
readonly flags: NodeBuilderFlags | undefined;
|
||||||
|
encounteredError: boolean;
|
||||||
|
inObjectTypeLiteral: boolean;
|
||||||
|
checkAlias: boolean;
|
||||||
|
symbolStack: Symbol[] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeBuilderContext {
|
||||||
|
return {
|
||||||
|
enclosingDeclaration,
|
||||||
|
flags,
|
||||||
|
encounteredError: false,
|
||||||
|
inObjectTypeLiteral: false,
|
||||||
|
checkAlias: true,
|
||||||
|
symbolStack: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let context: NodeBuilderContext;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
Debug.assert(encounteredError === false, "Nested call into nodeBuilder are forbidden.");
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
encounteredError = false;
|
const resultingNode = typeToTypeNodeHelper(type);
|
||||||
const resultingNode = typeToTypeNodeHelper(type, enclosingDeclaration, flags);
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
const result = encounteredError ? undefined : resultingNode;
|
|
||||||
encounteredError = false;
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
Debug.assert(encounteredError === false, "Nested call into nodeBuilder are forbidden.");
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
encounteredError = false;
|
const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind);
|
||||||
const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, enclosingDeclaration, flags);
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
const result = encounteredError ? undefined : resultingNode;
|
|
||||||
encounteredError = false;
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
Debug.assert(encounteredError === false, "Nested call into nodeBuilder are forbidden.");
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
encounteredError = false;
|
const resultingNode = signatureToSignatureDeclarationHelper(signature, kind);
|
||||||
const resultingNode = signatureToSignatureDeclarationHelper(signature, kind, enclosingDeclaration, flags);
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
const result = encounteredError ? undefined : resultingNode;
|
|
||||||
encounteredError = false;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function typeToTypeNodeHelper(type: Type, enclosingDeclaration: Node, flags: NodeBuilderFlags): TypeNode {
|
function typeToTypeNodeHelper(type: Type): TypeNode {
|
||||||
let inObjectTypeLiteral = false;
|
if (!type) {
|
||||||
let checkAlias = true;
|
context.encounteredError = true;
|
||||||
let symbolStack: Symbol[] = undefined;
|
// TODO(aozgaa): should we return implict any (undefined) or explicit any (keywordtypenode)?
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return typeToTypeNodeWorker(type);
|
if (type.flags & TypeFlags.Any) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.String) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.StringKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Number) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NumberKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Boolean) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.BooleanKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Enum) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & (TypeFlags.StringLiteral)) {
|
||||||
|
return createLiteralTypeNode((createLiteral((<LiteralType>type).text)));
|
||||||
|
}
|
||||||
|
if (type.flags & (TypeFlags.NumberLiteral)) {
|
||||||
|
return createLiteralTypeNode((createNumericLiteral((<LiteralType>type).text)));
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.BooleanLiteral) {
|
||||||
|
return (<IntrinsicType>type).intrinsicName === "true" ? createTrue() : createFalse();
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.EnumLiteral) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Void) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Undefined) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Null) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NullKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Never) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NeverKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.ESSymbol) {
|
||||||
|
throw new Error("ESSymbol not implemented");
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.NonPrimitive) {
|
||||||
|
throw new Error("Non primitive not implemented");
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) {
|
||||||
|
if (context.inObjectTypeLiteral) {
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowThisInObjectLiteral)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createThis();
|
||||||
|
}
|
||||||
|
|
||||||
function typeToTypeNodeWorker(type: Type): TypeNode {
|
const objectFlags = getObjectFlags(type);
|
||||||
if (!type) {
|
|
||||||
encounteredError = true;
|
if (objectFlags & ObjectFlags.Reference) {
|
||||||
// TODO(aozgaa): should we return implict any (undefined) or explicit any (keywordtypenode)?
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
return typeReferenceToTypeNode(<TypeReference>type);
|
||||||
|
}
|
||||||
|
if (objectFlags & ObjectFlags.ClassOrInterface) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
// TODO(aozgaa): handle type arguments.
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.TypeParameter) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.checkAlias && type.aliasSymbol) {
|
||||||
|
const name = symbolToName(type.aliasSymbol, /*expectsIdentifier*/ false);
|
||||||
|
const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments);
|
||||||
|
return createTypeReferenceNode(name, typeArgumentNodes);
|
||||||
|
}
|
||||||
|
context.checkAlias = false;
|
||||||
|
|
||||||
|
if (type.flags & TypeFlags.Union) {
|
||||||
|
const formattedUnionTypes = formatUnionTypes((<UnionType>type).types);
|
||||||
|
const unionTypeNodes = formattedUnionTypes && mapToTypeNodeArray(formattedUnionTypes);
|
||||||
|
if (unionTypeNodes && unionTypeNodes.length > 0) {
|
||||||
|
return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, unionTypeNodes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyUnionOrIntersection)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (type.flags & TypeFlags.Any) {
|
if (type.flags & TypeFlags.Intersection) {
|
||||||
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, mapToTypeNodeArray((type as UnionType).types));
|
||||||
}
|
}
|
||||||
if (type.flags & TypeFlags.String) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.StringKeyword);
|
if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
|
||||||
}
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
if (type.flags & TypeFlags.Number) {
|
// The type is an object literal type.
|
||||||
return createKeywordTypeNode(SyntaxKind.NumberKeyword);
|
return createAnonymousTypeNode(<ObjectType>type);
|
||||||
}
|
}
|
||||||
if (type.flags & TypeFlags.Boolean) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.BooleanKeyword);
|
if (type.flags & TypeFlags.Index) {
|
||||||
}
|
const indexedType = (<IndexType>type).type;
|
||||||
if (type.flags & TypeFlags.Enum) {
|
const indexTypeNode = typeToTypeNodeHelper(indexedType);
|
||||||
const name = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
return createTypeOperatorNode(indexTypeNode);
|
||||||
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
}
|
||||||
}
|
if (type.flags & TypeFlags.IndexedAccess) {
|
||||||
if (type.flags & (TypeFlags.StringLiteral)) {
|
const objectTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).objectType);
|
||||||
return createLiteralTypeNode((createLiteral((<LiteralType>type).text)));
|
const indexTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).indexType);
|
||||||
}
|
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
|
||||||
if (type.flags & (TypeFlags.NumberLiteral)) {
|
}
|
||||||
return createLiteralTypeNode((createNumericLiteral((<LiteralType>type).text)));
|
|
||||||
}
|
Debug.fail("Should be unreachable.");
|
||||||
if (type.flags & TypeFlags.BooleanLiteral) {
|
|
||||||
return (<IntrinsicType>type).intrinsicName === "true" ? createTrue() : createFalse();
|
function mapToTypeNodeArray(types: Type[]): TypeNode[] {
|
||||||
}
|
const result = [];
|
||||||
if (type.flags & TypeFlags.EnumLiteral) {
|
for (const type of types) {
|
||||||
const name = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
const typeNode = typeToTypeNodeHelper(type);
|
||||||
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
if (typeNode) {
|
||||||
}
|
result.push(typeNode);
|
||||||
if (type.flags & TypeFlags.Void) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.Undefined) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.Null) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.NullKeyword);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.Never) {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.NeverKeyword);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.ESSymbol) {
|
|
||||||
throw new Error("ESSymbol not implemented");
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.NonPrimitive) {
|
|
||||||
throw new Error("Non primitive not implemented");
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) {
|
|
||||||
if (inObjectTypeLiteral) {
|
|
||||||
encounteredError = encounteredError || !(flags & NodeBuilderFlags.allowThisInObjectLiteral);
|
|
||||||
}
|
}
|
||||||
return createThis();
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const objectFlags = getObjectFlags(type);
|
function createMappedTypeNodeFromType(type: MappedType) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
const typeParameter = getTypeParameterFromMappedType(<MappedType>type);
|
||||||
|
const typeParameterNode = typeParameterToDeclaration(typeParameter);
|
||||||
|
|
||||||
if (objectFlags & ObjectFlags.Reference) {
|
const templateType = getTemplateTypeFromMappedType(<MappedType>type);
|
||||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
const templateTypeNode = templateType && typeToTypeNodeHelper(templateType);
|
||||||
return typeReferenceToTypeNode (<TypeReference>type);
|
const readonlyToken = (<MappedType>type).declaration && (<MappedType>type).declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined;
|
||||||
}
|
const questionToken = (<MappedType>type).declaration && (<MappedType>type).declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||||
if (objectFlags & ObjectFlags.ClassOrInterface) {
|
|
||||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
|
||||||
const name = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
|
||||||
// TODO(aozgaa): handle type arguments.
|
|
||||||
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.TypeParameter) {
|
|
||||||
const name = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
|
||||||
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
|
|
||||||
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkAlias && type.aliasSymbol) {
|
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
|
||||||
const name = symbolToName(type.aliasSymbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
}
|
||||||
const typeArgumentNodes = mapToTypeNodeArray(type.aliasTypeArguments);
|
|
||||||
return createTypeReferenceNode(name, typeArgumentNodes);
|
|
||||||
}
|
|
||||||
checkAlias = false;
|
|
||||||
|
|
||||||
if (type.flags & TypeFlags.Union) {
|
function createAnonymousTypeNode(type: ObjectType): TypeNode {
|
||||||
return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, mapToTypeNodeArray(formatUnionTypes((<UnionType>type).types)));
|
const symbol = type.symbol;
|
||||||
}
|
if (symbol) {
|
||||||
|
// Always use 'typeof T' for type of class, enum, and module objects
|
||||||
if (type.flags & TypeFlags.Intersection) {
|
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) ||
|
||||||
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, mapToTypeNodeArray((type as UnionType).types));
|
symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) ||
|
||||||
}
|
shouldWriteTypeOfFunctionSymbol()) {
|
||||||
|
return createTypeQueryNodeFromType(type);
|
||||||
if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
|
}
|
||||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
else if (contains(context.symbolStack, symbol)) {
|
||||||
// The type is an object literal type.
|
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||||
return createAnonymousTypeNode(<ObjectType>type);
|
const typeAlias = getTypeAliasForTypeLiteral(type);
|
||||||
}
|
if (typeAlias) {
|
||||||
|
// The specified symbol flags need to be reinterpreted as type flags
|
||||||
if (type.flags & TypeFlags.Index) {
|
const entityName = symbolToName(typeAlias, /*expectsIdentifier*/ false);
|
||||||
const indexedType = (<IndexType>type).type;
|
return createTypeReferenceNode(entityName, /*typeArguments*/ undefined);
|
||||||
const indexTypeNode = typeToTypeNodeWorker(indexedType);
|
|
||||||
return createTypeOperatorNode(indexTypeNode);
|
|
||||||
}
|
|
||||||
if (type.flags & TypeFlags.IndexedAccess) {
|
|
||||||
const objectTypeNode = typeToTypeNodeWorker((<IndexedAccessType>type).objectType);
|
|
||||||
const indexTypeNode = typeToTypeNodeWorker((<IndexedAccessType>type).indexType);
|
|
||||||
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.fail("Should be unreachable.");
|
|
||||||
|
|
||||||
function mapToTypeNodeArray(types: Type[]): NodeArray<TypeNode> {
|
|
||||||
return types && asNodeArray(types.map(typeToTypeNodeWorker).filter(node => !!node));
|
|
||||||
}
|
|
||||||
|
|
||||||
function createMappedTypeNodeFromType(type: MappedType) {
|
|
||||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
|
||||||
const typeParameter = getTypeParameterFromMappedType(<MappedType>type);
|
|
||||||
const typeParameterNode = typeParameterToDeclaration(typeParameter, enclosingDeclaration, flags);
|
|
||||||
|
|
||||||
const templateType = getTemplateTypeFromMappedType(<MappedType>type);
|
|
||||||
const templateTypeNode = templateType && typeToTypeNodeWorker(templateType);
|
|
||||||
const readonlyToken = (<MappedType>type).declaration && (<MappedType>type).declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined;
|
|
||||||
const questionToken = (<MappedType>type).declaration && (<MappedType>type).declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined;
|
|
||||||
|
|
||||||
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createAnonymousTypeNode(type: ObjectType): TypeNode {
|
|
||||||
const symbol = type.symbol;
|
|
||||||
if (symbol) {
|
|
||||||
// Always use 'typeof T' for type of class, enum, and module objects
|
|
||||||
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) ||
|
|
||||||
symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) ||
|
|
||||||
shouldWriteTypeOfFunctionSymbol()) {
|
|
||||||
return createTypeQueryNodeFromType(type);
|
|
||||||
}
|
|
||||||
else if (contains(symbolStack, symbol)) {
|
|
||||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
|
||||||
const typeAlias = getTypeAliasForTypeLiteral(type);
|
|
||||||
if (typeAlias) {
|
|
||||||
// The specified symbol flags need to be reinterpreted as type flags
|
|
||||||
const entityName = symbolToName(typeAlias, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
|
||||||
return createTypeReferenceNode(entityName, /*typeArguments*/ undefined);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
|
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
// of types allows us to catch circular references to instantiations of the same anonymous type
|
|
||||||
if (!symbolStack) {
|
|
||||||
symbolStack = [];
|
|
||||||
}
|
|
||||||
symbolStack.push(symbol);
|
|
||||||
const result = createTypeNodeFromObjectType(type);
|
|
||||||
symbolStack.pop();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Anonymous types without a symbol are never circular.
|
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
|
||||||
return createTypeNodeFromObjectType(type);
|
// of types allows us to catch circular references to instantiations of the same anonymous type
|
||||||
}
|
if (!context.symbolStack) {
|
||||||
|
context.symbolStack = [];
|
||||||
function shouldWriteTypeOfFunctionSymbol() {
|
|
||||||
const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
|
|
||||||
forEach(symbol.declarations, declaration => getModifierFlags(declaration) & ModifierFlags.Static));
|
|
||||||
const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
|
|
||||||
(symbol.parent || // is exported function symbol
|
|
||||||
forEach(symbol.declarations, declaration =>
|
|
||||||
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
|
||||||
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
|
||||||
// typeof is allowed only for static/non local functions
|
|
||||||
return contains(symbolStack, symbol); // it is type of the symbol uses itself recursively
|
|
||||||
}
|
}
|
||||||
|
context.symbolStack.push(symbol);
|
||||||
|
const result = createTypeNodeFromObjectType(type);
|
||||||
|
context.symbolStack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Anonymous types without a symbol are never circular.
|
||||||
|
return createTypeNodeFromObjectType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldWriteTypeOfFunctionSymbol() {
|
||||||
|
const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
|
||||||
|
forEach(symbol.declarations, declaration => getModifierFlags(declaration) & ModifierFlags.Static));
|
||||||
|
const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
|
||||||
|
(symbol.parent || // is exported function symbol
|
||||||
|
forEach(symbol.declarations, declaration =>
|
||||||
|
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||||
|
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||||
|
// typeof is allowed only for static/non local functions
|
||||||
|
return contains(context.symbolStack, symbol); // it is type of the symbol uses itself recursively
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
|
||||||
|
if (type.objectFlags & ObjectFlags.Mapped) {
|
||||||
|
if (getConstraintTypeFromMappedType(<MappedType>type).flags & (TypeFlags.TypeParameter | TypeFlags.Index)) {
|
||||||
|
return createMappedTypeNodeFromType(<MappedType>type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
|
const resolved = resolveStructuredTypeMembers(type);
|
||||||
if (type.objectFlags & ObjectFlags.Mapped) {
|
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
|
||||||
if (getConstraintTypeFromMappedType(<MappedType>type).flags & (TypeFlags.TypeParameter | TypeFlags.Index)) {
|
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
||||||
return createMappedTypeNodeFromType(<MappedType>type);
|
return createTypeLiteralNode(/*members*/ undefined);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolved = resolveStructuredTypeMembers(type);
|
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
|
||||||
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
|
const signature = resolved.callSignatures[0];
|
||||||
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
return <FunctionTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType);
|
||||||
return createTypeLiteralNode(/*members*/ undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
|
|
||||||
const signature = resolved.callSignatures[0];
|
|
||||||
return <FunctionTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, enclosingDeclaration, flags);
|
|
||||||
}
|
|
||||||
if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
|
|
||||||
const signature = resolved.constructSignatures[0];
|
|
||||||
return <ConstructorTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, enclosingDeclaration, flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
|
||||||
const saveInObjectTypeLiteral = inObjectTypeLiteral;
|
const signature = resolved.constructSignatures[0];
|
||||||
inObjectTypeLiteral = true;
|
return <ConstructorTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType);
|
||||||
const members = createTypeNodesFromResolvedType(resolved);
|
|
||||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
|
||||||
return createTypeLiteralNode(members);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createTypeQueryNodeFromType(type: Type) {
|
|
||||||
const symbol = type.symbol;
|
|
||||||
if (symbol) {
|
|
||||||
const entityName = symbolToName(symbol, enclosingDeclaration, /*expectsIdentifier*/ false, flags);
|
|
||||||
return createTypeQueryNode(entityName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeReferenceToTypeNode(type: TypeReference) {
|
const saveInObjectTypeLiteral = context.inObjectTypeLiteral;
|
||||||
const typeArguments: Type[] = type.typeArguments || emptyArray;
|
context.inObjectTypeLiteral = true;
|
||||||
if (type.target === globalArrayType) {
|
const members = createTypeNodesFromResolvedType(resolved);
|
||||||
const elementType = typeToTypeNodeWorker(typeArguments[0]);
|
context.inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||||
return createArrayTypeNode(elementType);
|
return createTypeLiteralNode(members);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeQueryNodeFromType(type: Type) {
|
||||||
|
const symbol = type.symbol;
|
||||||
|
if (symbol) {
|
||||||
|
const entityName = symbolToName(symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeQueryNode(entityName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeReferenceToTypeNode(type: TypeReference) {
|
||||||
|
const typeArguments: Type[] = type.typeArguments || emptyArray;
|
||||||
|
if (type.target === globalArrayType) {
|
||||||
|
const elementType = typeToTypeNodeHelper(typeArguments[0]);
|
||||||
|
return createArrayTypeNode(elementType);
|
||||||
|
}
|
||||||
|
else if (type.target.objectFlags & ObjectFlags.Tuple) {
|
||||||
|
if (typeArguments.length > 0) {
|
||||||
|
const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)));
|
||||||
|
if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
|
||||||
|
return createTupleTypeNode(tupleConstituentNodes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type.target.objectFlags & ObjectFlags.Tuple) {
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyTuple)) {
|
||||||
return createTupleTypeNode(typeArguments.length > 0 ? mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type))) : undefined);
|
context.encounteredError = true;
|
||||||
}
|
}
|
||||||
else {
|
return undefined;
|
||||||
const outerTypeParameters = type.target.outerTypeParameters;
|
}
|
||||||
let i = 0;
|
else {
|
||||||
let qualifiedName: QualifiedName | undefined = undefined;
|
const outerTypeParameters = type.target.outerTypeParameters;
|
||||||
if (outerTypeParameters) {
|
let i = 0;
|
||||||
const length = outerTypeParameters.length;
|
let qualifiedName: QualifiedName | undefined = undefined;
|
||||||
while (i < length) {
|
if (outerTypeParameters) {
|
||||||
// Find group of type arguments for type parameters with the same declaring container.
|
const length = outerTypeParameters.length;
|
||||||
const start = i;
|
while (i < length) {
|
||||||
const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]);
|
// Find group of type arguments for type parameters with the same declaring container.
|
||||||
do {
|
const start = i;
|
||||||
i++;
|
const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]);
|
||||||
} while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
|
do {
|
||||||
// When type parameters are their own type arguments for the whole group (i.e. we have
|
i++;
|
||||||
// the default outer type arguments), we don't show the group.
|
} while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
|
||||||
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
|
// When type parameters are their own type arguments for the whole group (i.e. we have
|
||||||
const qualifiedNamePart = symbolToName(parent, enclosingDeclaration, /*expectsIdentifier*/ true, flags);
|
// the default outer type arguments), we don't show the group.
|
||||||
if (!qualifiedName) {
|
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
|
||||||
qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/ undefined);
|
const qualifiedNamePart = symbolToName(parent, /*expectsIdentifier*/ true);
|
||||||
}
|
if (!qualifiedName) {
|
||||||
else {
|
qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/ undefined);
|
||||||
Debug.assert(!qualifiedName.right);
|
}
|
||||||
qualifiedName.right = qualifiedNamePart;
|
else {
|
||||||
qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined);
|
Debug.assert(!qualifiedName.right);
|
||||||
}
|
qualifiedName.right = qualifiedNamePart;
|
||||||
|
qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let entityName: EntityName = undefined;
|
|
||||||
const nameIdentifier = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ true, flags);
|
|
||||||
if (qualifiedName) {
|
|
||||||
Debug.assert(!qualifiedName.right);
|
|
||||||
qualifiedName.right = nameIdentifier;
|
|
||||||
entityName = qualifiedName;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entityName = nameIdentifier;
|
|
||||||
}
|
|
||||||
const typeParameterCount = (type.target.typeParameters || emptyArray).length;
|
|
||||||
const typeArgumentNodes = mapToTypeNodeArray(typeArguments.length > 0 ? typeArguments.slice(i, typeParameterCount - i) : undefined);
|
|
||||||
return createTypeReferenceNode(entityName, typeArgumentNodes);
|
|
||||||
}
|
}
|
||||||
|
let entityName: EntityName = undefined;
|
||||||
|
const nameIdentifier = symbolToName(type.symbol, /*expectsIdentifier*/ true);
|
||||||
|
if (qualifiedName) {
|
||||||
|
Debug.assert(!qualifiedName.right);
|
||||||
|
qualifiedName.right = nameIdentifier;
|
||||||
|
entityName = qualifiedName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entityName = nameIdentifier;
|
||||||
|
}
|
||||||
|
const typeParameterCount = (type.target.typeParameters || emptyArray).length;
|
||||||
|
const typeArgumentNodes = typeArguments.length > 0 ? mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)) : undefined;
|
||||||
|
return createTypeReferenceNode(entityName, typeArgumentNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] {
|
||||||
|
const typeElements: TypeElement[] = [];
|
||||||
|
for (const signature of resolvedType.callSignatures) {
|
||||||
|
typeElements.push(<CallSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature));
|
||||||
|
}
|
||||||
|
for (const signature of resolvedType.constructSignatures) {
|
||||||
|
typeElements.push(<ConstructSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature));
|
||||||
|
}
|
||||||
|
if (resolvedType.stringIndexInfo) {
|
||||||
|
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.stringIndexInfo, IndexKind.String));
|
||||||
|
}
|
||||||
|
if (resolvedType.numberIndexInfo) {
|
||||||
|
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, IndexKind.Number));
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] {
|
const properties = resolvedType.properties;
|
||||||
const typeElements: TypeElement[] = [];
|
if (!properties) {
|
||||||
for (const signature of resolvedType.callSignatures) {
|
return typeElements;
|
||||||
typeElements.push(<CallSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, enclosingDeclaration, flags));
|
}
|
||||||
}
|
|
||||||
for (const signature of resolvedType.constructSignatures) {
|
|
||||||
typeElements.push(<ConstructSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, enclosingDeclaration, flags));
|
|
||||||
}
|
|
||||||
if (resolvedType.stringIndexInfo) {
|
|
||||||
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.stringIndexInfo, IndexKind.String, enclosingDeclaration, flags));
|
|
||||||
}
|
|
||||||
if (resolvedType.numberIndexInfo) {
|
|
||||||
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, IndexKind.Number, enclosingDeclaration, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
const properties = resolvedType.properties;
|
for (const propertySymbol of properties) {
|
||||||
if (!properties) {
|
const propertyType = getTypeOfSymbol(propertySymbol);
|
||||||
return typeElements;
|
const oldDeclaration = propertySymbol.declarations && propertySymbol.declarations[0] as TypeElement;
|
||||||
|
if (!oldDeclaration) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const propertyName = oldDeclaration.name;
|
||||||
for (const propertySymbol of properties) {
|
const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||||
const propertyType = getTypeOfSymbol(propertySymbol);
|
if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
|
||||||
const oldDeclaration = propertySymbol.declarations && propertySymbol.declarations[0] as TypeElement;
|
const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
|
||||||
if (!oldDeclaration) {
|
for (const signature of signatures) {
|
||||||
return;
|
const methodDeclaration = <MethodSignature>signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature);
|
||||||
|
methodDeclaration.name = propertyName;
|
||||||
|
methodDeclaration.questionToken = optionalToken;
|
||||||
|
typeElements.push(methodDeclaration);
|
||||||
}
|
}
|
||||||
const propertyName = oldDeclaration.name;
|
}
|
||||||
const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;
|
else {
|
||||||
if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
|
|
||||||
const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
|
|
||||||
for (const signature of signatures) {
|
|
||||||
const methodDeclaration = <MethodSignature>signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, enclosingDeclaration, flags);
|
|
||||||
methodDeclaration.name = propertyName;
|
|
||||||
methodDeclaration.questionToken = optionalToken;
|
|
||||||
typeElements.push(methodDeclaration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
// TODO(aozgaa): should we create a node with explicit or implict any?
|
// TODO(aozgaa): should we create a node with explicit or implict any?
|
||||||
const propertyTypeNode = propertyType ? typeToTypeNodeWorker(propertyType) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
typeElements.push(createPropertySignature(
|
typeElements.push(createPropertySignature(
|
||||||
propertyName,
|
propertyName,
|
||||||
optionalToken,
|
optionalToken,
|
||||||
propertyTypeNode,
|
propertyTypeNode,
|
||||||
/*initializer*/undefined));
|
/*initializer*/undefined));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return typeElements.length ? typeElements : undefined;
|
|
||||||
}
|
}
|
||||||
|
return typeElements.length ? typeElements : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration: Node, flags: NodeBuilderFlags): IndexSignatureDeclaration {
|
function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration {
|
||||||
const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword);
|
const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword);
|
||||||
const name = getNameFromIndexInfo(indexInfo);
|
const name = getNameFromIndexInfo(indexInfo);
|
||||||
|
|
||||||
|
@ -2578,7 +2612,7 @@ namespace ts {
|
||||||
/*questionToken*/ undefined,
|
/*questionToken*/ undefined,
|
||||||
indexerTypeNode,
|
indexerTypeNode,
|
||||||
/*initializer*/ undefined);
|
/*initializer*/ undefined);
|
||||||
const typeNode = typeToTypeNodeHelper(indexInfo.type, enclosingDeclaration, flags);
|
const typeNode = typeToTypeNodeHelper(indexInfo.type);
|
||||||
return createIndexSignatureDeclaration(
|
return createIndexSignatureDeclaration(
|
||||||
[indexingParameter],
|
[indexingParameter],
|
||||||
typeNode,
|
typeNode,
|
||||||
|
@ -2586,37 +2620,37 @@ namespace ts {
|
||||||
indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined);
|
indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node, flags: NodeBuilderFlags): SignatureDeclaration {
|
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind): SignatureDeclaration {
|
||||||
|
|
||||||
const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, enclosingDeclaration, flags));
|
const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter));
|
||||||
const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter, enclosingDeclaration, flags));
|
const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter));
|
||||||
const returnTypeNode = typeToTypeNodeExceptAny(getReturnTypeOfSignature(signature));
|
const returnTypeNode = typeToTypeNodeExceptAny(getReturnTypeOfSignature(signature));
|
||||||
|
|
||||||
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode);
|
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode);
|
||||||
|
|
||||||
function typeToTypeNodeExceptAny(type: Type): TypeNode | undefined {
|
function typeToTypeNodeExceptAny(type: Type): TypeNode | undefined {
|
||||||
const typeNode = type && typeToTypeNodeHelper(type, enclosingDeclaration, flags);
|
const typeNode = type && typeToTypeNodeHelper(type);
|
||||||
return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined;
|
return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeParameterToDeclaration(type: TypeParameter, enclosingDeclaration: Node, flags: NodeBuilderFlags): TypeParameterDeclaration {
|
function typeParameterToDeclaration(type: TypeParameter): TypeParameterDeclaration {
|
||||||
if (!(type && type.symbol && type.flags & TypeFlags.TypeParameter)) {
|
if (!(type && type.symbol && type.flags & TypeFlags.TypeParameter)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const constraint = getConstraintFromTypeParameter(type);
|
const constraint = getConstraintFromTypeParameter(type);
|
||||||
const constraintNode = constraint && typeToTypeNodeHelper(constraint, enclosingDeclaration, flags);
|
const constraintNode = constraint && typeToTypeNodeHelper(constraint);
|
||||||
const defaultParameter = getDefaultFromTypeParameter(type);
|
const defaultParameter = getDefaultFromTypeParameter(type);
|
||||||
const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, enclosingDeclaration, flags);
|
const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter);
|
||||||
const name = symbolToName(type.symbol, enclosingDeclaration, /*expectsIdentifier*/ true, flags);
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ true);
|
||||||
return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode);
|
return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function symbolToParameterDeclaration(parameterSymbol: Symbol, enclosingDeclaration: Node, flags: NodeBuilderFlags): ParameterDeclaration {
|
function symbolToParameterDeclaration(parameterSymbol: Symbol): ParameterDeclaration {
|
||||||
const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration;
|
const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration;
|
||||||
const parameterType = getTypeOfSymbol(parameterSymbol);
|
const parameterType = getTypeOfSymbol(parameterSymbol);
|
||||||
const parameterTypeNode = typeToTypeNodeHelper(parameterType, enclosingDeclaration, flags);
|
const parameterTypeNode = typeToTypeNodeHelper(parameterType);
|
||||||
// TODO(aozgaa): check initializer accessibility correctly.
|
// TODO(aozgaa): check initializer accessibility correctly.
|
||||||
const parameterNode = createParameter(
|
const parameterNode = createParameter(
|
||||||
parameterDeclaration.decorators,
|
parameterDeclaration.decorators,
|
||||||
|
@ -2630,15 +2664,15 @@ namespace ts {
|
||||||
return parameterNode;
|
return parameterNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function symbolToName(symbol: Symbol, enclosingDeclaration: Node | undefined, expectsIdentifier: true, flags: NodeBuilderFlags): Identifier;
|
function symbolToName(symbol: Symbol, expectsIdentifier: true): Identifier;
|
||||||
function symbolToName(symbol: Symbol, enclosingDeclaration: Node | undefined, expectsIdentifier: false, flags: NodeBuilderFlags): EntityName;
|
function symbolToName(symbol: Symbol, expectsIdentifier: false): EntityName;
|
||||||
function symbolToName(symbol: Symbol, enclosingDeclaration: Node | undefined, expectsIdentifier: boolean, flags: NodeBuilderFlags): EntityName {
|
function symbolToName(symbol: Symbol, expectsIdentifier: boolean): EntityName {
|
||||||
let parentSymbol: Symbol;
|
let parentSymbol: Symbol;
|
||||||
|
|
||||||
// Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration.
|
// Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration.
|
||||||
let chain: Symbol[];
|
let chain: Symbol[];
|
||||||
const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
|
const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
|
||||||
if (!isTypeParameter && enclosingDeclaration) {
|
if (!isTypeParameter && context.enclosingDeclaration) {
|
||||||
chain = getSymbolChain(symbol, SymbolFlags.None, /*endOfChain*/ true);
|
chain = getSymbolChain(symbol, SymbolFlags.None, /*endOfChain*/ true);
|
||||||
Debug.assert(chain && chain.length > 0);
|
Debug.assert(chain && chain.length > 0);
|
||||||
}
|
}
|
||||||
|
@ -2648,8 +2682,10 @@ namespace ts {
|
||||||
|
|
||||||
parentSymbol = undefined;
|
parentSymbol = undefined;
|
||||||
|
|
||||||
if (expectsIdentifier && chain.length !== 1) {
|
if (expectsIdentifier && chain.length !== 1
|
||||||
encounteredError = encounteredError || !(flags & NodeBuilderFlags.allowQualifedNameInPlaceOfIdentifier);
|
&& !context.encounteredError
|
||||||
|
&& !(context.flags & NodeBuilderFlags.allowQualifedNameInPlaceOfIdentifier)) {
|
||||||
|
context.encounteredError = true;
|
||||||
}
|
}
|
||||||
return createEntityNameFromSymbolChain(chain, chain.length - 1);
|
return createEntityNameFromSymbolChain(chain, chain.length - 1);
|
||||||
|
|
||||||
|
@ -2672,11 +2708,12 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeParameters && typeParameters.length > 0) {
|
if (typeParameters && typeParameters.length > 0) {
|
||||||
encounteredError = encounteredError || !(flags & NodeBuilderFlags.allowTypeParameterInQualifiedName);
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowTypeParameterInQualifiedName)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
const writer = getSingleLineStringWriter();
|
const writer = getSingleLineStringWriter();
|
||||||
const displayBuilder = getSymbolDisplayBuilder();
|
const displayBuilder = getSymbolDisplayBuilder();
|
||||||
displayBuilder.buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosingDeclaration, 0);
|
displayBuilder.buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, context.enclosingDeclaration, 0);
|
||||||
typeParameterString = writer.string();
|
typeParameterString = writer.string();
|
||||||
releaseStringWriter(writer);
|
releaseStringWriter(writer);
|
||||||
|
|
||||||
|
@ -2691,10 +2728,10 @@ namespace ts {
|
||||||
|
|
||||||
/** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */
|
/** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */
|
||||||
function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined {
|
function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined {
|
||||||
let accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/false);
|
let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/false);
|
||||||
|
|
||||||
if (!accessibleSymbolChain ||
|
if (!accessibleSymbolChain ||
|
||||||
needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
|
needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
|
||||||
|
|
||||||
// Go up and add our parent.
|
// Go up and add our parent.
|
||||||
const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol);
|
const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol);
|
||||||
|
@ -2731,7 +2768,9 @@ namespace ts {
|
||||||
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||||
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
|
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
|
||||||
}
|
}
|
||||||
encounteredError = encounteredError || !(flags & NodeBuilderFlags.allowAnonymousIdentifier);
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowAnonymousIdentifier)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
switch (declaration.kind) {
|
switch (declaration.kind) {
|
||||||
case SyntaxKind.ClassExpression:
|
case SyntaxKind.ClassExpression:
|
||||||
return "(Anonymous class)";
|
return "(Anonymous class)";
|
||||||
|
|
|
@ -238,10 +238,10 @@ namespace ts {
|
||||||
: node;
|
: node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: NodeArray<TypeNode> | undefined) {
|
export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: TypeNode[] | undefined) {
|
||||||
const typeReference = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
|
const typeReference = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
|
||||||
typeReference.typeName = asName(typeName);
|
typeReference.typeName = asName(typeName);
|
||||||
typeReference.typeArguments = typeArguments;
|
typeReference.typeArguments = asNodeArray(typeArguments);
|
||||||
return typeReference;
|
return typeReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2548,7 +2548,9 @@ namespace ts {
|
||||||
allowThisInObjectLiteral = 1 << 0,
|
allowThisInObjectLiteral = 1 << 0,
|
||||||
allowQualifedNameInPlaceOfIdentifier = 1 << 1,
|
allowQualifedNameInPlaceOfIdentifier = 1 << 1,
|
||||||
allowTypeParameterInQualifiedName = 1 << 2,
|
allowTypeParameterInQualifiedName = 1 << 2,
|
||||||
allowAnonymousIdentifier = 1 << 3
|
allowAnonymousIdentifier = 1 << 3,
|
||||||
|
allowEmptyUnionOrIntersection = 1 << 4,
|
||||||
|
allowEmptyTuple = 1 << 5
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SymbolDisplayBuilder {
|
export interface SymbolDisplayBuilder {
|
||||||
|
|
Loading…
Reference in a new issue