diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7a7ce2536fe..6c24def1500 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2384,13 +2384,13 @@ namespace ts { function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); - const typeParameter = getTypeParameterFromMappedType(type); + const typeParameter = getTypeParameterFromMappedType(type); const typeParameterNode = typeParameterToDeclaration(typeParameter); - const templateType = getTemplateTypeFromMappedType(type); - const templateTypeNode = templateType && typeToTypeNodeHelper(templateType); - const readonlyToken = (type).declaration && (type).declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined; - const questionToken = (type).declaration && (type).declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined; + const templateType = getTemplateTypeFromMappedType(type); + const templateTypeNode = typeToTypeNodeHelper(templateType); + const readonlyToken = type.declaration && type.declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined; + const questionToken = type.declaration && type.declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined; return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); } @@ -2402,7 +2402,7 @@ namespace ts { if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { - return createTypeQueryNodeFromType(type); + return createTypeQueryNodeFromSymbol(symbol); } else if (contains(context.symbolStack, symbol)) { // If type is an anonymous type literal in a type alias declaration, use type alias name @@ -2477,12 +2477,9 @@ namespace ts { return createTypeLiteralNode(members); } - function createTypeQueryNodeFromType(type: Type) { - const symbol = type.symbol; - if (symbol) { - const entityName = symbolToName(symbol, /*expectsIdentifier*/ false); - return createTypeQueryNode(entityName); - } + function createTypeQueryNodeFromSymbol(symbol: Symbol) { + const entityName = symbolToName(symbol, /*expectsIdentifier*/ false); + return createTypeQueryNode(entityName); } function typeReferenceToTypeNode(type: TypeReference) { @@ -2542,7 +2539,7 @@ namespace ts { entityName = nameIdentifier; } const typeParameterCount = (type.target.typeParameters || emptyArray).length; - const typeArgumentNodes = typeArguments.length > 0 ? mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)) : undefined; + const typeArgumentNodes = some(typeArguments) ? mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)) : undefined; return createTypeReferenceNode(entityName, typeArgumentNodes); } } @@ -2604,13 +2601,13 @@ namespace ts { const name = getNameFromIndexInfo(indexInfo); const indexingParameter = createParameter( - /*decorators*/ undefined, - /*modifiers*/ undefined, - /*dotDotDotToken*/ undefined, + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, name, - /*questionToken*/ undefined, + /*questionToken*/ undefined, indexerTypeNode, - /*initializer*/ undefined); + /*initializer*/ undefined); const typeNode = typeToTypeNodeHelper(indexInfo.type); return createIndexSignatureDeclaration( [indexingParameter], @@ -2623,21 +2620,14 @@ namespace ts { const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter)); const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter)); - const returnTypeNode = typeToTypeNodeExceptAny(getReturnTypeOfSignature(signature)); + const returnType = getReturnTypeOfSignature(signature); + const returnTypeNode = returnType && typeToTypeNodeHelper(returnType); + const returnTypeNodeExceptAny = returnTypeNode && returnTypeNode.kind !== SyntaxKind.AnyKeyword ? returnTypeNode : undefined; - return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode); - - function typeToTypeNodeExceptAny(type: Type): TypeNode | undefined { - const typeNode = type && typeToTypeNodeHelper(type); - return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined; - } + return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNodeExceptAny); } function typeParameterToDeclaration(type: TypeParameter): TypeParameterDeclaration { - if (!(type && type.symbol && type.flags & TypeFlags.TypeParameter)) { - return undefined; - } - const constraint = getConstraintFromTypeParameter(type); const constraintNode = constraint && typeToTypeNodeHelper(constraint); const defaultParameter = getDefaultFromTypeParameter(type); @@ -2647,10 +2637,10 @@ namespace ts { } function symbolToParameterDeclaration(parameterSymbol: Symbol): ParameterDeclaration { - const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration; + const parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); const parameterType = getTypeOfSymbol(parameterSymbol); const parameterTypeNode = typeToTypeNodeHelper(parameterType); - // TODO(aozgaa): check initializer accessibility correctly. + // TODO(aozgaa): In the future, check initializer accessibility. const parameterNode = createParameter( parameterDeclaration.decorators, parameterDeclaration.modifiers, @@ -2666,7 +2656,6 @@ namespace ts { function symbolToName(symbol: Symbol, expectsIdentifier: true): Identifier; function symbolToName(symbol: Symbol, expectsIdentifier: false): EntityName; function symbolToName(symbol: Symbol, expectsIdentifier: boolean): EntityName { - let parentSymbol: Symbol; // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. let chain: Symbol[]; @@ -2679,8 +2668,6 @@ namespace ts { chain = [symbol]; } - parentSymbol = undefined; - if (expectsIdentifier && chain.length !== 1 && !context.encounteredError && !(context.flags & NodeBuilderFlags.allowQualifedNameInPlaceOfIdentifier)) { @@ -2728,6 +2715,7 @@ namespace ts { /** @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 { let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/false); + let parentSymbol: Symbol; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { @@ -2737,6 +2725,7 @@ namespace ts { if (parent) { const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); if (parentChain) { + parentSymbol = parent; accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [symbol]); } } @@ -2745,8 +2734,7 @@ namespace ts { if (accessibleSymbolChain) { return accessibleSymbolChain; } - - else if ( + if ( // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. endOfChain || // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) @@ -2759,8 +2747,8 @@ namespace ts { } function getNameOfSymbol(symbol: Symbol): string { - if (symbol.declarations && symbol.declarations.length) { - const declaration = symbol.declarations[0]; + const declaration = firstOrUndefined(symbol.declarations); + if (declaration) { if (declaration.name) { return declarationNameToString(declaration.name); } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index e1e4e2c4ae5..4c5a4b4067f 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -46,9 +46,6 @@ namespace ts { */ /* @internal */ export function getSynthesizedClone(node: T | undefined): T { - if (node === undefined) { - return undefined; - } // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). @@ -169,23 +166,23 @@ namespace ts { // Reserved words export function createSuper() { - return createSynthesizedNode(SyntaxKind.SuperKeyword); + return createSynthesizedNode(SyntaxKind.SuperKeyword); } export function createThis() { - return createSynthesizedNode(SyntaxKind.ThisKeyword); + return >createSynthesizedNode(SyntaxKind.ThisKeyword); } export function createNull() { - return createSynthesizedNode(SyntaxKind.NullKeyword); + return >createSynthesizedNode(SyntaxKind.NullKeyword); } export function createTrue() { - return createSynthesizedNode(SyntaxKind.TrueKeyword); + return >createSynthesizedNode(SyntaxKind.TrueKeyword); } export function createFalse() { - return createSynthesizedNode(SyntaxKind.FalseKeyword); + return >createSynthesizedNode(SyntaxKind.FalseKeyword); } // Names @@ -218,11 +215,74 @@ namespace ts { // Type Elements - // TODO: add signatures + export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { + const signatureDeclaration = createSynthesizedNode(kind) as SignatureDeclaration; + signatureDeclaration.typeParameters = asNodeArray(typeParameters); + signatureDeclaration.parameters = asNodeArray(parameters); + signatureDeclaration.type = type; + return signatureDeclaration; + } + + function updateSignatureDeclaration(node: SignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + ? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node) + : node; + } + + export function createFunctionTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { + return createSignatureDeclaration(SyntaxKind.FunctionType, typeParameters, parameters, type) as FunctionTypeNode; + } + + export function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { + return updateSignatureDeclaration(node, typeParameters, parameters, type); + } + + export function createConstructorTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { + return createSignatureDeclaration(SyntaxKind.ConstructorType, typeParameters, parameters, type) as ConstructorTypeNode; + } + + export function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { + return updateSignatureDeclaration(node, typeParameters, parameters, type); + } + + export function createCallSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { + return createSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type) as CallSignatureDeclaration; + } + + export function updateCallSignatureDeclaration(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { + return updateSignatureDeclaration(node, typeParameters, parameters, type); + } + + export function createConstructSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { + return createSignatureDeclaration(SyntaxKind.ConstructSignature, typeParameters, parameters, type) as ConstructSignatureDeclaration; + } + + export function updateConstructSignatureDeclaration(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { + return updateSignatureDeclaration(node, typeParameters, parameters, type); + } + + export function createMethodSignature(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined) { + const methodSignature = createSignatureDeclaration(SyntaxKind.MethodSignature, typeParameters, parameters, type) as MethodSignature; + methodSignature.name = asName(name); + methodSignature.questionToken = questionToken; + return methodSignature; + } + + export function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined) { + return node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.name !== name + || node.questionToken !== questionToken + ? updateNode(createMethodSignature(typeParameters, parameters, type, name, questionToken), node) + : node; + } // Types - export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode { + export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]) { return createSynthesizedNode(kind); } @@ -259,10 +319,10 @@ namespace ts { } export function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) { - return node.exprName !== exprName ? updateNode(createTypeQueryNode(exprName) , node) : node; + return node.exprName !== exprName ? updateNode(createTypeQueryNode(exprName), node) : node; } - export function createArrayTypeNode(elementType: TypeNode): ArrayTypeNode { + export function createArrayTypeNode(elementType: TypeNode) { const arrayTypeNode = createSynthesizedNode(SyntaxKind.ArrayType) as ArrayTypeNode; arrayTypeNode.elementType = elementType; return arrayTypeNode; @@ -277,9 +337,9 @@ namespace ts { export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType, types: TypeNode[]): UnionTypeNode; export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.IntersectionType, types: TypeNode[]): IntersectionTypeNode; export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]): UnionOrIntersectionTypeNode; - export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]): UnionOrIntersectionTypeNode { + export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]) { const unionTypeNode = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode; - unionTypeNode.types = asNodeArray(types); + unionTypeNode.types = createNodeArray(types); return unionTypeNode; } @@ -291,7 +351,7 @@ namespace ts { export function createTypeLiteralNode(members: TypeElement[]) { const typeLiteralNode = createSynthesizedNode(SyntaxKind.TypeLiteral) as TypeLiteralNode; - typeLiteralNode.members = asNodeArray(members); + typeLiteralNode.members = createNodeArray(members); return typeLiteralNode; } @@ -303,7 +363,7 @@ namespace ts { export function createTupleTypeNode(elementTypes: TypeNode[]) { const tupleTypeNode = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode; - tupleTypeNode.elementTypes = asNodeArray(elementTypes); + tupleTypeNode.elementTypes = createNodeArray(elementTypes); return tupleTypeNode; } @@ -349,7 +409,6 @@ namespace ts { return indexedAccessTypeNode; } - export function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { return node.objectType !== objectType || node.indexType !== indexType @@ -357,86 +416,22 @@ namespace ts { : node; } - // Type Declarations - export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultParameter: TypeNode | undefined) { + export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) { const typeParameter = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration; typeParameter.name = asName(name); typeParameter.constraint = constraint; - typeParameter.default = defaultParameter; + typeParameter.default = defaultType; return typeParameter; } - export function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultParameter: TypeNode | undefined) { + export function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) { return node.name !== name || node.constraint !== constraint - || node.default !== defaultParameter - ? updateNode(createTypeParameterDeclaration(name, constraint, defaultParameter), node) - : node; - } - - // TODO: Split according to AST nodes. - export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) { - const signatureDeclaration = createSynthesizedNode(kind) as SignatureDeclaration; - signatureDeclaration.typeParameters = asNodeArray(typeParameters); - signatureDeclaration.parameters = asNodeArray(parameters); - signatureDeclaration.type = type; - return signatureDeclaration; - } - - export function updateSignatureDeclaration(node: SignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined) { - return node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - ? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node) - : node; - } - - export function createFunctionTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode { - return createSignatureDeclaration(SyntaxKind.FunctionType, typeParameters, parameters, type) as FunctionTypeNode; - } - - export function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): FunctionTypeNode { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createConstructorTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined): ConstructorTypeNode { - return createSignatureDeclaration(SyntaxKind.ConstructorType, typeParameters, parameters, type) as ConstructorTypeNode; - } - export function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createCallSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration { - return createSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type) as CallSignatureDeclaration; - } - export function updateCallSignatureDeclaration(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createConstructSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration { - return createSignatureDeclaration(SyntaxKind.ConstructSignature, typeParameters, parameters, type) as ConstructSignatureDeclaration; - } - export function updateConstructSignatureDeclaration(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration { - return updateSignatureDeclaration(node, typeParameters, parameters, type); - } - - export function createMethodSignature(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): MethodSignature { - const methodSignature = createSignatureDeclaration(SyntaxKind.MethodSignature, typeParameters, parameters, type) as MethodSignature; - methodSignature.name = asName(name); - methodSignature.questionToken = questionToken; - return methodSignature; - } - - export function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined, name?: PropertyName, questionToken?: QuestionToken): MethodSignature { - return node.typeParameters !== typeParameters - || node.parameters !== parameters - || node.type !== type - || node.name !== name - || node.questionToken !== questionToken - ? updateNode(createMethodSignature(typeParameters, parameters, type, name, questionToken), node) + || node.default !== defaultType + ? updateNode(createTypeParameterDeclaration(name, constraint, defaultType), node) : node; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a93e8bddef1..45a4de01c9f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1034,15 +1034,15 @@ namespace ts { _primaryExpressionBrand: any; } - export interface NullLiteral extends PrimaryExpression { + export interface NullLiteral extends PrimaryExpression, TypeNode { kind: SyntaxKind.NullKeyword; } - export interface BooleanLiteral extends PrimaryExpression { + export interface BooleanLiteral extends PrimaryExpression, TypeNode { kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword; } - export interface ThisExpression extends PrimaryExpression { + export interface ThisExpression extends PrimaryExpression, TypeNode { kind: SyntaxKind.ThisKeyword; }