diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 25c275fe969..baa7b7c1e61 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1502,6 +1502,8 @@ namespace ts { case SyntaxKind.MethodSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.JSDocSignature: case SyntaxKind.JSDocFunctionType: @@ -1600,6 +1602,8 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: @@ -2236,8 +2240,10 @@ namespace ts { case SyntaxKind.Constructor: return declareSymbolAndAddToSymbolTable(node, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); case SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessorSignature: return bindPropertyOrMethodOrAccessor(node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); case SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessorSignature: return bindPropertyOrMethodOrAccessor(node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); case SyntaxKind.FunctionType: case SyntaxKind.JSDocFunctionType: @@ -3750,6 +3756,8 @@ namespace ts { case SyntaxKind.TypeParameter: case SyntaxKind.PropertySignature: case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: @@ -3934,6 +3942,8 @@ namespace ts { case SyntaxKind.TypeParameter: case SyntaxKind.PropertySignature: case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eff67197bbc..60ecfdb2cf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4902,6 +4902,8 @@ namespace ts { case SyntaxKind.PropertySignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: if (hasModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { @@ -5356,13 +5358,14 @@ namespace ts { } if (declaration.kind === SyntaxKind.Parameter) { - const func = declaration.parent; + const func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present - if (func.kind === SyntaxKind.SetAccessor && !hasNonBindableDynamicName(func)) { - const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor); + if (isSetAccessorLike(func) && !hasNonBindableDynamicName(func)) { + const getAccessorKind = func.kind === SyntaxKind.SetAccessorSignature ? SyntaxKind.GetAccessorSignature : SyntaxKind.GetAccessor; + const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), getAccessorKind); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); - const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); + const thisParameter = getAccessorThisParameter(func); if (thisParameter && declaration === thisParameter) { // Use the type from the *getter* Debug.assert(!thisParameter.type); @@ -5866,9 +5869,9 @@ namespace ts { return type; } - function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | undefined): TypeNode | undefined { + function getAnnotatedAccessorTypeNode(accessor: AccessorLike | undefined): TypeNode | undefined { if (accessor) { - if (accessor.kind === SyntaxKind.GetAccessor) { + if (isGetAccessorLike(accessor)) { const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor); return getterTypeAnnotation; } @@ -5880,12 +5883,12 @@ namespace ts { return undefined; } - function getAnnotatedAccessorType(accessor: AccessorDeclaration | undefined): Type | undefined { + function getAnnotatedAccessorType(accessor: AccessorLike | undefined): Type | undefined { const node = getAnnotatedAccessorTypeNode(accessor); return node && getTypeFromTypeNode(node); } - function getAnnotatedAccessorThisParameter(accessor: AccessorDeclaration): Symbol | undefined { + function getAnnotatedAccessorThisParameter(accessor: AccessorLike): Symbol | undefined { const parameter = getAccessorThisParameter(accessor); return parameter && parameter.symbol; } @@ -5900,8 +5903,10 @@ namespace ts { } function getTypeOfAccessorsWorker(symbol: Symbol): Type { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); - const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor) || + getDeclarationOfKind(symbol, SyntaxKind.GetAccessorSignature); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor) || + getDeclarationOfKind(symbol, SyntaxKind.SetAccessorSignature); if (getter && isInJSFile(getter)) { const jsDocType = getTypeForDeclarationFromJSDocComment(getter); @@ -5929,7 +5934,7 @@ namespace ts { } else { // If there are no specified types, try to infer it from the body of the get accessor if it exists. - if (getter && getter.body) { + if (getter && isGetAccessorDeclaration(getter) && getter.body) { type = getReturnTypeFromBody(getter); } // Otherwise, fall back to 'any'. @@ -5950,7 +5955,8 @@ namespace ts { if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { - const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor) || + getDeclarationOfKind(symbol, SyntaxKind.GetAccessorSignature); error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } @@ -6748,7 +6754,9 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return isThislessFunctionLikeDeclaration(declaration); + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: + return isThislessFunctionLikeDeclaration(declaration); } } } @@ -8562,11 +8570,12 @@ namespace ts { } // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation - if ((declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) && + if (isAccessorDeclaration(declaration) && !hasNonBindableDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { - const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); + const symbol = getSymbolOfNode(declaration); + const other = getDeclarationOfKind(symbol, getOtherAccessorDeclarationKind(declaration)) || + getDeclarationOfKind(symbol, getOtherAccessorSignatureKind(declaration)); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } @@ -8779,12 +8788,13 @@ namespace ts { if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === SyntaxKind.GetAccessor && !hasNonBindableDynamicName(declaration)) { + if (isGetAccessorLike(declaration) && !hasNonBindableDynamicName(declaration)) { const jsDocType = isInJSFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration); if (jsDocType) { return jsDocType; } - const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor) || + getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessorSignature); const setterType = getAnnotatedAccessorType(setter); if (setterType) { return setterType; @@ -15177,6 +15187,8 @@ namespace ts { case SyntaxKind.MethodSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: if (noImplicitAny && !(declaration as NamedDeclaration).name) { @@ -18566,13 +18578,17 @@ namespace ts { return container.kind === SyntaxKind.MethodDeclaration || container.kind === SyntaxKind.MethodSignature || container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor; + container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.GetAccessorSignature || + container.kind === SyntaxKind.SetAccessorSignature; } else { return container.kind === SyntaxKind.MethodDeclaration || container.kind === SyntaxKind.MethodSignature || container.kind === SyntaxKind.GetAccessor || container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.GetAccessorSignature || + container.kind === SyntaxKind.SetAccessorSignature || container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.PropertySignature || container.kind === SyntaxKind.Constructor; @@ -25861,7 +25877,7 @@ namespace ts { } } - function checkAccessorDeclaration(node: AccessorDeclaration) { + function checkAccessorDeclaration(node: AccessorLike) { if (produceDiagnostics) { // Grammar checking accessors if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); @@ -25884,8 +25900,9 @@ namespace ts { if (!hasNonBindableDynamicName(node)) { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. - const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); + const symbol = getSymbolOfNode(node); + const otherAccessor = getDeclarationOfKind(symbol, getOtherAccessorDeclarationKind(node)) || + getDeclarationOfKind(symbol, getOtherAccessorSignatureKind(node)); if (otherAccessor) { const nodeFlags = getModifierFlags(node); const otherFlags = getModifierFlags(otherAccessor); @@ -25907,10 +25924,12 @@ namespace ts { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } } - checkSourceElement(node.body); + if (isAccessorDeclaration(node)) { + checkSourceElement(node.body); + } } - function checkAccessorDeclarationTypesIdentical(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type | undefined, message: DiagnosticMessage) { + function checkAccessorDeclarationTypesIdentical(first: AccessorLike, second: AccessorLike, getAnnotatedType: (a: AccessorLike) => Type | undefined, message: DiagnosticMessage) { const firstType = getAnnotatedType(first); const secondType = getAnnotatedType(second); if (firstType && secondType && !isTypeIdenticalTo(firstType, secondType)) { @@ -27199,6 +27218,8 @@ namespace ts { checkUnusedTypeParameters(node, addDiagnostic); break; case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.FunctionType: @@ -27471,7 +27492,9 @@ namespace ts { node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.GetAccessor || - node.kind === SyntaxKind.SetAccessor) { + node.kind === SyntaxKind.SetAccessor || + node.kind === SyntaxKind.GetAccessorSignature || + node.kind === SyntaxKind.SetAccessorSignature) { // it is ok to have member named '_super' or '_this' - member access is always qualified return false; } @@ -30326,6 +30349,8 @@ namespace ts { return checkConstructorDeclaration(node); case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: return checkAccessorDeclaration(node); case SyntaxKind.TypeReference: return checkTypeReferenceNode(node); @@ -30564,7 +30589,9 @@ namespace ts { break; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - checkAccessorDeclaration(node); + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: + checkAccessorDeclaration(node); break; case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node); @@ -31931,8 +31958,8 @@ namespace ts { }, getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity, getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { - accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 - const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; + accessor = getParseTreeNode(accessor, isAccessorDeclaration)!; // TODO: GH#18217 + const otherKind = getOtherAccessorDeclarationKind(accessor); const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; @@ -31945,6 +31972,21 @@ namespace ts { getAccessor }; }, + getAllAccessorSignatures(accessor: AccessorSignature): AllAccessorSignatures { + accessor = getParseTreeNode(accessor, isAccessorSignature)!; // TODO: GH#18217 + const otherKind = getOtherAccessorSignatureKind(accessor); + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); + const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; + const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; + const setAccessor = accessor.kind === SyntaxKind.SetAccessorSignature ? accessor : otherAccessor as SetAccessorSignature; + const getAccessor = accessor.kind === SyntaxKind.GetAccessorSignature ? accessor : otherAccessor as GetAccessorSignature; + return { + firstAccessor, + secondAccessor, + setAccessor, + getAccessor + }; + }, getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined), isBindingCapturedByNode: (node, decl) => { const parseNode = getParseTreeNode(node); @@ -32493,6 +32535,8 @@ namespace ts { switch (node.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.Constructor: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -32624,7 +32668,7 @@ namespace ts { return false; } - function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean { + function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature | AccessorSignature): boolean { // Prevent cascading error by short-circuit const file = getSourceFileOfNode(node); return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || @@ -33036,27 +33080,28 @@ namespace ts { return false; } - function checkGrammarAccessor(accessor: AccessorDeclaration): boolean { - const kind = accessor.kind; - if (languageVersion < ScriptTarget.ES5) { - return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); + function checkGrammarAccessor(accessor: AccessorLike): boolean { + if (isAccessorDeclaration(accessor)) { + if (languageVersion < ScriptTarget.ES5) { + return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); + } + else if (accessor.body === undefined && !hasModifier(accessor, ModifierFlags.Abstract) && !(accessor.flags & NodeFlags.Ambient)) { + return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); + } + else if (accessor.body && hasModifier(accessor, ModifierFlags.Abstract)) { + return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation); + } } - else if (accessor.body === undefined && !hasModifier(accessor, ModifierFlags.Abstract) && !(accessor.flags & NodeFlags.Ambient)) { - return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); - } - else if (accessor.body && hasModifier(accessor, ModifierFlags.Abstract)) { - return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation); - } - else if (accessor.typeParameters) { + if (accessor.typeParameters) { return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters); } else if (!doesAccessorHaveCorrectParameterCount(accessor)) { return grammarErrorOnNode(accessor.name, - kind === SyntaxKind.GetAccessor ? + isGetAccessorLike(accessor) ? Diagnostics.A_get_accessor_cannot_have_parameters : Diagnostics.A_set_accessor_must_have_exactly_one_parameter); } - else if (kind === SyntaxKind.SetAccessor) { + else if (isSetAccessorLike(accessor)) { if (accessor.type) { return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); } @@ -33080,12 +33125,12 @@ namespace ts { * A get accessor has no parameters or a single `this` parameter. * A set accessor has one parameter or a `this` parameter and one more parameter. */ - function doesAccessorHaveCorrectParameterCount(accessor: AccessorDeclaration) { - return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1); + function doesAccessorHaveCorrectParameterCount(accessor: AccessorLike) { + return getAccessorThisParameter(accessor) || accessor.parameters.length === (isGetAccessorLike(accessor) ? 0 : 1); } - function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration | undefined { - if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2)) { + function getAccessorThisParameter(accessor: AccessorLike): ParameterDeclaration | undefined { + if (accessor.parameters.length === (isGetAccessorLike(accessor) ? 1 : 2)) { return getThisParameter(accessor); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5cca456dd49..5abc9ee1e8a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3036,6 +3036,27 @@ "code": 4105 }, + "Parameter type of setter '{0}' from exported interface has or is using name '{1}' from private module '{2}'.": { + "category": "Error", + "code": 4106 + }, + "Parameter type of setter '{0}' from exported interface has or is using private name '{1}'.": { + "category": "Error", + "code": 4107 + }, + "Return type of getter '{0}' from exported interface has or is using name '{1}' from external module {2} but cannot be named.": { + "category": "Error", + "code": 4108 + }, + "Return type of getter '{0}' from exported interface has or is using name '{1}' from private module '{2}'.": { + "category": "Error", + "code": 4109 + }, + "Return type of getter '{0}' from exported interface has or is using private name '{1}'.": { + "category": "Error", + "code": 4110 + }, + "The current host does not support the '{0}' option.": { "category": "Error", "code": 5001 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8681a452e2a..a1f3534b60d 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -617,6 +617,7 @@ namespace ts { isLiteralConstDeclaration: notImplemented, getJsxFactoryEntity: notImplemented, getAllAccessorDeclarations: notImplemented, + getAllAccessorSignatures: notImplemented, getSymbolOfExternalModuleSpecifier: notImplemented, isBindingCapturedByNode: notImplemented, }; @@ -1211,6 +1212,9 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: return emitAccessorDeclaration(node); + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: + return emitAccessorSignature(node); case SyntaxKind.CallSignature: return emitCallSignature(node); case SyntaxKind.ConstructSignature: @@ -1865,6 +1869,19 @@ namespace ts { emitSignatureAndBody(node, emitSignatureHead); } + function emitAccessorSignature(node: AccessorSignature) { + pushNameGenerationScope(node); + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeKeyword(node.kind === SyntaxKind.GetAccessorSignature ? "get" : "set"); + writeSpace(); + emit(node.name); + emitParameters(node, node.parameters); + emitTypeAnnotation(node.type); + writeTrailingSemicolon(); + popNameGenerationScope(node); + } + function emitCallSignature(node: CallSignatureDeclaration) { pushNameGenerationScope(node); emitDecorators(node, node.decorators); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 3a8ecb20999..7ba691a3126 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -600,6 +600,66 @@ namespace ts { : node; } + export function createGetAccessorSignature( + decorators: ReadonlyArray | undefined, + modifiers: ReadonlyArray | undefined, + name: string | PropertyName, + parameters: ReadonlyArray, + type: TypeNode | undefined) { + const node = createSynthesizedNode(SyntaxKind.GetAccessorSignature); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + return node; + } + + export function updateGetAccessorSignature( + node: GetAccessorSignature, + decorators: ReadonlyArray | undefined, + modifiers: ReadonlyArray | undefined, + name: PropertyName, + parameters: ReadonlyArray, + type: TypeNode | undefined) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + || node.type !== type + ? updateNode(createGetAccessorSignature(decorators, modifiers, name, parameters, type), node) + : node; + } + + export function createSetAccessorSignature( + decorators: ReadonlyArray | undefined, + modifiers: ReadonlyArray | undefined, + name: string | PropertyName, + parameters: ReadonlyArray) { + const node = createSynthesizedNode(SyntaxKind.SetAccessorSignature); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + return node; + } + + export function updateSetAccessorSignature( + node: SetAccessorSignature, + decorators: ReadonlyArray | undefined, + modifiers: ReadonlyArray | undefined, + name: PropertyName, + parameters: ReadonlyArray) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + ? updateNode(createSetAccessorSignature(decorators, modifiers, name, parameters), node) + : node; + } + export function createCallSignature(typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined) { return createSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type) as CallSignatureDeclaration; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 704260e7279..9041ef5f85f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -149,6 +149,8 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: @@ -2006,6 +2008,8 @@ namespace ts { switch (node.kind) { case SyntaxKind.ConstructSignature: case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.IndexSignature: case SyntaxKind.PropertySignature: case SyntaxKind.CallSignature: @@ -2702,6 +2706,14 @@ namespace ts { return finishNode(node); } + function parseAccessorSignature(node: AccessorSignature, kind: AccessorSignature["kind"]): AccessorSignature { + node.kind = kind; + node.name = parsePropertyName(); + fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type, node); + parseTypeMemberSemicolon(); + return finishNode(node); + } + function parsePropertyOrMethodSignature(node: PropertySignature | MethodSignature): PropertySignature | MethodSignature { node.name = parsePropertyName(); node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); @@ -2730,10 +2742,10 @@ namespace ts { if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { return true; } - let idToken = false; + let idToken: SyntaxKind | undefined; // Eat up all modifiers, but hold on to the last one in case it is actually an identifier while (isModifierKind(token())) { - idToken = true; + idToken = token(); nextToken(); } // Index signatures and computed property names are type members @@ -2742,12 +2754,17 @@ namespace ts { } // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { - idToken = true; + idToken = token(); nextToken(); } // If we were able to get any potential identifier, check that it is // the start of a member declaration - if (idToken) { + if (idToken !== undefined) { + // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. + if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) { + return true; + } + return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.QuestionToken || @@ -2765,8 +2782,18 @@ namespace ts { if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } + const node = createNodeWithJSDoc(SyntaxKind.Unknown); node.modifiers = parseModifiers(); + + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorSignature(node, SyntaxKind.GetAccessorSignature); + } + + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorSignature(node, SyntaxKind.SetAccessorSignature); + } + if (isIndexSignature()) { return parseIndexSignatureDeclaration(node); } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 6dfc909b93a..d834e29f2f3 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -393,7 +393,24 @@ namespace ts { } } - function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags): ParameterDeclaration { + function ensureParameter(node: Node, p: ParameterDeclaration, modifierMask?: ModifierFlags): ParameterDeclaration { + let type: TypeNode | undefined; + let name: BindingName | undefined; + let noType = false; + if (isAccessorLike(node) && !isThisIdentifier(p.name)) { + if (!hasModifier(node, ModifierFlags.Private)) { + type = p.type || (isAccessorDeclaration(node) + ? getTypeAnnotationFromAllAccessorDeclarations(node) + : getTypeAnnotationFromAllAccessorSignatures(node)); + } + else { + name = createIdentifier("value"); + noType = true; + } + } + else { + type = p.type; + } let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; @@ -404,9 +421,9 @@ namespace ts { /*decorators*/ undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, - filterBindingPatternInitializers(p.name), + name || filterBindingPatternInitializers(p.name), resolver.isOptionalParameter(p) ? (p.questionToken || createToken(SyntaxKind.QuestionToken)) : undefined, - ensureType(p, p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param + noType ? undefined : ensureType(p, type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param ensureNoInitializer(p) ); if (!suppressNewDiagnosticContexts) { @@ -435,6 +452,8 @@ namespace ts { | ConstructSignatureDeclaration | VariableDeclaration | MethodSignature + | GetAccessorSignature + | SetAccessorSignature | CallSignatureDeclaration | ParameterDeclaration | PropertyDeclaration @@ -525,10 +544,10 @@ namespace ts { } function updateParamsList(node: Node, params: NodeArray, modifierMask?: ModifierFlags) { - if (hasModifier(node, ModifierFlags.Private)) { + if (hasModifier(node, ModifierFlags.Private) && !isSetAccessorLike(node)) { return undefined!; // TODO: GH#18217 } - const newParams = map(params, p => ensureParameter(p, modifierMask)); + const newParams = map(params, p => ensureParameter(node, p, modifierMask)); if (!newParams) { return undefined!; // TODO: GH#18217 } @@ -847,6 +866,24 @@ namespace ts { input.questionToken )); } + case SyntaxKind.GetAccessorSignature: { + const accessorType = getTypeAnnotationFromAllAccessorSignatures(input); + return cleanup(updateGetAccessorSignature( + input, + /*decorators*/ undefined, + ensureModifiers(input), + input.name, + updateParamsList(input, input.parameters), + !hasModifier(input, ModifierFlags.Private) ? ensureType(input, accessorType) : undefined)); + } + case SyntaxKind.SetAccessorSignature: { + return cleanup(updateSetAccessorSignature( + input, + /*decorators*/ undefined, + ensureModifiers(input), + input.name, + updateParamsList(input, input.parameters))); + } case SyntaxKind.CallSignature: { return cleanup(updateCallSignature( input, @@ -1374,17 +1411,35 @@ namespace ts { return maskModifierFlags(node, mask, additions); } - function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined { + function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration) { const accessors = resolver.getAllAccessorDeclarations(node); - if (node.kind !== accessors.firstAccessor.kind) { - return; - } let accessorType = getTypeAnnotationFromAccessor(node); if (!accessorType && accessors.secondAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor); // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); } + return accessorType; + } + + function getTypeAnnotationFromAllAccessorSignatures(node: AccessorSignature) { + const accessors = resolver.getAllAccessorSignatures(node); + let accessorType = getTypeAnnotationFromAccessor(node); + if (!accessorType && accessors.secondAccessor) { + accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor); + // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); + } + return accessorType; + } + + function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined { + const accessors = resolver.getAllAccessorDeclarations(node); + if (node.kind !== accessors.firstAccessor.kind) { + return; + } + + const accessorType = getTypeAnnotationFromAllAccessorDeclarations(node); const prop = createProperty(/*decorators*/ undefined, maskModifiers(node, /*mask*/ undefined, (!accessors.setAccessor) ? ModifierFlags.Readonly : ModifierFlags.None), node.name, node.questionToken, ensureType(node, accessorType), /*initializer*/ undefined); const leadingsSyntheticCommentRanges = accessors.secondAccessor && getLeadingCommentRangesOfNode(accessors.secondAccessor, currentSourceFile); if (leadingsSyntheticCommentRanges) { @@ -1441,9 +1496,9 @@ namespace ts { return flags; } - function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined { + function getTypeAnnotationFromAccessor(accessor: AccessorLike): TypeNode | undefined { if (accessor) { - return accessor.kind === SyntaxKind.GetAccessor + return isGetAccessorLike(accessor) ? accessor.type // Getter - return type : accessor.parameters.length > 0 ? accessor.parameters[0].type // Setter parameter type @@ -1501,6 +1556,8 @@ namespace ts { | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration + | GetAccessorSignature + | SetAccessorSignature | PropertyDeclaration | PropertySignature | MethodSignature @@ -1522,6 +1579,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: case SyntaxKind.MethodSignature: diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 33465799c29..ca679864b67 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -15,6 +15,8 @@ namespace ts { | BindingElement | SetAccessorDeclaration | GetAccessorDeclaration + | SetAccessorSignature + | GetAccessorSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | MethodDeclaration @@ -34,8 +36,10 @@ namespace ts { isPropertyDeclaration(node) || isPropertySignature(node) || isBindingElement(node) || - isSetAccessor(node) || - isGetAccessor(node) || + isSetAccessorDeclaration(node) || + isGetAccessorDeclaration(node) || + isSetAccessorSignature(node) || + isGetAccessorSignature(node) || isConstructSignatureDeclaration(node) || isCallSignatureDeclaration(node) || isMethodDeclaration(node) || @@ -131,6 +135,9 @@ namespace ts { else if (isSetAccessor(node) || isGetAccessor(node)) { return getAccessorDeclarationTypeVisibilityError; } + else if (isAccessorSignature(node)) { + return getAccessorSignatureTypeVisibilityError; + } else if (isConstructSignatureDeclaration(node) || isCallSignatureDeclaration(node) || isMethodDeclaration(node) || isMethodSignature(node) || isFunctionDeclaration(node) || isIndexSignatureDeclaration(node)) { return getReturnTypeVisibilityError; } @@ -240,6 +247,29 @@ namespace ts { }; } + function getAccessorSignatureTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + let diagnosticMessage: DiagnosticMessage; + if (node.kind === SyntaxKind.SetAccessorSignature) { + // Getters can infer the return type from the returned expression, but setters cannot, so the + // "_from_external_module_1_but_cannot_be_named" case cannot occur. + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + Diagnostics.Parameter_type_of_setter_0_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_type_of_setter_0_from_exported_interface_has_or_is_using_private_name_1; + } + else { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_getter_0_from_exported_interface_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Return_type_of_getter_0_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Return_type_of_getter_0_from_exported_interface_has_or_is_using_private_name_1; + } + return { + diagnosticMessage, + errorNode: (node as NamedDeclaration).name!, + typeName: (node as NamedDeclaration).name + }; + } + function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; switch (node.kind) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3f1b30feb45..a57e5d7766a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -295,7 +295,9 @@ namespace ts { MethodDeclaration, Constructor, GetAccessor, + GetAccessorSignature, SetAccessor, + SetAccessorSignature, CallSignature, ConstructSignature, IndexSignature, @@ -648,6 +650,7 @@ namespace ts { | ConstructSignatureDeclaration | MethodSignature | PropertySignature + | AccessorSignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment @@ -871,6 +874,7 @@ namespace ts { | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature + | AccessorSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode @@ -1109,6 +1113,23 @@ namespace ts { export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; + export interface GetAccessorSignature extends SignatureDeclarationBase, TypeElement { + kind: SyntaxKind.GetAccessorSignature; + parent: ObjectTypeDeclaration; + name: PropertyName; + } + + export interface SetAccessorSignature extends SignatureDeclarationBase, TypeElement { + kind: SyntaxKind.SetAccessorSignature; + parent: ObjectTypeDeclaration; + name: PropertyName; + } + + export type AccessorSignature = GetAccessorSignature | SetAccessorSignature; + export type GetAccessorLike = GetAccessorDeclaration | GetAccessorSignature; + export type SetAccessorLike = SetAccessorDeclaration | SetAccessorSignature; + export type AccessorLike = AccessorDeclaration | AccessorSignature; + export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; parent: ObjectTypeDeclaration; @@ -3560,6 +3581,14 @@ namespace ts { setAccessor: SetAccessorDeclaration | undefined; } + /* @internal */ + export interface AllAccessorSignatures { + firstAccessor: AccessorSignature; + secondAccessor: AccessorSignature | undefined; + getAccessor: GetAccessorSignature | undefined; + setAccessor: SetAccessorSignature | undefined; + } + /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */ /* @internal */ export enum TypeReferenceSerializationKind { @@ -3620,6 +3649,7 @@ namespace ts { isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; getJsxFactoryEntity(location?: Node): EntityName | undefined; getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; + getAllAccessorSignatures(declaration: AccessorSignature): AllAccessorSignatures; getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined; isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4ca13e663ab..07947b53712 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -746,6 +746,8 @@ namespace ts { case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.IndexSignature: case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: @@ -921,6 +923,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -1097,6 +1101,8 @@ namespace ts { case SyntaxKind.MethodSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: return node === (parent).type; case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: @@ -1400,6 +1406,8 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: @@ -1456,6 +1464,8 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: return node; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. @@ -2520,6 +2530,8 @@ namespace ts { case SyntaxKind.MethodSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.EnumMember: case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAccessExpression: @@ -3518,7 +3530,7 @@ namespace ts { return find(node.members, (member): member is ConstructorDeclaration & { body: FunctionBody } => isConstructorDeclaration(member) && nodeIsPresent(member.body)); } - function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined { + function getSetAccessorValueParameter(accessor: SetAccessorLike): ParameterDeclaration | undefined { if (accessor && accessor.parameters.length > 0) { const hasThis = accessor.parameters.length === 2 && parameterIsThisKeyword(accessor.parameters[0]); return accessor.parameters[hasThis ? 1 : 0]; @@ -3526,7 +3538,7 @@ namespace ts { } /** Get the type annotation for the value parameter. */ - export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode | undefined { + export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorLike): TypeNode | undefined { const parameter = getSetAccessorValueParameter(accessor); return parameter && parameter.type; } @@ -3553,6 +3565,23 @@ namespace ts { return id.originalKeywordKind === SyntaxKind.ThisKeyword; } + export function getOtherAccessorLikeKind(node: AccessorLike) { + return isGetAccessorDeclaration(node) ? SyntaxKind.SetAccessor : + isGetAccessorSignature(node) ? SyntaxKind.SetAccessorSignature : + isSetAccessorDeclaration(node) ? SyntaxKind.GetAccessor : + SyntaxKind.GetAccessorSignature; + } + + export function getOtherAccessorDeclarationKind(node: AccessorLike) { + return isGetAccessorLike(node) ? SyntaxKind.SetAccessor : + SyntaxKind.GetAccessor; + } + + export function getOtherAccessorSignatureKind(node: AccessorLike) { + return isGetAccessorLike(node) ? SyntaxKind.SetAccessorSignature : + SyntaxKind.GetAccessorSignature; + } + export function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations { // TODO: GH#18217 let firstAccessor!: AccessorDeclaration; @@ -3641,7 +3670,7 @@ namespace ts { * Gets the effective type annotation of the value parameter of a set accessor. If the node * was parsed in a JavaScript file, gets the type annotation from JSDoc. */ - export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode | undefined { + export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorLike): TypeNode | undefined { const parameter = getSetAccessorValueParameter(node); return parameter && getEffectiveTypeAnnotationNode(parameter); } @@ -5541,6 +5570,46 @@ namespace ts { return node.kind === SyntaxKind.SetAccessor; } + export function isGetAccessorSignature(node: Node): node is GetAccessorSignature { + return node.kind === SyntaxKind.GetAccessorSignature; + } + + export function isSetAccessorSignature(node: Node): node is SetAccessorSignature { + return node.kind === SyntaxKind.SetAccessorSignature; + } + + export function isGetAccessorLike(node: Node): node is GetAccessorLike { + const kind = node.kind; + return kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.GetAccessorSignature; + } + + export function isSetAccessorLike(node: Node): node is SetAccessorLike { + const kind = node.kind; + return kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.SetAccessorSignature; + } + + export function isAccessorDeclaration(node: Node): node is AccessorDeclaration { + const kind = node.kind; + return kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor; + } + + export function isAccessorSignature(node: Node): node is AccessorSignature { + const kind = node.kind; + return kind === SyntaxKind.GetAccessorSignature + || kind === SyntaxKind.SetAccessorSignature; + } + + export function isAccessorLike(node: Node): node is AccessorLike { + const kind = node.kind; + return kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.GetAccessorSignature + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.SetAccessorSignature; + } + export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { return node.kind === SyntaxKind.CallSignature; } @@ -5553,9 +5622,10 @@ namespace ts { return node.kind === SyntaxKind.IndexSignature; } + /** @deprecated Use `isAccessorDeclaration` instead. */ /* @internal */ export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; + return isAccessorDeclaration(node); } // Type @@ -6347,6 +6417,8 @@ namespace ts { export function isFunctionLikeKind(kind: SyntaxKind): boolean { switch (kind) { case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessorSignature: + case SyntaxKind.SetAccessorSignature: case SyntaxKind.CallSignature: case SyntaxKind.JSDocSignature: case SyntaxKind.ConstructSignature: @@ -6381,8 +6453,9 @@ namespace ts { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } + /** @deprecated Use `isAccessorDeclaration` instead. */ export function isAccessor(node: Node): node is AccessorDeclaration { - return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor); + return isAccessorDeclaration(node); } /* @internal */ @@ -6405,6 +6478,8 @@ namespace ts { || kind === SyntaxKind.CallSignature || kind === SyntaxKind.PropertySignature || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.GetAccessorSignature + || kind === SyntaxKind.SetAccessorSignature || kind === SyntaxKind.IndexSignature; } @@ -6955,12 +7030,14 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode; } + /** @deprecated Use `isSetAccessorDeclaration` instead. */ export function isSetAccessor(node: Node): node is SetAccessorDeclaration { - return node.kind === SyntaxKind.SetAccessor; + return isSetAccessorDeclaration(node); } + /** @deprecated Use `isGetAccessorDeclaration` instead. */ export function isGetAccessor(node: Node): node is GetAccessorDeclaration { - return node.kind === SyntaxKind.GetAccessor; + return isGetAccessorDeclaration(node); } /** True if has jsdoc nodes attached to it. */ diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 53ccd81f7a6..eb25da4a96f 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -317,6 +317,21 @@ namespace ts { visitParameterList((node).parameters, visitor, context, nodesVisitor), visitFunctionBody((node).body!, visitor, context)); + case SyntaxKind.GetAccessorSignature: + return updateGetAccessorSignature(node, + nodesVisitor((node).decorators, visitor, isDecorator), + nodesVisitor((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isPropertyName), + nodesVisitor((node).parameters, visitor, isParameter), + visitNode((node).type, visitor, isTypeNode)); + + case SyntaxKind.SetAccessorSignature: + return updateSetAccessorSignature(node, + nodesVisitor((node).decorators, visitor, isDecorator), + nodesVisitor((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isPropertyName), + visitNodes((node).parameters, visitor, isParameter)); + case SyntaxKind.CallSignature: return updateCallSignature(node, nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), @@ -1034,6 +1049,15 @@ namespace ts { result = reduceNode((node).initializer, cbNode, result); break; + case SyntaxKind.MethodSignature: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).typeParameters, cbNodes, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + break; + case SyntaxKind.MethodDeclaration: result = reduceNodes((node).decorators, cbNodes, result); result = reduceNodes((node).modifiers, cbNodes, result); @@ -1060,11 +1084,26 @@ namespace ts { break; case SyntaxKind.SetAccessor: - result = reduceNodes((node).decorators, cbNodes, result); - result = reduceNodes((node).modifiers, cbNodes, result); - result = reduceNode((node).name, cbNode, result); - result = reduceNodes((node).parameters, cbNodes, result); - result = reduceNode((node).body, cbNode, result); + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.GetAccessorSignature: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).parameters, cbNodes, result); + result = reduceNode((node).type, cbNode, result); + break; + + case SyntaxKind.SetAccessorSignature: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).parameters, cbNodes, result); break; // Binding patterns