From 27fe2df203eb552976c853b704f6682eb8e81ae2 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 13 Mar 2017 20:20:26 -0700 Subject: [PATCH] some missed token bugs --- src/compiler/checker.ts | 11 ++---- src/compiler/factory.ts | 9 +++-- src/compiler/transformers/esnext.ts | 1 + src/compiler/types.ts | 2 +- src/compiler/visitor.ts | 1 + src/services/codefixes/fixAddMissingMember.ts | 3 +- src/services/codefixes/helpers.ts | 39 +++++++++---------- src/services/textChanges.ts | 2 +- .../codeFixClassExtendAbstractGetterSetter.ts | 2 +- 9 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea7c01b9735..ca105c41139 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2361,7 +2361,7 @@ namespace ts { return createArrayTypeNode(elementType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { - return createTupleTypeNode(mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)))); + return createTupleTypeNode(typeArguments.length > 0 ? mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type))) : undefined); } else { // TODO: handle type parameters in qualified names... @@ -2406,7 +2406,7 @@ namespace ts { entityName = nameIdentifier; } const typeParameterCount = (type.target.typeParameters || emptyArray).length; - const typeArgumentNodes = mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)); + const typeArgumentNodes = mapToTypeNodeArray(typeArguments.length > 0 ? typeArguments.slice(i, typeParameterCount - i) : undefined); return createTypeReferenceNode(entityName, typeArgumentNodes); } } @@ -2478,7 +2478,8 @@ namespace ts { , /*dotDotDotToken*/ undefined , name , /*questionToken*/ undefined - , stringTypeNode); + , stringTypeNode + , /*initializer*/ undefined); const typeNode = createTypeNode(indexInfo.type); return createIndexSignatureDeclaration( [indexingParameter] @@ -7261,10 +7262,6 @@ namespace ts { } } - // export function synthesizeTypeNode(type: Type, enclosingDeclaration: Node): TypeNode { - // throw new Error("Not implemented" + enclosingDeclaration); - // } - function instantiateList(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] { if (items && items.length) { const result: T[] = []; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 7eb44f93bc5..077bc349867 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -355,8 +355,6 @@ namespace ts { export function createIndexSignatureDeclaration(parameters: ParameterDeclaration[], type: TypeNode, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined): IndexSignatureDeclaration { const indexSignature = createSynthesizedNode(SyntaxKind.IndexSignature) as IndexSignatureDeclaration; - // indexSignature.name = asName(name); - // type parameters indexSignature.parameters = asNodeArray(parameters); indexSignature.type = type; indexSignature.decorators = asNodeArray(decorators); @@ -373,6 +371,8 @@ namespace ts { : node; } + // Signature elements + export function createParameter(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) { const node = createSynthesizedNode(SyntaxKind.Parameter); node.decorators = asNodeArray(decorators); @@ -385,11 +385,12 @@ namespace ts { return node; } - export function updateParameter(node: ParameterDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) { + export function updateParameter(node: ParameterDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { return node.decorators !== decorators || node.modifiers !== modifiers || node.dotDotDotToken !== dotDotDotToken || node.name !== name + || node.questionToken !== questionToken || node.type !== type || node.initializer !== initializer ? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer), node) @@ -438,7 +439,7 @@ namespace ts { node.asteriskToken = asteriskToken; node.name = asName(name); node.typeParameters = asNodeArray(typeParameters); - node.parameters = createNodeArray(parameters); + node.parameters = asNodeArray(parameters); node.type = type; node.body = body; return node; diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 971dddd20ea..f66bf14da53 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -475,6 +475,7 @@ namespace ts { /*modifiers*/ undefined, node.dotDotDotToken, getGeneratedNameForNode(node), + node.questionToken, /*type*/ undefined, visitNode(node.initializer, visitor, isExpression) ); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e3c5525e06f..bccf0f1c4f9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -895,7 +895,7 @@ namespace ts { exprName: EntityName; } - /** A TypeLiteral is the declaration node for an anonymous symbol. */ + // A TypeLiteral is the declaration node for an anonymous symbol. export interface TypeLiteralNode extends TypeNode, Declaration { kind: SyntaxKind.TypeLiteral; members: NodeArray; diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 3b75e072a57..e64e59eba3a 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -272,6 +272,7 @@ namespace ts { nodesVisitor((node).modifiers, visitor, isModifier), (node).dotDotDotToken, visitNode((node).name, visitor, isBindingName), + visitNode((node).questionToken, visitor, isToken), visitNode((node).type, visitor, isTypeNode), visitNode((node).initializer, visitor, isExpression)); diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 2403c0adbe0..61c823908d9 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -61,7 +61,8 @@ namespace ts.codefix { , /*dotDotDotToken*/ undefined , "x" , /*questionToken*/ undefined - , stringTypeNode); + , stringTypeNode + , /*initializer*/ undefined); const indexSignature = createIndexSignatureDeclaration( [indexingParameter] , typeNode diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 8c4eb40a3ea..2db14f81df1 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -126,7 +126,7 @@ namespace ts.codefix { } else { Debug.assert(declarations.length === signatures.length); - const methodImplementingSignatures = createMethodImplementingSignatures(signatures, enclosingDeclaration, name, modifiers); + const methodImplementingSignatures = createMethodImplementingSignatures(signatures, name, modifiers); signatureDeclarations.push(methodImplementingSignatures); } return signatureDeclarations; @@ -135,11 +135,8 @@ namespace ts.codefix { } } - // TODO: infer types of arguments? - function createMethodImplementingSignatures(signatures: Signature[], enclosingDeclaration: ClassLikeDeclaration, name: string, modifiers: Modifier[] | undefined): MethodDeclaration { - const newMethodDeclaration = createNode(SyntaxKind.CallSignature) as SignatureDeclaration; - newMethodDeclaration.parent = enclosingDeclaration; - newMethodDeclaration.name = signatures[0].getDeclaration().name; + function createMethodImplementingSignatures(signatures: Signature[], name: string, modifiers: Modifier[] | undefined): MethodDeclaration { + Debug.assert(signatures && signatures.length > 0); let maxNonRestArgs = -1; let maxArgsIndex = 0; @@ -157,46 +154,45 @@ namespace ts.codefix { } const maxArgsParameterSymbolNames = signatures[maxArgsIndex].getParameters().map(symbol => symbol.getName()); - const parameters = createNodeArray(); + const parameters: ParameterDeclaration[] = []; for (let i = 0; i < maxNonRestArgs; i++) { + const anyType = createKeywordTypeNode(SyntaxKind.AnyKeyword); const newParameter = createParameter( /*decorators*/ undefined , /*modifiers*/ undefined , /*dotDotDotToken*/ undefined , maxArgsParameterSymbolNames[i] , /*questionToken*/ i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined - , /*type*/ undefined + , anyType , /*initializer*/ undefined); parameters.push(newParameter); } if (hasRestParameter) { + const anyType = createKeywordTypeNode(SyntaxKind.AnyKeyword); const restParameter = createParameter( /*decorators*/ undefined , /*modifiers*/ undefined , createToken(SyntaxKind.DotDotDotToken) , maxArgsParameterSymbolNames[maxNonRestArgs] || "rest" , /*questionToken*/ maxNonRestArgs >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined - , /*type*/ undefined + , anyType , /*initializer*/ undefined); parameters.push(restParameter); } - return createMethod( - /*decorators*/ undefined - , modifiers - , /*asteriskToken*/ undefined + return createStubbedMethod( + modifiers , name , /*typeParameters*/undefined , parameters - , /*type*/ undefined - , /*body*/undefined); + , /*returnType*/ undefined); } - export function createStubbedMethod(modifiers: Modifier[], name: string, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType?: TypeNode) { + export function createStubbedMethod(modifiers: Modifier[], name: string, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType: TypeNode | undefined) { return createMethod( /*decorators*/undefined - , /*modifiers*/modifiers + , modifiers , /*asteriskToken*/undefined , name , typeParameters @@ -231,12 +227,13 @@ namespace ts.codefix { const parameterTypeNode = checker.createTypeNode(parameterType); // TODO: deep cloning of decorators/any node. const parameterNode = createParameter( - parameterDeclaration.decorators && parameterDeclaration.decorators.map(getSynthesizedClone) - , parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone) + parameterDeclaration.decorators && parameterDeclaration.decorators.map(getSynthesizedDeepClone) + , parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedDeepClone) , parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken) - , parameterDeclaration.name + , getSynthesizedDeepClone(parameterDeclaration.name) , parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken) - , parameterTypeNode); + , parameterTypeNode + , /*initializer*/ undefined); return parameterNode; } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index cb8c614cb22..71536dc75f5 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -360,7 +360,7 @@ namespace ts.textChanges { return visited; } // clone nodearray if necessary - const nodeArray = visited === nodes ? createNodeArray(visited) : visited; + const nodeArray = visited === nodes ? createNodeArray(visited.slice(0)) : visited; nodeArray.pos = getPos(nodes); nodeArray.end = getEnd(nodes); return nodeArray; diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts index 4bddfb799f2..bc437c93bcd 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts @@ -28,4 +28,4 @@ verify.rangeAfterCodeFix(` e: this; f: A; g: string; -`); \ No newline at end of file +`);