mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
signatures, parameter, literals, anyonymous types
This commit is contained in:
+103
-180
@@ -109,6 +109,7 @@ namespace ts {
|
||||
createTypeNode,
|
||||
createTypeParameterDeclarationFromType,
|
||||
createIndexSignatureFromIndexInfo,
|
||||
createParameterDeclarationFromSymbol,
|
||||
getSymbolsInScope: (location, meaning) => {
|
||||
location = getParseTreeNode(location);
|
||||
return location ? getSymbolsInScope(location, meaning) : [];
|
||||
@@ -2203,6 +2204,45 @@ namespace ts {
|
||||
return createTypeParameterDeclaration(name, constraint, defaultParameter);
|
||||
}
|
||||
|
||||
// TODO: enclosing declaration appears to be unused in getTypeOfSymbolAtLocation
|
||||
function createParameterDeclarationFromSymbol(parameterSymbol: Symbol): ParameterDeclaration {
|
||||
const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration;
|
||||
const parameterType = getTypeOfSymbol(parameterSymbol);
|
||||
const parameterTypeNode = checker.createTypeNode(parameterType);
|
||||
// TODO: clone binding names correctly.
|
||||
// TODO: copy initialzer in a way that checks whether all symbols used in expression are accessible here, and qualify them appropriately.
|
||||
const parameterNode = createParameter(
|
||||
parameterDeclaration.decorators && parameterDeclaration.decorators.map(getSynthesizedDeepClone)
|
||||
, parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedDeepClone)
|
||||
, parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken)
|
||||
, getSynthesizedDeepClone(parameterDeclaration.name)
|
||||
, parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken)
|
||||
, parameterTypeNode
|
||||
, /*initializer*/ undefined);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
type SignatureParts = {
|
||||
typeParameters: TypeParameterDeclaration[] | undefined;
|
||||
parameters: ParameterDeclaration[];
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
// TODO: expose this, remove copy from helper, possibly don't expose createParameter/TypeParameter?
|
||||
function createSignatureParts(signature: Signature): SignatureParts {
|
||||
return {
|
||||
typeParameters: signature.typeParameters && signature.typeParameters.map(createTypeParameterDeclarationFromType),
|
||||
parameters: signature.parameters.map(createParameterDeclarationFromSymbol),
|
||||
type: createTypeNodeExceptAny(getReturnTypeOfSignature(signature))
|
||||
}
|
||||
|
||||
function createTypeNodeExceptAny(type: Type): TypeNode | undefined {
|
||||
const typeNode = createTypeNode(type);
|
||||
return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createTypeNode(type: Type): TypeNode {
|
||||
let undefinedArgumentIsError = true;
|
||||
let encounteredError = false;
|
||||
@@ -2322,22 +2362,6 @@ namespace ts {
|
||||
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, mapToTypeNodeArray((type as UnionType).types));
|
||||
}
|
||||
|
||||
if (objectFlags & ObjectFlags.Mapped) {
|
||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||
|
||||
// TODO: does typeParameter have the same constraint or do we need to overwrite it somehow?
|
||||
const typeParameter = getTypeParameterFromMappedType(<MappedType>type);
|
||||
// const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
|
||||
const typeParameterNode = createTypeParameterDeclarationFromType(typeParameter);
|
||||
|
||||
const templateTypeNode = createTypeNode(getTemplateTypeFromMappedType(<MappedType>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;
|
||||
|
||||
// TODO: test.
|
||||
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
|
||||
}
|
||||
|
||||
if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
|
||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||
// The type is an object literal type.
|
||||
@@ -2371,57 +2395,25 @@ namespace ts {
|
||||
return asNodeArray(types && types.map(createTypeNodeWorker) as TypeNode[]);
|
||||
}
|
||||
|
||||
/******** START COPY *********/
|
||||
|
||||
// function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
// const globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
|
||||
// let inObjectTypeLiteral = false;
|
||||
// return writeType(type, globalFlags);
|
||||
|
||||
// function writeType(type: Type, flags: TypeFormatFlags) {
|
||||
// // const nextFlags = flags & ~TypeFormatFlags.InTypeAlias;
|
||||
// // // Write undefined/null type as any
|
||||
// // if (type.flags & TypeFlags.Intrinsic) {
|
||||
// // // Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
|
||||
// // writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
|
||||
// // ? "any"
|
||||
// // : (<IntrinsicType>type).intrinsicName);
|
||||
// // }
|
||||
// // else if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) {
|
||||
// // if (inObjectTypeLiteral) {
|
||||
// // writer.reportInaccessibleThisError();
|
||||
// // }
|
||||
// // writer.writeKeyword("this");
|
||||
// // }
|
||||
// else if (getObjectFlags(type) & ObjectFlags.Reference) {
|
||||
// writeTypeReference(<TypeReference>type, nextFlags);
|
||||
// }
|
||||
// else if (type.flags & TypeFlags.EnumLiteral) {
|
||||
// buildSymbolDisplay(getParentOfSymbol(type.symbol), writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
|
||||
// writePunctuation(writer, SyntaxKind.DotToken);
|
||||
// appendSymbolNameOnly(type.symbol, writer);
|
||||
// }
|
||||
// else if (getObjectFlags(type) & ObjectFlags.ClassOrInterface || type.flags & (TypeFlags.Enum | TypeFlags.TypeParameter)) {
|
||||
// // The specified symbol flags need to be reinterpreted as type flags
|
||||
// buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
|
||||
// }
|
||||
// else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol &&
|
||||
// isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
|
||||
// const typeArguments = type.aliasTypeArguments;
|
||||
// writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, length(typeArguments), nextFlags);
|
||||
// }
|
||||
// else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
// writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
|
||||
// }
|
||||
// else if (getObjectFlags(type) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
|
||||
// writeAnonymousType(<ObjectType>type, nextFlags);
|
||||
// }
|
||||
// TODO: implement when this is testable.
|
||||
// else if (type.flags & TypeFlags.StringOrNumberLiteral) {
|
||||
// writer.writeStringLiteral(literalTypeToString(<LiteralType>type));
|
||||
// }
|
||||
// }
|
||||
|
||||
/******** END COPY *********/
|
||||
function createMappedTypeNodeFromType(type: MappedType) {
|
||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||
|
||||
// TODO: does typeParameter have the same constraint or do we need to overwrite it somehow?
|
||||
const typeParameter = getTypeParameterFromMappedType(<MappedType>type);
|
||||
// const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
|
||||
const typeParameterNode = createTypeParameterDeclarationFromType(typeParameter);
|
||||
|
||||
const templateTypeNode = createTypeNode(getTemplateTypeFromMappedType(<MappedType>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;
|
||||
|
||||
// TODO: test.
|
||||
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
|
||||
}
|
||||
|
||||
function createAnonymousTypeNode(type: ObjectType): TypeNode {
|
||||
const symbol = type.symbol;
|
||||
@@ -2439,7 +2431,7 @@ namespace ts {
|
||||
const typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
const entityName = getEntityNameFromSymbol(typeAlias, enclosingDeclaration);
|
||||
const entityName = createNameFromSymbol(typeAlias, enclosingDeclaration);
|
||||
return createTypeReferenceNode(entityName, /*typeArguments*/ undefined);
|
||||
}
|
||||
else {
|
||||
@@ -2453,14 +2445,14 @@ namespace ts {
|
||||
symbolStack = [];
|
||||
}
|
||||
symbolStack.push(symbol);
|
||||
let result = createTypeLiteralNodeFromType(type);
|
||||
let result = createTypeNodeFromObjectType(type);
|
||||
symbolStack.pop();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Anonymous types with no symbol are never circular
|
||||
return createTypeLiteralNodeFromType(type);
|
||||
return createTypeNodeFromObjectType(type);
|
||||
}
|
||||
|
||||
function shouldWriteTypeOfFunctionSymbol() {
|
||||
@@ -2477,103 +2469,48 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
|
||||
function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
|
||||
if (type.objectFlags & ObjectFlags.Mapped) {
|
||||
if (getConstraintTypeFromMappedType(<MappedType>type).flags & (TypeFlags.TypeParameter | TypeFlags.Index)) {
|
||||
writeMappedType(<MappedType>type);
|
||||
return;
|
||||
return createMappedTypeNodeFromType(<MappedType>type);
|
||||
}
|
||||
}
|
||||
|
||||
const resolved = resolveStructuredTypeMembers(type);
|
||||
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
|
||||
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
return;
|
||||
return createTypeLiteralNode(/*members*/ undefined);
|
||||
}
|
||||
|
||||
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
|
||||
const parenthesizeSignature = shouldAddParenthesisAroundFunctionType(resolved.callSignatures[0], flags);
|
||||
if (parenthesizeSignature) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
|
||||
if (parenthesizeSignature) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
return;
|
||||
const signature = resolved.callSignatures[0];
|
||||
const signatureParts = createSignatureParts(signature);
|
||||
return createSignatureDeclaration<FunctionTypeNode>(SyntaxKind.FunctionType, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type);
|
||||
}
|
||||
if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
return;
|
||||
const signature = resolved.constructSignatures[0];
|
||||
const signatureParts = createSignatureParts(signature);
|
||||
return createSignatureDeclaration<ConstructorTypeNode>(SyntaxKind.ConstructorType, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type);
|
||||
}
|
||||
}
|
||||
|
||||
const saveInObjectTypeLiteral = inObjectTypeLiteral;
|
||||
inObjectTypeLiteral = true;
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
writeObjectLiteralType(resolved);
|
||||
writer.decreaseIndent();
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
const members = createTypeNodesFromResolvedType(resolved);
|
||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||
}
|
||||
|
||||
function writeObjectLiteralType(resolved: ResolvedType) {
|
||||
for (const signature of resolved.callSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
for (const signature of resolved.constructSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack);
|
||||
buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack);
|
||||
for (const p of resolved.properties) {
|
||||
const t = getTypeOfSymbol(p);
|
||||
if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) {
|
||||
const signatures = getSignaturesOfType(t, SignatureKind.Call);
|
||||
for (const signature of signatures) {
|
||||
writePropertyWithModifiers(p);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
else {
|
||||
writePropertyWithModifiers(p);
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
writeSpace(writer);
|
||||
writeType(t, TypeFormatFlags.None);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
return createTypeLiteralNode(members);
|
||||
}
|
||||
|
||||
function createTypeQueryNodeFromType(type: Type) {
|
||||
const symbol = type.symbol;
|
||||
if (symbol) {
|
||||
// TODO: get entity name instead.
|
||||
const entityName = createIdentifier(symbolToString(symbol));
|
||||
const entityName = createNameFromSymbol(symbol);
|
||||
return createTypeQueryNode(entityName);
|
||||
}
|
||||
}
|
||||
|
||||
function getEntityNameFromSymbol(symbol: Symbol, enclosingDeclaration: Node): EntityName {
|
||||
function createNameFromSymbol(symbol: Symbol): EntityName {
|
||||
symbol; enclosingDeclaration;
|
||||
// TODO: actually implement this
|
||||
return createIdentifier(symbolToString(symbol, enclosingDeclaration));
|
||||
@@ -2636,67 +2573,53 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createTypeLiteralNodeFromType(type: ObjectType) {
|
||||
const resolvedType = resolveStructuredTypeMembers(type);
|
||||
const newMembers = createTypeNodesFromResolvedType(resolvedType);
|
||||
return createTypeLiteralNode(newMembers);
|
||||
}
|
||||
|
||||
function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] {
|
||||
const typeElements: TypeElement[] = [];
|
||||
for(const signature of resolvedType.callSignatures) {
|
||||
signature;
|
||||
throw new Error("call signatures not implemented");
|
||||
for (const signature of resolvedType.callSignatures) {
|
||||
const signatureParts = createSignatureParts(signature);
|
||||
typeElements.push(createSignatureDeclaration<CallSignatureDeclaration>(SyntaxKind.CallSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type));
|
||||
}
|
||||
for (const signature of resolvedType.constructSignatures) {
|
||||
signature;
|
||||
throw new Error("Construct signatures not implemented");
|
||||
const signatureParts = createSignatureParts(signature);
|
||||
typeElements.push(createSignatureDeclaration<ConstructSignatureDeclaration>(SyntaxKind.ConstructSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type));
|
||||
}
|
||||
if (resolvedType.stringIndexInfo) {
|
||||
typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.stringIndexInfo, IndexKind.String));
|
||||
}
|
||||
if (resolvedType.numberIndexInfo) {
|
||||
typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.stringIndexInfo, IndexKind.Number));
|
||||
typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.numberIndexInfo, IndexKind.Number));
|
||||
}
|
||||
|
||||
const members = resolvedType.members;
|
||||
const properties = resolvedType.properties;
|
||||
if (!properties) {
|
||||
return typeElements;
|
||||
}
|
||||
|
||||
members.forEach(memberSymbol => {
|
||||
const oldDeclaration = memberSymbol.declarations && memberSymbol.declarations[0] as TypeElement;
|
||||
for (const propertySymbol of properties) {
|
||||
const propertyType = getTypeOfSymbol(propertySymbol);
|
||||
const oldDeclaration = propertySymbol.declarations && propertySymbol.declarations[0] as TypeElement;
|
||||
if (!oldDeclaration) {
|
||||
return;
|
||||
}
|
||||
|
||||
const kind = oldDeclaration.kind;
|
||||
const memberName = getSynthesizedDeepClone(oldDeclaration.name);
|
||||
const memberType = getTypeOfSymbol(memberSymbol);
|
||||
|
||||
switch (kind) {
|
||||
case SyntaxKind.PropertySignature:
|
||||
const optional = !!oldDeclaration.questionToken;
|
||||
typeElements.push(createPropertySignature(
|
||||
memberName
|
||||
, optional ? createToken(SyntaxKind.QuestionToken) : undefined
|
||||
, createTypeNode(memberType)
|
||||
, /*initializer*/undefined));
|
||||
break;
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
const signatureType = getSignaturesOfSymbol(memberSymbol);
|
||||
signatureType
|
||||
createSignatureDeclaration
|
||||
throw new Error("signature problems.");
|
||||
// name ?: PropertyName;
|
||||
// typeParameters ?: NodeArray<TypeParameterDeclaration>;
|
||||
// parameters: NodeArray<ParameterDeclaration>;
|
||||
// type ?: TypeNode;
|
||||
case SyntaxKind.IndexSignature:
|
||||
throw new Error("type literal constituent not implemented.");
|
||||
default:
|
||||
throw new Error("Unknown resolved member kind.");
|
||||
const propertyName = getSynthesizedDeepClone(oldDeclaration.name);
|
||||
const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;;
|
||||
if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
|
||||
const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
|
||||
for (const signature of signatures) {
|
||||
const signatureParts = createSignatureParts(signature);
|
||||
const methodDeclaration = createSignatureDeclaration<MethodSignature>(SyntaxKind.MethodSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type, propertyName, optionalToken);
|
||||
methodDeclaration.questionToken = optionalToken;
|
||||
typeElements.push(methodDeclaration);
|
||||
}
|
||||
}
|
||||
});
|
||||
else {
|
||||
typeElements.push(createPropertySignature(
|
||||
propertyName
|
||||
, optionalToken
|
||||
, createTypeNode(propertyType)
|
||||
, /*initializer*/undefined));
|
||||
}
|
||||
}
|
||||
return typeElements.length ? typeElements : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-11
@@ -394,29 +394,37 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createSignatureDeclaration<T extends SignatureDeclaration>(kind: SyntaxKind, name: string | PropertyName | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined): T {
|
||||
// TODO: ask if we should have multiple implementations. Some T's can't have question token.
|
||||
export function createSignatureDeclaration<T extends SignatureDeclaration>(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined): T;
|
||||
export function createSignatureDeclaration<T extends SignatureDeclaration & TypeElement>(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined): T;
|
||||
export function createSignatureDeclaration<T extends SignatureDeclaration & TypeElement>(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, name?: string | PropertyName, questionToken?: QuestionToken): T {
|
||||
const signatureDeclaration = createSynthesizedNode(kind) as T;
|
||||
signatureDeclaration.name = asName(name);
|
||||
signatureDeclaration.typeParameters = asNodeArray(typeParameters);
|
||||
signatureDeclaration.parameters = asNodeArray(parameters);
|
||||
signatureDeclaration.type = type;
|
||||
signatureDeclaration.name = asName(name);
|
||||
signatureDeclaration.questionToken = questionToken;
|
||||
return signatureDeclaration;
|
||||
}
|
||||
|
||||
export function updateSignatureDeclaration<T extends SignatureDeclaration>(node: T, name: string | PropertyName | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined): T {
|
||||
return node.name !== name
|
||||
|| node.typeParameters !== typeParameters
|
||||
// TODO: figure out right type annotation for this function.
|
||||
export function updateSignatureDeclaration<T extends SignatureDeclaration>(node: T, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined): T;
|
||||
export function updateSignatureDeclaration<T extends SignatureDeclaration & TypeElement>(node: T, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined): T;
|
||||
export function updateSignatureDeclaration<T extends SignatureDeclaration & TypeElement>(node: T, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined, name?: PropertyName, questionToken?: QuestionToken): T {
|
||||
return node.typeParameters !== typeParameters
|
||||
|| node.parameters !== parameters
|
||||
|| node.type !== type
|
||||
? <T>updateNode(createSignatureDeclaration(node.kind, name, typeParameters, parameters, type), node)
|
||||
|| node.name !== name
|
||||
|| node.questionToken !== questionToken
|
||||
? updateNode(createSignatureDeclaration<T>(node.kind, typeParameters, parameters, type, name, questionToken), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// Signature elements
|
||||
|
||||
export function createPropertySignature(name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature {
|
||||
export function createPropertySignature(name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature {
|
||||
const propertySignature = createSynthesizedNode(SyntaxKind.PropertySignature) as PropertySignature;
|
||||
propertySignature.name = name;
|
||||
propertySignature.name = asName(name);
|
||||
propertySignature.questionToken = questionToken;
|
||||
propertySignature.type = type;
|
||||
propertySignature.initializer = initializer;
|
||||
@@ -511,12 +519,13 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createMethod(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
export function createMethod(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
const node = <MethodDeclaration>createSynthesizedNode(SyntaxKind.MethodDeclaration);
|
||||
node.decorators = asNodeArray(decorators);
|
||||
node.modifiers = asNodeArray(modifiers);
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = asName(name);
|
||||
node.questionToken = questionToken;
|
||||
node.typeParameters = asNodeArray(typeParameters);
|
||||
node.parameters = asNodeArray(parameters);
|
||||
node.type = type;
|
||||
@@ -524,7 +533,7 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateMethod(node: MethodDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
export function updateMethod(node: MethodDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
return node.decorators !== decorators
|
||||
|| node.modifiers !== modifiers
|
||||
|| node.asteriskToken !== asteriskToken
|
||||
@@ -533,7 +542,7 @@ namespace ts {
|
||||
|| node.parameters !== parameters
|
||||
|| node.type !== type
|
||||
|| node.body !== body
|
||||
? updateNode(createMethod(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
|
||||
? updateNode(createMethod(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
|
||||
@@ -2474,6 +2474,8 @@ namespace ts {
|
||||
createTypeParameterDeclarationFromType(type: Type): TypeParameterDeclaration;
|
||||
/** Note that the resulting type node cannot be checked. */
|
||||
createIndexSignatureFromIndexInfo(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration
|
||||
/** Note that the resulting type node cannot be checked. */
|
||||
createParameterDeclarationFromSymbol(parameterSymbol: Symbol): ParameterDeclaration;
|
||||
|
||||
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
||||
getSymbolAtLocation(node: Node): Symbol;
|
||||
|
||||
+25
-31
@@ -245,6 +245,8 @@ namespace ts {
|
||||
case SyntaxKind.EmptyStatement:
|
||||
case SyntaxKind.OmittedExpression:
|
||||
case SyntaxKind.DebuggerStatement:
|
||||
case SyntaxKind.EndOfDeclarationMarker:
|
||||
case SyntaxKind.MissingDeclaration:
|
||||
// No need to visit nodes with no children.
|
||||
return node;
|
||||
|
||||
@@ -260,18 +262,25 @@ namespace ts {
|
||||
|
||||
// Signatures and Signature Elements
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.MethodSignature:
|
||||
return updateSignatureDeclaration(<SignatureDeclaration>node
|
||||
, visitNode((<SignatureDeclaration>node).name, visitor, isPropertyName)
|
||||
, nodesVisitor((<SignatureDeclaration>node).typeParameters, visitor, isTypeParameter)
|
||||
, nodesVisitor((<SignatureDeclaration>node).parameters, visitor, isParameter)
|
||||
, visitParameterList((<SignatureDeclaration>node).parameters, visitor, context, nodesVisitor)
|
||||
, visitNode((<SignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.MethodSignature:
|
||||
return updateSignatureDeclaration(<SignatureDeclaration & TypeElement>node
|
||||
, nodesVisitor((<SignatureDeclaration & TypeElement>node).typeParameters, visitor, isTypeParameter)
|
||||
, visitParameterList((<SignatureDeclaration & TypeElement>node).parameters, visitor, context, nodesVisitor)
|
||||
, visitNode((<SignatureDeclaration & TypeElement>node).type, visitor, isTypeNode)
|
||||
, visitNode((<SignatureDeclaration & TypeElement>node).name, visitor, isPropertyName)
|
||||
, visitNode((<SignatureDeclaration & TypeElement>node).questionToken, visitor, isToken));
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor)
|
||||
, visitParameterList((<IndexSignatureDeclaration>node).parameters, visitor, context, nodesVisitor)
|
||||
, visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier));
|
||||
@@ -290,47 +299,32 @@ namespace ts {
|
||||
return updateDecorator(<Decorator>node,
|
||||
visitNode((<Decorator>node).expression, visitor, isExpression));
|
||||
|
||||
// Keyword Types and This
|
||||
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.NumberKeyword:
|
||||
case SyntaxKind.ObjectKeyword:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.UndefinedKeyword:
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.NeverKeyword:
|
||||
case SyntaxKind.NeverKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
throw new Error("should be caught above");
|
||||
|
||||
// Types
|
||||
|
||||
case SyntaxKind.TypePredicate:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
case SyntaxKind.TypeReference:
|
||||
return updateTypeReferenceNode(<TypeReferenceNode>node
|
||||
, visitNode((<TypeReferenceNode>node).typeName, visitor, isEntityName)
|
||||
, nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor, isTypeNode));
|
||||
, visitNode((<TypeReferenceNode>node).typeName, visitor, isEntityName)
|
||||
, nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
case SyntaxKind.ConstructorType:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
case SyntaxKind.TypeQuery:
|
||||
return updateTypeQueryNode((<TypeQueryNode>node), visitNode((<TypeQueryNode>node).exprName, visitor, isEntityName));
|
||||
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return updateTypeLiteralNode((<TypeLiteralNode>node), nodesVisitor((<TypeLiteralNode>node).members, visitor));
|
||||
|
||||
case SyntaxKind.ArrayType:
|
||||
return updateArrayTypeNode(<ArrayTypeNode>node, visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TupleType:
|
||||
return updateTypleTypeNode((<TupleTypeNode>node), nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
return updateUnionOrIntersectionTypeNode(<UnionOrIntersectionTypeNode>node
|
||||
, nodesVisitor((<UnionOrIntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||
, nodesVisitor((<UnionOrIntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
case SyntaxKind.ThisType:
|
||||
@@ -366,7 +360,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor, isParameter)
|
||||
, visitParameterList((<IndexSignatureDeclaration>node).parameters, visitor, context, nodesVisitor)
|
||||
, visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier));
|
||||
@@ -383,8 +377,9 @@ namespace ts {
|
||||
return updateMethod(<MethodDeclaration>node,
|
||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<MethodDeclaration>node).asteriskToken,
|
||||
visitNode((<MethodDeclaration>node).asteriskToken, visitor, isToken),
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodDeclaration>node).questionToken, visitor, isToken),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
@@ -857,8 +852,7 @@ namespace ts {
|
||||
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
default:
|
||||
throw new Error("not handled");
|
||||
// return node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,56 +85,66 @@ namespace ts.codefix {
|
||||
if (!(signatures && signatures.length > 0)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const optional = !!(symbol.flags & SymbolFlags.Optional);
|
||||
if (declarations.length === 1) {
|
||||
Debug.assert(signatures.length === 1);
|
||||
// TODO: suppress any return type
|
||||
// TODO: get parameters working.
|
||||
// TODO: add support for type parameters.
|
||||
const signature = signatures[0];
|
||||
const newTypeParameters = signature.typeParameters && signature.typeParameters.map(checker.createTypeParameterDeclarationFromType);
|
||||
const newParameterNodes = signature.getParameters().map(symbol => createParameterDeclarationFromSymbol(symbol, enclosingDeclaration, checker));
|
||||
|
||||
const returnType = createTypeNodeExceptAny(checker.getReturnTypeOfSignature(signature), checker);
|
||||
return createStubbedMethod(modifiers, name, newTypeParameters, newParameterNodes, returnType);
|
||||
const signatureParts = getSignatureParts(signature);
|
||||
return createStubbedMethod(modifiers, name, optional, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type);
|
||||
}
|
||||
|
||||
let signatureDeclarations = [];
|
||||
for (let i = 0; i < signatures.length; i++) {
|
||||
// TODO: make signatures instead of methods
|
||||
const signature = signatures[i];
|
||||
const newTypeParameters = signature.typeParameters && signature.typeParameters.map(checker.createTypeParameterDeclarationFromType);
|
||||
const newParameterNodes = signature.getParameters().map(symbol => createParameterDeclarationFromSymbol(symbol, enclosingDeclaration, checker));
|
||||
const returnType = createTypeNodeExceptAny(checker.getReturnTypeOfSignature(signature), checker);
|
||||
const signatureParts = getSignatureParts(signature);
|
||||
signatureDeclarations.push(createMethod(
|
||||
/*decorators*/ undefined
|
||||
, modifiers
|
||||
, /*asteriskToken*/ undefined
|
||||
, name
|
||||
, newTypeParameters
|
||||
, newParameterNodes
|
||||
, returnType
|
||||
, optional ? createToken(SyntaxKind.QuestionToken) : undefined
|
||||
, signatureParts.typeParameters
|
||||
, signatureParts.parameters
|
||||
, signatureParts.type
|
||||
, /*body*/undefined));
|
||||
}
|
||||
|
||||
if (declarations.length > signatures.length) {
|
||||
let signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration);
|
||||
const newTypeParameters = signature.typeParameters && signature.typeParameters.map(checker.createTypeParameterDeclarationFromType);
|
||||
const newParameterNodes = signature.getParameters().map(symbol => createParameterDeclarationFromSymbol(symbol, enclosingDeclaration, checker));
|
||||
const returnType = createTypeNodeExceptAny(checker.getReturnTypeOfSignature(signature), checker);
|
||||
signatureDeclarations.push(createStubbedMethod(modifiers, name, newTypeParameters, newParameterNodes, returnType));
|
||||
const signatureParts = getSignatureParts(signature);
|
||||
signatureDeclarations.push(createStubbedMethod(modifiers, name, optional, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type));
|
||||
}
|
||||
else {
|
||||
Debug.assert(declarations.length === signatures.length);
|
||||
const methodImplementingSignatures = createMethodImplementingSignatures(signatures, name, modifiers);
|
||||
const methodImplementingSignatures = createMethodImplementingSignatures(signatures, name, optional, modifiers);
|
||||
signatureDeclarations.push(methodImplementingSignatures);
|
||||
}
|
||||
return signatureDeclarations;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
||||
type SignatureParts = {
|
||||
typeParameters: TypeParameterDeclaration[];
|
||||
parameters: ParameterDeclaration[];
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
function getSignatureParts(signature: Signature): SignatureParts {
|
||||
return {
|
||||
typeParameters: signature.typeParameters && signature.typeParameters.map(checker.createTypeParameterDeclarationFromType),
|
||||
parameters: signature.getParameters().map(symbol => checker.createParameterDeclarationFromSymbol(symbol)),
|
||||
type: createTypeNodeExceptAny(checker.getReturnTypeOfSignature(signature), checker)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, modifiers: Modifier[] | undefined): MethodDeclaration {
|
||||
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
|
||||
Debug.assert(signatures && signatures.length > 0);
|
||||
|
||||
let maxArgsIndex = 0;
|
||||
@@ -153,7 +163,7 @@ namespace ts.codefix {
|
||||
maxArgsSignature = sig;
|
||||
}
|
||||
}
|
||||
const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
|
||||
const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
|
||||
const maxArgsParameterSymbolNames = signatures[maxArgsIndex].getParameters().map(symbol => symbol.getName());
|
||||
|
||||
const parameters: ParameterDeclaration[] = [];
|
||||
@@ -186,17 +196,19 @@ namespace ts.codefix {
|
||||
return createStubbedMethod(
|
||||
modifiers
|
||||
, name
|
||||
, optional
|
||||
, /*typeParameters*/undefined
|
||||
, parameters
|
||||
, /*returnType*/ undefined);
|
||||
}
|
||||
|
||||
export function createStubbedMethod(modifiers: Modifier[], name: PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType: TypeNode | undefined) {
|
||||
export function createStubbedMethod(modifiers: Modifier[], name: PropertyName, optional: boolean, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType: TypeNode | undefined) {
|
||||
return createMethod(
|
||||
/*decorators*/undefined
|
||||
, modifiers
|
||||
, /*asteriskToken*/undefined
|
||||
, name
|
||||
, optional ? createToken(SyntaxKind.QuestionToken) : undefined
|
||||
, typeParameters
|
||||
, parameters
|
||||
, returnType
|
||||
@@ -223,22 +235,6 @@ namespace ts.codefix {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createParameterDeclarationFromSymbol(parameterSymbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker) {
|
||||
const parameterDeclaration = parameterSymbol.getDeclarations()[0] as ParameterDeclaration;
|
||||
const parameterType = checker.getTypeOfSymbolAtLocation(parameterSymbol, enclosingDeclaration);
|
||||
const parameterTypeNode = checker.createTypeNode(parameterType);
|
||||
// TODO: deep cloning of decorators/any node.
|
||||
const parameterNode = createParameter(
|
||||
parameterDeclaration.decorators && parameterDeclaration.decorators.map(getSynthesizedDeepClone)
|
||||
, parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedDeepClone)
|
||||
, parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken)
|
||||
, getSynthesizedDeepClone(parameterDeclaration.name)
|
||||
, parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken)
|
||||
, parameterTypeNode
|
||||
, /*initializer*/ undefined);
|
||||
return parameterNode;
|
||||
}
|
||||
|
||||
function createTypeNodeExceptAny(type: Type, checker: TypeChecker) {
|
||||
const typeNode = checker.createTypeNode(type);
|
||||
return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined;
|
||||
|
||||
Reference in New Issue
Block a user