diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7af5b877b53..960a36e3476 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2191,23 +2191,23 @@ namespace ts { return result; } - function createTypeParameterDeclarationFromType(type: TypeParameter): TypeParameterDeclaration { + function createTypeParameterDeclarationFromType(type: TypeParameter, enclosingDeclaration: Node): TypeParameterDeclaration { if (!(type && type.symbol && type.flags & TypeFlags.TypeParameter)) { return undefined; } - const constraint = createTypeNode(getConstraintFromTypeParameter(type)) as TypeNode; - const defaultParameter = createTypeNode(getDefaultFromTypeParameter(type)) as TypeNode; + const constraint = createTypeNode(getConstraintFromTypeParameter(type), enclosingDeclaration); + const defaultParameter = createTypeNode(getDefaultFromTypeParameter(type), enclosingDeclaration); const name = symbolToString(type.symbol); return createTypeParameterDeclaration(name, constraint, defaultParameter); } // TODO: enclosing declaration appears to be unused in getTypeOfSymbolAtLocation - function createParameterDeclarationFromSymbol(parameterSymbol: Symbol): ParameterDeclaration { + function createParameterDeclarationFromSymbol(parameterSymbol: Symbol, enclosingDeclaration: Node): ParameterDeclaration { const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration; const parameterType = getTypeOfSymbol(parameterSymbol); - const parameterTypeNode = checker.createTypeNode(parameterType); + const parameterTypeNode = createTypeNode(parameterType, enclosingDeclaration); // 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( @@ -2222,25 +2222,24 @@ namespace ts { } // TODO: expose this, remove copy from helper, possibly don't expose createParameter/TypeParameter? - function createSignatureParts(signature: Signature): SignatureParts { + function createSignatureParts(signature: Signature, enclosingDeclaration: Node): SignatureParts { return { - typeParameters: signature.typeParameters && signature.typeParameters.map(createTypeParameterDeclarationFromType), - parameters: signature.parameters.map(createParameterDeclarationFromSymbol), + typeParameters: signature.typeParameters && signature.typeParameters.map(parameter => createTypeParameterDeclarationFromType(parameter,enclosingDeclaration)), + parameters: signature.parameters.map(parameter => createParameterDeclarationFromSymbol(parameter,enclosingDeclaration)), type: createTypeNodeExceptAny(getReturnTypeOfSignature(signature)) } function createTypeNodeExceptAny(type: Type): TypeNode | undefined { - const typeNode = createTypeNode(type); + const typeNode = createTypeNode(type, enclosingDeclaration); return typeNode && typeNode.kind !== SyntaxKind.AnyKeyword ? typeNode : undefined; } } - function createTypeNode(type: Type): TypeNode { + function createTypeNode(type: Type, enclosingDeclaration: Node): TypeNode { let undefinedArgumentIsError = true; let encounteredError = false; let inObjectTypeLiteral = false; let checkAlias = true; - let enclosingDeclaration: Node = undefined; // TODO: add parameter. let symbolStack: Symbol[] = undefined; let result = createTypeNodeWorker(type); @@ -2256,7 +2255,7 @@ namespace ts { return undefined; } - const typeString = typeToString(type); typeString; // TODO: remove. + const typeString = typeToString(type, enclosingDeclaration); typeString; // TODO: remove. if (type.flags & TypeFlags.Any) { // TODO: add other case where type ends up being `any`. @@ -2315,15 +2314,8 @@ namespace ts { if (objectFlags & ObjectFlags.Reference) { Debug.assert(!!(type.flags & TypeFlags.Object)); - // and vice versa. - // this case includes tuple types - // TODO: test empty tuples, see if they are coherent. return createTypeReferenceNodeFromType(type); } - - if (type.flags & TypeFlags.EnumLiteral) { - throw new Error("Enum literal not implemented"); - } if (objectFlags & ObjectFlags.ClassOrInterface) { Debug.assert(!!(type.flags & TypeFlags.Object)); // TODO: Detect whether class is named and fail if not. @@ -2397,9 +2389,9 @@ namespace ts { // TODO: does typeParameter have the same constraint or do we need to overwrite it somehow? const typeParameter = getTypeParameterFromMappedType(type); // const constraintType = getConstraintTypeFromMappedType(type); - const typeParameterNode = createTypeParameterDeclarationFromType(typeParameter); + const typeParameterNode = createTypeParameterDeclarationFromType(typeParameter, enclosingDeclaration); - const templateTypeNode = createTypeNode(getTemplateTypeFromMappedType(type)); + const templateTypeNode = createTypeNode(getTemplateTypeFromMappedType(type), enclosingDeclaration); const readonlyToken = (type).declaration && (type).declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined; const questionToken = (type).declaration && (type).declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined; @@ -2474,12 +2466,12 @@ namespace ts { if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { const signature = resolved.callSignatures[0]; - const signatureParts = createSignatureParts(signature); + const signatureParts = createSignatureParts(signature, enclosingDeclaration); return createSignatureDeclaration(SyntaxKind.FunctionType, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type); } if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { const signature = resolved.constructSignatures[0]; - const signatureParts = createSignatureParts(signature); + const signatureParts = createSignatureParts(signature, enclosingDeclaration); return createSignatureDeclaration(SyntaxKind.ConstructorType, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type); } } @@ -2559,18 +2551,18 @@ namespace ts { function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] { const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { - const signatureParts = createSignatureParts(signature); + const signatureParts = createSignatureParts(signature, enclosingDeclaration); typeElements.push(createSignatureDeclaration(SyntaxKind.CallSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type)); } for (const signature of resolvedType.constructSignatures) { - const signatureParts = createSignatureParts(signature); + const signatureParts = createSignatureParts(signature, enclosingDeclaration); typeElements.push(createSignatureDeclaration(SyntaxKind.ConstructSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type)); } if (resolvedType.stringIndexInfo) { - typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.stringIndexInfo, IndexKind.String)); + typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.stringIndexInfo, IndexKind.String, enclosingDeclaration)); } if (resolvedType.numberIndexInfo) { - typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.numberIndexInfo, IndexKind.Number)); + typeElements.push(createIndexSignatureFromIndexInfo(resolvedType.numberIndexInfo, IndexKind.Number, enclosingDeclaration)); } const properties = resolvedType.properties; @@ -2589,7 +2581,7 @@ namespace ts { 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 signatureParts = createSignatureParts(signature, enclosingDeclaration); const methodDeclaration = createSignatureDeclaration(SyntaxKind.MethodSignature, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type, propertyName, optionalToken); methodDeclaration.questionToken = optionalToken; typeElements.push(methodDeclaration); @@ -2599,7 +2591,7 @@ namespace ts { typeElements.push(createPropertySignature( propertyName , optionalToken - , createTypeNode(propertyType) + , createTypeNodeWorker(propertyType) , /*initializer*/undefined)); } } @@ -2608,7 +2600,7 @@ namespace ts { } } - function createIndexSignatureFromIndexInfo(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration { + function createIndexSignatureFromIndexInfo(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration: Node): IndexSignatureDeclaration { const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword); const name = getNameFromIndexInfo(indexInfo); @@ -2620,7 +2612,7 @@ namespace ts { , /*questionToken*/ undefined , indexerTypeNode , /*initializer*/ undefined); - const typeNode = createTypeNode(indexInfo.type); + const typeNode = createTypeNode(indexInfo.type, enclosingDeclaration); return createIndexSignatureDeclaration( [indexingParameter] , typeNode diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 679e11fa255..d802adf67ec 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2469,11 +2469,11 @@ namespace ts { getNonNullableType(type: Type): Type; /** Note that the resulting nodes cannot be checked. */ - createTypeNode(type: Type): TypeNode; + createTypeNode(type: Type, enclosingDeclaration: Node): TypeNode; /** Note that the resulting nodes cannot be checked. */ - createIndexSignatureFromIndexInfo(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration; + createIndexSignatureFromIndexInfo(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration: Node): IndexSignatureDeclaration; /** Note that the resulting nodes cannot be checked. */ - createSignatureParts(signature: Signature): SignatureParts; + createSignatureParts(signature: Signature, enclosingDeclaration: Node): SignatureParts; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol; diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index ace11cda807..ab973bb5772 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -38,7 +38,7 @@ namespace ts.codefix { const checker = context.program.getTypeChecker(); const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right))); - typeNode = checker.createTypeNode(widenedType) || typeNode; + typeNode = checker.createTypeNode(widenedType, classDeclaration) || typeNode; } const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile); diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 33b4a10dffc..de34676eda0 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -11,14 +11,14 @@ namespace ts.codefix { const token = getTokenAtPosition(sourceFile, start); const checker = context.program.getTypeChecker(); - const classDecl = getContainingClass(token); - if (!classDecl) { + const classDeclaration = getContainingClass(token); + if (!classDeclaration) { return undefined; } - const openBrace = getOpenBraceOfClassLike(classDecl, sourceFile); - const classType = checker.getTypeAtLocation(classDecl) as InterfaceType; - const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); + const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile); + const classType = checker.getTypeAtLocation(classDeclaration) as InterfaceType; + const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDeclaration); const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number); const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String); @@ -34,7 +34,7 @@ namespace ts.codefix { let newNodes: Node[] = []; createAndAddMissingIndexSignatureDeclaration(implementedType, IndexKind.Number, hasNumericIndexSignature, newNodes); createAndAddMissingIndexSignatureDeclaration(implementedType, IndexKind.String, hasStringIndexSignature, newNodes); - newNodes = newNodes.concat(createMissingMemberNodes(classDecl, nonPrivateMembers, checker)); + newNodes = newNodes.concat(createMissingMemberNodes(classDeclaration, nonPrivateMembers, checker)); const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]); if (newNodes.length > 0) { pushAction(result, newNodes, message); @@ -53,7 +53,7 @@ namespace ts.codefix { if (!indexInfoOfKind) { return undefined; } - const newIndexSignatureDeclaration = checker.createIndexSignatureFromIndexInfo(indexInfoOfKind, kind); + const newIndexSignatureDeclaration = checker.createIndexSignatureFromIndexInfo(indexInfoOfKind, kind, classDeclaration); newNodes.push(newIndexSignatureDeclaration); } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index a8347cb0a9b..8693cc453bb 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -62,7 +62,7 @@ namespace ts.codefix { case SyntaxKind.SetAccessor: case SyntaxKind.PropertySignature: case SyntaxKind.PropertyDeclaration: - const typeNode = checker.createTypeNode(type); + const typeNode = checker.createTypeNode(type, enclosingDeclaration); // TODO: add modifiers. const property = createProperty( /*decorators*/undefined @@ -89,11 +89,8 @@ namespace ts.codefix { 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 signatureParts = checker.createSignatureParts(signature); + const signatureParts = checker.createSignatureParts(signature, enclosingDeclaration); return createStubbedMethod(modifiers, name, optional, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type); } @@ -101,7 +98,7 @@ namespace ts.codefix { for (let i = 0; i < signatures.length; i++) { // TODO: make signatures instead of methods const signature = signatures[i]; - const signatureParts = checker.createSignatureParts(signature); + const signatureParts = checker.createSignatureParts(signature, enclosingDeclaration); signatureDeclarations.push(createMethod( /*decorators*/ undefined , modifiers @@ -116,7 +113,7 @@ namespace ts.codefix { if (declarations.length > signatures.length) { let signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration); - const signatureParts = checker.createSignatureParts(signature); + const signatureParts = checker.createSignatureParts(signature, enclosingDeclaration); signatureDeclarations.push(createStubbedMethod(modifiers, name, optional, signatureParts.typeParameters, signatureParts.parameters, signatureParts.type)); } else {