Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Basic parsing+handling code that is aware of named type arguments, no…
… check yet
  • Loading branch information
weswigham committed Apr 25, 2018
commit b8812266a5b6b25a440ee8a07f50698e9eb0ced7
225 changes: 162 additions & 63 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ namespace ts {
return emitCallSignature(<CallSignatureDeclaration>node);
case SyntaxKind.ConstructSignature:
return emitConstructSignature(<ConstructSignatureDeclaration>node);
case SyntaxKind.NamedTypeArgument:
return emitNamedTypeArgument(<NamedTypeArgument>node);
case SyntaxKind.IndexSignature:
return emitIndexSignature(<IndexSignatureDeclaration>node);

Expand Down Expand Up @@ -975,7 +977,7 @@ namespace ts {
function emitIdentifier(node: Identifier) {
const writeText = node.symbol ? writeSymbol : write;
writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol);
emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments
emitTypeParameters(node, node.typeParameters);
}

//
Expand Down Expand Up @@ -1125,6 +1127,14 @@ namespace ts {
writeSemicolon();
}

function emitNamedTypeArgument(node: NamedTypeArgument) {
emit(node.name);
writeSpace();
writePunctuation("=");
writeSpace();
emit(node.type);
}

function emitIndexSignature(node: IndexSignatureDeclaration) {
emitDecorators(node, node.decorators);
emitModifiers(node, node.modifiers);
Expand Down Expand Up @@ -2674,12 +2684,12 @@ namespace ts {
emitList(parentNode, decorators, ListFormat.Decorators);
}

function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeNode>) {
function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeArgument>) {
emitList(parentNode, typeArguments, ListFormat.TypeArguments);
}

function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray<TypeParameterDeclaration>) {
if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures
function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression | Identifier, typeParameters: NodeArray<TypeParameterDeclaration>) {
if ((isFunctionLike(parentNode) || isIdentifier(parentNode)) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures
return emitTypeArguments(parentNode, parentNode.typeArguments);
}
emitList(parentNode, typeParameters, ListFormat.TypeParameters);
Expand Down
84 changes: 54 additions & 30 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,26 +112,30 @@ namespace ts {

export function createIdentifier(text: string): Identifier;
/* @internal */
export function createIdentifier(text: string, typeArguments: ReadonlyArray<TypeNode | TypeParameterDeclaration>): Identifier; // tslint:disable-line unified-signatures
export function createIdentifier(text: string, typeArguments?: ReadonlyArray<TypeNode | TypeParameterDeclaration>): Identifier {
export function createIdentifier(text: string, typeArguments: ReadonlyArray<TypeArgument>, typeParameters: ReadonlyArray<TypeParameterDeclaration>): Identifier; // tslint:disable-line unified-signatures
export function createIdentifier(text: string, typeArguments?: ReadonlyArray<TypeArgument>, typeParameters?: ReadonlyArray<TypeParameterDeclaration>): Identifier {
const node = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
node.escapedText = escapeLeadingUnderscores(text);
node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown;
node.autoGenerateFlags = GeneratedIdentifierFlags.None;
node.autoGenerateId = 0;
if (typeArguments) {
node.typeArguments = createNodeArray(typeArguments as ReadonlyArray<TypeNode>);
node.typeArguments = createNodeArray(typeArguments);
}
if (typeParameters) {
node.typeParameters = createNodeArray(typeParameters);
}
return node;
}

export function updateIdentifier(node: Identifier): Identifier;
/* @internal */
export function updateIdentifier(node: Identifier, typeArguments: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier; // tslint:disable-line unified-signatures
export function updateIdentifier(node: Identifier, typeArguments?: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier {
return node.typeArguments !== typeArguments
? updateNode(createIdentifier(idText(node), typeArguments), node)
: node;
export function updateIdentifier(node: Identifier, typeArguments: NodeArray<TypeArgument> | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined): Identifier; // tslint:disable-line unified-signatures
export function updateIdentifier(node: Identifier, typeArguments?: NodeArray<TypeArgument> | undefined, typeParameters?: NodeArray<TypeParameterDeclaration> | undefined): Identifier {
return node.typeArguments !== typeArguments ||
node.typeParameters !== typeParameters
? updateNode(createIdentifier(idText(node), typeArguments, typeParameters), node)
: node;
}

let nextAutoGenerateId = 0;
Expand Down Expand Up @@ -605,6 +609,20 @@ namespace ts {
return updateSignatureDeclaration(node, typeParameters, parameters, type);
}

export function createNamedTypeArgument(name: string | Identifier, type: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.NamedTypeArgument) as NamedTypeArgument;
node.name = asName(name);
node.type = type;
return node;
}

export function updateNamedTypeArgument(node: NamedTypeArgument, name: Identifier, type: TypeNode) {
return node.name !== name ||
node.type !== type
? updateNode(createNamedTypeArgument(name, type), node)
: node;
}

export function createIndexSignature(
decorators: ReadonlyArray<Decorator> | undefined,
modifiers: ReadonlyArray<Modifier> | undefined,
Expand Down Expand Up @@ -670,14 +688,14 @@ namespace ts {
: node;
}

export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: ReadonlyArray<TypeNode> | undefined) {
export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: ReadonlyArray<TypeArgument> | undefined) {
const node = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
node.typeName = asName(typeName);
node.typeArguments = typeArguments && parenthesizeTypeParameters(typeArguments);
return node;
}

export function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined) {
export function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeArgument> | undefined) {
return node.typeName !== typeName
|| node.typeArguments !== typeArguments
? updateNode(createTypeReferenceNode(typeName, typeArguments), node)
Expand Down Expand Up @@ -806,7 +824,7 @@ namespace ts {
: node;
}

export function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeNode>, isTypeOf?: boolean) {
export function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeArgument>, isTypeOf?: boolean) {
const node = <ImportTypeNode>createSynthesizedNode(SyntaxKind.ImportType);
node.argument = argument;
node.qualifier = qualifier;
Expand All @@ -815,7 +833,7 @@ namespace ts {
return node;
}

export function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeNode>, isTypeOf?: boolean) {
export function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeArgument>, isTypeOf?: boolean) {
return node.argument !== argument
|| node.qualifier !== qualifier
|| node.typeArguments !== typeArguments
Expand Down Expand Up @@ -1000,31 +1018,31 @@ namespace ts {
: node;
}

export function createCall(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression>) {
export function createCall(expression: Expression, typeArguments: ReadonlyArray<TypeArgument> | undefined, argumentsArray: ReadonlyArray<Expression>) {
const node = <CallExpression>createSynthesizedNode(SyntaxKind.CallExpression);
node.expression = parenthesizeForAccess(expression);
node.typeArguments = asNodeArray(typeArguments);
node.arguments = parenthesizeListElements(createNodeArray(argumentsArray));
return node;
}

export function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression>) {
export function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray<TypeArgument> | undefined, argumentsArray: ReadonlyArray<Expression>) {
return node.expression !== expression
|| node.typeArguments !== typeArguments
|| node.arguments !== argumentsArray
? updateNode(createCall(expression, typeArguments, argumentsArray), node)
: node;
}

export function createNew(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined) {
export function createNew(expression: Expression, typeArguments: ReadonlyArray<TypeArgument> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined) {
const node = <NewExpression>createSynthesizedNode(SyntaxKind.NewExpression);
node.expression = parenthesizeForNew(expression);
node.typeArguments = asNodeArray(typeArguments);
node.arguments = argumentsArray ? parenthesizeListElements(createNodeArray(argumentsArray)) : undefined;
return node;
}

export function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined) {
export function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray<TypeArgument> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined) {
return node.expression !== expression
|| node.typeArguments !== typeArguments
|| node.arguments !== argumentsArray
Expand All @@ -1033,14 +1051,14 @@ namespace ts {
}

export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeArgument>, template: TemplateLiteral): TaggedTemplateExpression;
/** @internal */
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral) {
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeArgument> | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeArgument> | TemplateLiteral, template?: TemplateLiteral) {
const node = <TaggedTemplateExpression>createSynthesizedNode(SyntaxKind.TaggedTemplateExpression);
node.tag = parenthesizeForAccess(tag);
if (template) {
node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray<TypeNode>);
node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray<TypeArgument>);
node.template = template!;
}
else {
Expand All @@ -1051,8 +1069,8 @@ namespace ts {
}

export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral) {
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeArgument>, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeArgument> | TemplateLiteral, template?: TemplateLiteral) {
return node.tag !== tag
|| (template
? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template
Expand Down Expand Up @@ -1422,14 +1440,14 @@ namespace ts {
return <OmittedExpression>createSynthesizedNode(SyntaxKind.OmittedExpression);
}

export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray<TypeNode>, expression: Expression) {
export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray<TypeArgument>, expression: Expression) {
const node = <ExpressionWithTypeArguments>createSynthesizedNode(SyntaxKind.ExpressionWithTypeArguments);
node.expression = parenthesizeForAccess(expression);
node.typeArguments = asNodeArray(typeArguments);
return node;
}

export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray<TypeNode>, expression: Expression) {
export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray<TypeArgument>, expression: Expression) {
return node.typeArguments !== typeArguments
|| node.expression !== expression
? updateNode(createExpressionWithTypeArguments(typeArguments, expression), node)
Expand Down Expand Up @@ -2197,31 +2215,31 @@ namespace ts {
: node;
}

export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeArgument> | undefined, attributes: JsxAttributes) {
const node = <JsxSelfClosingElement>createSynthesizedNode(SyntaxKind.JsxSelfClosingElement);
node.tagName = tagName;
node.typeArguments = typeArguments && createNodeArray(typeArguments);
node.attributes = attributes;
return node;
}

export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeArgument> | undefined, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.typeArguments !== typeArguments
|| node.attributes !== attributes
? updateNode(createJsxSelfClosingElement(tagName, typeArguments, attributes), node)
: node;
}

export function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
export function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeArgument> | undefined, attributes: JsxAttributes) {
const node = <JsxOpeningElement>createSynthesizedNode(SyntaxKind.JsxOpeningElement);
node.tagName = tagName;
node.typeArguments = typeArguments && createNodeArray(typeArguments);
node.attributes = attributes;
return node;
}

export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeArgument> | undefined, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.typeArguments !== typeArguments
|| node.attributes !== attributes
Expand Down Expand Up @@ -4242,11 +4260,17 @@ namespace ts {
return createNodeArray(sameMap(members, parenthesizeElementTypeMember));
}

export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeNode>) {
export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeNode>): MutableNodeArray<TypeNode>;
export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeArgument>): MutableNodeArray<TypeArgument>;
export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeNode> | ReadonlyArray<TypeArgument>): MutableNodeArray<TypeNode> | MutableNodeArray<TypeArgument> {
if (some(typeParameters)) {
const params: TypeNode[] = [];
const params: TypeArgument[] = [];
for (let i = 0; i < typeParameters.length; ++i) {
const entry = typeParameters[i];
if (isNamedTypeArgument(entry)) {
params.push(entry);
continue;
}
params.push(i === 0 && isFunctionOrConstructorTypeNode(entry) && entry.typeParameters ?
createParenthesizedType(entry) :
entry);
Expand Down
Loading