mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 04:43:37 -05:00
basic end-to-end building type nodes
This commit is contained in:
@@ -2190,7 +2190,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createTypeNode(type: Type) {
|
||||
let encounteredError = false;
|
||||
// let encounteredError = false;
|
||||
let checkAlias = true;
|
||||
|
||||
return createTypeNodeWorker(type);
|
||||
@@ -2224,9 +2224,17 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Number) {
|
||||
return createKeywordTypeNode(SyntaxKind.NumberKeyword);
|
||||
}
|
||||
if (type.flags & (TypeFlags.Boolean | TypeFlags.StringOrNumberLiteral)) {
|
||||
if(type.flags & TypeFlags.Boolean) {
|
||||
// TODO: this is probably x: boolean. How do we deal with x: true ?
|
||||
return createKeywordTypeNode(SyntaxKind.BooleanKeyword);
|
||||
}
|
||||
if (type.flags & (TypeFlags.StringLiteral)) {
|
||||
// TODO: check if this actually works with boolean.
|
||||
return createLiteralTypeNode((<LiteralType>type).text);
|
||||
return createLiteralTypeNode((createLiteral((<LiteralType>type).text)));
|
||||
}
|
||||
if (type.flags & (TypeFlags.NumberLiteral)) {
|
||||
// TODO: check if this actually works with boolean.
|
||||
return createLiteralTypeNode((createNumericLiteral((<LiteralType>type).text)));
|
||||
}
|
||||
if (type.flags & TypeFlags.Void) {
|
||||
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
|
||||
@@ -2279,11 +2287,10 @@ namespace ts {
|
||||
|
||||
if (objectFlags & ObjectFlags.ClassOrInterface) {
|
||||
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||
// If type is a class or interface type that wasn't hit by the isSymbolAccessible check above,
|
||||
// type must be an anonymous class or interface.
|
||||
|
||||
encounteredError = true;
|
||||
return undefined;
|
||||
const name = getNameOfSymbol(type.symbol);
|
||||
// TODO: handle type arguments.
|
||||
// TODO: handle anonymous classes.
|
||||
return createTypeReferenceNode(name);
|
||||
}
|
||||
|
||||
if (objectFlags & ObjectFlags.Reference) {
|
||||
|
||||
@@ -234,23 +234,75 @@ namespace ts {
|
||||
return <KeywordTypeNode>createSynthesizedNode(kind);
|
||||
}
|
||||
|
||||
|
||||
export function createLiteralTypeNode(value: string | number | boolean) {
|
||||
const literal = createLiteral(value);
|
||||
export function createLiteralTypeNode(literal: Expression) {
|
||||
const literalTypeNode = createSynthesizedNode(SyntaxKind.LiteralType) as LiteralTypeNode;
|
||||
literalTypeNode.literal = literal;
|
||||
return literalTypeNode;
|
||||
}
|
||||
|
||||
export function updateLiteralTypeNode(node: LiteralTypeNode, literal: Expression) {
|
||||
return node.literal !== literal
|
||||
? updateNode(createLiteralTypeNode(literal), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// TODO: handle qualified names, ie EntityName's.
|
||||
export function createTypeReferenceNode(typeName: string | Identifier, typeArguments?: NodeArray<TypeNode>) {
|
||||
const typeReference = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
|
||||
typeReference.typeName = asName(typeName);
|
||||
typeReference.typeName.parent
|
||||
typeReference.typeArguments = typeArguments;
|
||||
return typeReference;
|
||||
}
|
||||
|
||||
export function updateTypeReferenceNode(node: TypeReferenceNode, typeName: Identifier, typeArguments?: NodeArray<TypeNode>) {
|
||||
return node.typeName !== typeName
|
||||
|| node.typeArguments !== typeArguments
|
||||
? updateNode(createTypeReferenceNode(typeName, typeArguments), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
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 {
|
||||
const unionTypeNode = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode;
|
||||
unionTypeNode.types = asNodeArray(types);
|
||||
return unionTypeNode;
|
||||
}
|
||||
|
||||
export function updateUnionOrIntersectionTypeNode(node: UnionOrIntersectionTypeNode, kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: NodeArray<TypeNode>) {
|
||||
return node.types !== types
|
||||
|| node.kind !== kind
|
||||
? updateNode(createUnionOrIntersectionTypeNode(kind, types), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createTypeLiteralNode(members: TypeElement[]) {
|
||||
const typeLiteralNode = createSynthesizedNode(SyntaxKind.LiteralType) as TypeLiteralNode;
|
||||
typeLiteralNode.members = asNodeArray(members);
|
||||
return typeLiteralNode;
|
||||
}
|
||||
|
||||
export function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray<TypeElement>) {
|
||||
return node.members !== members
|
||||
? updateNode(createTypeLiteralNode(members), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createTupleTypeNode(elementTypes: TypeNode[]) {
|
||||
const tupleTypeNode = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode;
|
||||
tupleTypeNode.elementTypes = asNodeArray(elementTypes);
|
||||
return tupleTypeNode;
|
||||
}
|
||||
|
||||
export function updateTypleTypeNode(node: TupleTypeNode, elementTypes: TypeNode[]) {
|
||||
return node.elementTypes !== elementTypes
|
||||
? updateNode(createTupleTypeNode(elementTypes), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// Type Declarations
|
||||
|
||||
export function createTypeParameterNode(name: string | Identifier, constraint?: TypeNode, defaultParameter?: TypeNode) {
|
||||
const typeParameter = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration;
|
||||
typeParameter.name = asName(name);
|
||||
@@ -260,31 +312,6 @@ namespace ts {
|
||||
return typeParameter;
|
||||
}
|
||||
|
||||
export function createUnionTypeNode(types: NodeArray<TypeNode>) {
|
||||
const unionTypeNode = createSynthesizedNode(SyntaxKind.UnionType) as UnionTypeNode;
|
||||
unionTypeNode.types = asNodeArray(types);
|
||||
return unionTypeNode;
|
||||
}
|
||||
|
||||
export function createIntersectionTypeNode(types: NodeArray<TypeNode>) {
|
||||
const intersectionTypeNode = createSynthesizedNode(SyntaxKind.IntersectionType) as IntersectionTypeNode;
|
||||
intersectionTypeNode.types = asNodeArray(types);
|
||||
return intersectionTypeNode;
|
||||
}
|
||||
|
||||
export function createTypeLiteralNode(typeElements: TypeElement[]) {
|
||||
const typeLiteralNode = createSynthesizedNode(SyntaxKind.LiteralType) as TypeLiteralNode;
|
||||
typeLiteralNode.members = asNodeArray(typeElements);
|
||||
return typeLiteralNode;
|
||||
}
|
||||
|
||||
export function createTupleTypeNode(types: NodeArray<TypeNode>) {
|
||||
const tupleTypeNode = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode;
|
||||
tupleTypeNode.elementTypes = asNodeArray(types);
|
||||
return tupleTypeNode;
|
||||
}
|
||||
|
||||
|
||||
// Signature elements
|
||||
|
||||
/** Note, can also be used to construct index signatures. */
|
||||
@@ -298,10 +325,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
// TODO: check usage of name...
|
||||
export function createIndexSignature(parameter: ParameterDeclaration, type: TypeNode, decorators?: Decorator[], modifiers?: Modifier[]): IndexSignatureDeclaration {
|
||||
// TODO: create entry in visitor.ts
|
||||
export function createIndexSignatureDeclaration(parameters: ParameterDeclaration[], type: TypeNode, decorators?: Decorator[], modifiers?: Modifier[]): IndexSignatureDeclaration {
|
||||
const indexSignature = createSignature(
|
||||
SyntaxKind.IndexSignature
|
||||
, asNodeArray([parameter])
|
||||
, asNodeArray(parameters)
|
||||
, /*name*/ undefined
|
||||
, /*typeParameters*/undefined
|
||||
, type) as IndexSignatureDeclaration;
|
||||
@@ -310,6 +338,15 @@ namespace ts {
|
||||
return indexSignature;
|
||||
}
|
||||
|
||||
export function updateIndexSignatureDeclaration(node: IndexSignatureDeclaration, parameters: ParameterDeclaration[], type: TypeNode, decorators?: Decorator[], modifiers?: Modifier[]) {
|
||||
return node.parameters !== parameters
|
||||
|| node.type !== type
|
||||
|| node.decorators !== decorators
|
||||
|| node.modifiers !== modifiers
|
||||
? updateNode(createIndexSignatureDeclaration(parameters, type, decorators, modifiers), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createParameter(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) {
|
||||
const node = <ParameterDeclaration>createSynthesizedNode(SyntaxKind.Parameter);
|
||||
node.decorators = asNodeArray(decorators);
|
||||
|
||||
@@ -673,7 +673,7 @@ namespace ts {
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
export interface BindingElement extends Declaration {
|
||||
export interface BindingElement extends Declaration {
|
||||
kind: SyntaxKind.BindingElement;
|
||||
parent?: BindingPattern;
|
||||
propertyName?: PropertyName; // Binding property name (in object binding pattern)
|
||||
@@ -849,19 +849,17 @@ namespace ts {
|
||||
_typeNodeBrand: any;
|
||||
}
|
||||
|
||||
export type KeywordKind = SyntaxKind.AnyKeyword
|
||||
| SyntaxKind.NumberKeyword
|
||||
| SyntaxKind.ObjectKeyword
|
||||
| SyntaxKind.BooleanKeyword
|
||||
| SyntaxKind.StringKeyword
|
||||
| SyntaxKind.SymbolKeyword
|
||||
| SyntaxKind.VoidKeyword
|
||||
| SyntaxKind.UndefinedKeyword
|
||||
| SyntaxKind.NullKeyword
|
||||
| SyntaxKind.NeverKeyword;
|
||||
|
||||
export interface KeywordTypeNode extends TypeNode {
|
||||
kind: KeywordKind;
|
||||
kind: SyntaxKind.AnyKeyword
|
||||
| SyntaxKind.NumberKeyword
|
||||
| SyntaxKind.ObjectKeyword
|
||||
| SyntaxKind.BooleanKeyword
|
||||
| SyntaxKind.StringKeyword
|
||||
| SyntaxKind.SymbolKeyword
|
||||
| SyntaxKind.VoidKeyword
|
||||
| SyntaxKind.UndefinedKeyword
|
||||
| SyntaxKind.NullKeyword
|
||||
| SyntaxKind.NeverKeyword;
|
||||
}
|
||||
|
||||
export interface ThisTypeNode extends TypeNode {
|
||||
|
||||
@@ -212,16 +212,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
const kind = node.kind;
|
||||
|
||||
// No need to visit nodes with no children.
|
||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// We do not yet support types.
|
||||
if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SemicolonClassElement:
|
||||
case SyntaxKind.EmptyStatement:
|
||||
@@ -241,6 +237,13 @@ namespace ts {
|
||||
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
|
||||
|
||||
// Signature elements
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor)
|
||||
, visitNode((<IndexSignatureDeclaration>node).type, visitor)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator)
|
||||
, nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier));
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
@@ -254,7 +257,60 @@ namespace ts {
|
||||
return updateDecorator(<Decorator>node,
|
||||
visitNode((<Decorator>node).expression, visitor, isExpression));
|
||||
|
||||
// Type member
|
||||
// Keyword Types
|
||||
|
||||
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:
|
||||
return node;
|
||||
|
||||
// Types
|
||||
|
||||
case SyntaxKind.TypePredicate:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.TypeReference:
|
||||
return updateTypeReferenceNode(<TypeReferenceNode>node
|
||||
, visitNode((<TypeReferenceNode>node).typeName as Identifier, visitor)
|
||||
, nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor)
|
||||
);
|
||||
case SyntaxKind.FunctionType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.ConstructorType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.TypeQuery:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.TypeLiteral:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.ArrayType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.TupleType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.ThisType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.TypeOperator:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.MappedType:
|
||||
throw new Error("reached unsupported type.");
|
||||
case SyntaxKind.LiteralType:
|
||||
throw new Error("reached unsupported type.");
|
||||
|
||||
// Type members
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
|
||||
@@ -62,13 +62,12 @@ namespace ts.codefix {
|
||||
, "name"
|
||||
, /*questionToken*/ undefined
|
||||
, stringTypeNode);
|
||||
const indexSignature = createIndexSignature(indexingParameter, typeNode);
|
||||
const indexSignature = createIndexSignatureDeclaration([indexingParameter], typeNode);
|
||||
|
||||
// const startPos = classDeclaration.members.pos;
|
||||
const indexSignatureChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
indexSignatureChangeTracker.insertNodeAfter(sourceFile, openBrace, indexSignature, { insertTrailingNewLine: true });
|
||||
|
||||
return [{
|
||||
return [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
||||
changes: propertyChangeTracker.getChanges()
|
||||
},
|
||||
|
||||
@@ -1386,6 +1386,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getOpenBraceOfClassLike(declaration: ClassLikeDeclaration, sourceFile: SourceFile) {
|
||||
return getTokenAtPosition(sourceFile, declaration.members.pos);
|
||||
return getTokenAtPosition(sourceFile, declaration.members.pos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user