type predicate support
This commit is contained in:
parent
a39bb0aaaa
commit
7340c4ca1e
|
@ -2610,18 +2610,27 @@ namespace ts {
|
|||
/*initializer*/ undefined);
|
||||
const typeNode = typeToTypeNodeHelper(indexInfo.type);
|
||||
return createIndexSignatureDeclaration(
|
||||
[indexingParameter],
|
||||
typeNode,
|
||||
/*decorators*/ undefined,
|
||||
indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined);
|
||||
indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined,
|
||||
[indexingParameter],
|
||||
typeNode);
|
||||
}
|
||||
|
||||
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind): SignatureDeclaration {
|
||||
|
||||
const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter));
|
||||
const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter));
|
||||
let returnTypeNode: TypeNode | TypePredicate;
|
||||
if (signature.typePredicate) {
|
||||
const typePredicate = signature.typePredicate;
|
||||
const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier((<IdentifierTypePredicate>typePredicate).parameterName) : createThisTypeNode();
|
||||
const typeNode = typeToTypeNodeHelper(typePredicate.type);
|
||||
returnTypeNode = createTypePredicateNode(parameterName, typeNode);
|
||||
}
|
||||
else {
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
const returnTypeNode = returnType && typeToTypeNodeHelper(returnType);
|
||||
returnTypeNode = returnType && typeToTypeNodeHelper(returnType);
|
||||
}
|
||||
const returnTypeNodeExceptAny = returnTypeNode && returnTypeNode.kind !== SyntaxKind.AnyKeyword ? returnTypeNode : undefined;
|
||||
|
||||
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNodeExceptAny);
|
||||
|
|
|
@ -286,6 +286,10 @@ namespace ts {
|
|||
return <KeywordTypeNode>createSynthesizedNode(kind);
|
||||
}
|
||||
|
||||
export function createThisTypeNode() {
|
||||
return <ThisTypeNode>createSynthesizedNode(SyntaxKind.ThisType);
|
||||
}
|
||||
|
||||
export function createLiteralTypeNode(literal: Expression) {
|
||||
const literalTypeNode = createSynthesizedNode(SyntaxKind.LiteralType) as LiteralTypeNode;
|
||||
literalTypeNode.literal = literal;
|
||||
|
@ -312,6 +316,20 @@ namespace ts {
|
|||
: node;
|
||||
}
|
||||
|
||||
export function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode) {
|
||||
const typePredicateNode = createSynthesizedNode(SyntaxKind.TypePredicate) as TypePredicateNode;
|
||||
typePredicateNode.parameterName = asName(parameterName);
|
||||
typePredicateNode.type = type;
|
||||
return typePredicateNode;
|
||||
}
|
||||
|
||||
export function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) {
|
||||
return node.parameterName !== parameterName
|
||||
|| node.type !== type
|
||||
? updateNode(createTypePredicateNode(parameterName, type), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createTypeQueryNode(exprName: EntityName) {
|
||||
const typeQueryNode = createSynthesizedNode(SyntaxKind.TypeQuery) as TypeQueryNode;
|
||||
typeQueryNode.exprName = exprName;
|
||||
|
@ -455,21 +473,21 @@ namespace ts {
|
|||
: node;
|
||||
}
|
||||
|
||||
export function createIndexSignatureDeclaration(parameters: ParameterDeclaration[], type: TypeNode, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined): IndexSignatureDeclaration {
|
||||
export function createIndexSignatureDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration {
|
||||
const indexSignature = createSynthesizedNode(SyntaxKind.IndexSignature) as IndexSignatureDeclaration;
|
||||
indexSignature.parameters = asNodeArray(parameters);
|
||||
indexSignature.type = type;
|
||||
indexSignature.decorators = asNodeArray(decorators);
|
||||
indexSignature.modifiers = asNodeArray(modifiers);
|
||||
indexSignature.parameters = createNodeArray(parameters);
|
||||
indexSignature.type = type;
|
||||
return indexSignature;
|
||||
}
|
||||
|
||||
export function updateIndexSignatureDeclaration(node: IndexSignatureDeclaration, parameters: ParameterDeclaration[], type: TypeNode, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined) {
|
||||
export function updateIndexSignatureDeclaration(node: IndexSignatureDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], type: TypeNode) {
|
||||
return node.parameters !== parameters
|
||||
|| node.type !== type
|
||||
|| node.decorators !== decorators
|
||||
|| node.modifiers !== modifiers
|
||||
? updateNode(createIndexSignatureDeclaration(parameters, type, decorators, modifiers), node)
|
||||
? updateNode(createIndexSignatureDeclaration(decorators, modifiers, parameters, type), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
|
@ -542,7 +560,7 @@ namespace ts {
|
|||
node.name = asName(name);
|
||||
node.questionToken = questionToken;
|
||||
node.typeParameters = asNodeArray(typeParameters);
|
||||
node.parameters = asNodeArray(parameters);
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = type;
|
||||
node.body = body;
|
||||
return node;
|
||||
|
@ -2052,7 +2070,8 @@ namespace ts {
|
|||
function asName(name: string | BindingName): BindingName;
|
||||
function asName(name: string | PropertyName): PropertyName;
|
||||
function asName(name: string | EntityName): EntityName;
|
||||
function asName(name: string | Identifier | BindingName | PropertyName | QualifiedName) {
|
||||
function asName(name: string | Identifier | ThisTypeNode): Identifier | ThisTypeNode;
|
||||
function asName(name: string | Identifier | BindingName | PropertyName | QualifiedName | ThisTypeNode) {
|
||||
return typeof name === "string" ? createIdentifier(name) : name;
|
||||
}
|
||||
|
||||
|
@ -2060,7 +2079,7 @@ namespace ts {
|
|||
return typeof value === "string" || typeof value === "number" ? createLiteral(value) : value;
|
||||
}
|
||||
|
||||
export function asNodeArray<T extends Node>(array: T[] | undefined): NodeArray<T> | undefined {
|
||||
function asNodeArray<T extends Node>(array: T[] | undefined): NodeArray<T> | undefined {
|
||||
return array ? createNodeArray(array) : undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -1042,7 +1042,7 @@ namespace ts {
|
|||
kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword;
|
||||
}
|
||||
|
||||
export interface ThisExpression extends PrimaryExpression, TypeNode {
|
||||
export interface ThisExpression extends PrimaryExpression, KeywordTypeNode {
|
||||
kind: SyntaxKind.ThisKeyword;
|
||||
}
|
||||
|
||||
|
@ -3248,12 +3248,6 @@ namespace ts {
|
|||
declaration?: SignatureDeclaration;
|
||||
}
|
||||
|
||||
export interface SignatureParts {
|
||||
typeParameters: TypeParameterDeclaration[] | undefined;
|
||||
parameters: ParameterDeclaration[];
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
|
|
|
@ -3735,7 +3735,7 @@ namespace ts {
|
|||
* of a TypeNode.
|
||||
*/
|
||||
export function isTypeNode(node: Node): node is TypeNode {
|
||||
return node && isTypeNodeKind(node.kind);
|
||||
return isTypeNodeKind(node.kind);
|
||||
}
|
||||
|
||||
// Binding patterns
|
||||
|
|
|
@ -3,26 +3,6 @@
|
|||
/// <reference path="utilities.ts" />
|
||||
|
||||
namespace ts {
|
||||
export const nullTransformationContext: TransformationContext = {
|
||||
enableEmitNotification: noop,
|
||||
enableSubstitution: noop,
|
||||
endLexicalEnvironment: () => undefined,
|
||||
getCompilerOptions: notImplemented,
|
||||
getEmitHost: notImplemented,
|
||||
getEmitResolver: notImplemented,
|
||||
hoistFunctionDeclaration: noop,
|
||||
hoistVariableDeclaration: noop,
|
||||
isEmitNotificationEnabled: notImplemented,
|
||||
isSubstitutionEnabled: notImplemented,
|
||||
onEmitNode: noop,
|
||||
onSubstituteNode: notImplemented,
|
||||
readEmitHelpers: notImplemented,
|
||||
requestEmitHelper: noop,
|
||||
resumeLexicalEnvironment: noop,
|
||||
startLexicalEnvironment: noop,
|
||||
suspendLexicalEnvironment: noop
|
||||
};
|
||||
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
|
@ -234,7 +214,7 @@ namespace ts {
|
|||
const kind = node.kind;
|
||||
|
||||
// No need to visit nodes with no children.
|
||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) {
|
||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) || kind === SyntaxKind.ThisType) {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -293,10 +273,10 @@ namespace ts {
|
|||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node,
|
||||
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));
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<IndexSignatureDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
|
@ -314,13 +294,16 @@ namespace ts {
|
|||
|
||||
// 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));
|
||||
|
||||
case SyntaxKind.TypePredicate:
|
||||
return updateTypePredicateNode(<TypePredicateNode>node,
|
||||
visitNode((<TypePredicateNode>node).parameterName, visitor),
|
||||
visitNode((<TypePredicateNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
return updateTypeQueryNode((<TypeQueryNode>node), visitNode((<TypeQueryNode>node).exprName, visitor, isEntityName));
|
||||
|
||||
|
@ -339,9 +322,8 @@ namespace ts {
|
|||
nodesVisitor((<UnionOrIntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
case SyntaxKind.ThisType:
|
||||
throw new Error("reached unsupported type in visitor.");
|
||||
Debug.fail("not implemented.");
|
||||
|
||||
case SyntaxKind.TypeOperator:
|
||||
return updateTypeOperatorNode(<TypeOperatorNode>node, visitNode((<TypeOperatorNode>node).type, visitor, isTypeNode));
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
|
@ -376,13 +358,6 @@ namespace ts {
|
|||
visitNode((<PropertySignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertySignature>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node,
|
||||
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));
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
|
|
|
@ -65,10 +65,10 @@ namespace ts.codefix {
|
|||
stringTypeNode,
|
||||
/*initializer*/ undefined);
|
||||
const indexSignature = createIndexSignatureDeclaration(
|
||||
[indexingParameter],
|
||||
typeNode,
|
||||
/*decorators*/undefined,
|
||||
/*modifiers*/ undefined);
|
||||
/*modifiers*/ undefined,
|
||||
[indexingParameter],
|
||||
typeNode);
|
||||
|
||||
const indexSignatureChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
indexSignatureChangeTracker.insertNodeAfter(sourceFile, openBrace, indexSignature, { suffix: context.newLineCharacter });
|
||||
|
|
|
@ -230,12 +230,4 @@ namespace ts.codefix {
|
|||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function stripComments(node: Node): Node {
|
||||
if (node === undefined) {
|
||||
return node;
|
||||
}
|
||||
const strippedChildren = visitEachChild(node, stripComments, nullTransformationContext);
|
||||
return strippedChildren === node ? getSynthesizedClone(strippedChildren) : strippedChildren;
|
||||
}
|
||||
}
|
|
@ -528,6 +528,26 @@ namespace ts.textChanges {
|
|||
return skipTrivia(s, 0) === s.length;
|
||||
}
|
||||
|
||||
const nullTransformationContext: TransformationContext = {
|
||||
enableEmitNotification: noop,
|
||||
enableSubstitution: noop,
|
||||
endLexicalEnvironment: () => undefined,
|
||||
getCompilerOptions: notImplemented,
|
||||
getEmitHost: notImplemented,
|
||||
getEmitResolver: notImplemented,
|
||||
hoistFunctionDeclaration: noop,
|
||||
hoistVariableDeclaration: noop,
|
||||
isEmitNotificationEnabled: notImplemented,
|
||||
isSubstitutionEnabled: notImplemented,
|
||||
onEmitNode: noop,
|
||||
onSubstituteNode: notImplemented,
|
||||
readEmitHelpers: notImplemented,
|
||||
requestEmitHelper: noop,
|
||||
resumeLexicalEnvironment: noop,
|
||||
startLexicalEnvironment: noop,
|
||||
suspendLexicalEnvironment: noop
|
||||
};
|
||||
|
||||
function assignPositionsToNode(node: Node): Node {
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||
// create proxy node for non synthesized nodes
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// interface I {
|
||||
//// f(i: any): i is I;
|
||||
//// f(): this is I;
|
||||
//// }
|
||||
////
|
||||
//// class C implements I {[| |]}
|
||||
|
||||
verify.rangeAfterCodeFix(`
|
||||
f(i: any): i is I;
|
||||
f(): this is I;
|
||||
f(i?: any) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
`);
|
Loading…
Reference in a new issue