Skip to content

Commit ca0e616

Browse files
committed
feat(14417): add optionality to accessors
1 parent e1532a1 commit ca0e616

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+623
-37
lines changed

src/compiler/binder.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2637,9 +2637,9 @@ namespace ts {
26372637
case SyntaxKind.Constructor:
26382638
return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None);
26392639
case SyntaxKind.GetAccessor:
2640-
return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes);
2640+
return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor | ((node as GetAccessorDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.GetAccessorExcludes);
26412641
case SyntaxKind.SetAccessor:
2642-
return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes);
2642+
return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor | ((node as SetAccessorDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.SetAccessorExcludes);
26432643
case SyntaxKind.FunctionType:
26442644
case SyntaxKind.JSDocFunctionType:
26452645
case SyntaxKind.JSDocSignature:

src/compiler/checker.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -5709,8 +5709,8 @@ namespace ts {
57095709
kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
57105710
kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
57115711
kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) :
5712-
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
5713-
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
5712+
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*questionToken*/ undefined, /*body*/ undefined) :
5713+
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*questionToken*/ undefined, /*body*/ undefined) :
57145714
kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, modifiers, parameters, returnTypeNode) :
57155715
kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) :
57165716
kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
@@ -7787,6 +7787,7 @@ namespace ts {
77877787
/*questionToken*/ undefined,
77887788
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled)
77897789
)],
7790+
/*questionToken*/ undefined,
77907791
/*body*/ undefined
77917792
), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl));
77927793
}
@@ -7798,6 +7799,7 @@ namespace ts {
77987799
name,
77997800
[],
78007801
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
7802+
/*questionToken*/ undefined,
78017803
/*body*/ undefined
78027804
), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl));
78037805
}
@@ -9496,15 +9498,14 @@ namespace ts {
94969498
}
94979499

94989500
let type = resolveTypeOfAccessors(symbol, writing);
9499-
95009501
if (!popTypeResolution()) {
95019502
type = anyType;
95029503
if (noImplicitAny) {
95039504
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
95049505
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));
95059506
}
95069507
}
9507-
return type;
9508+
return type ? addOptionality(type, /*isProperty*/ true, !!(symbol.flags & SymbolFlags.Optional)) : undefined;
95089509
}
95099510

95109511
function resolveTypeOfAccessors(symbol: Symbol, writing = false) {
@@ -43241,9 +43242,11 @@ namespace ts {
4324143242
currentKind = DeclarationMeaning.Method;
4324243243
break;
4324343244
case SyntaxKind.GetAccessor:
43245+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4324443246
currentKind = DeclarationMeaning.GetAccessor;
4324543247
break;
4324643248
case SyntaxKind.SetAccessor:
43249+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4324743250
currentKind = DeclarationMeaning.SetAccessor;
4324843251
break;
4324943252
default:
@@ -43430,7 +43433,7 @@ namespace ts {
4343043433
if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) {
4343143434
return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
4343243435
}
43433-
if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
43436+
if (accessor.body === undefined && !hasQuestionToken(accessor) && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
4343443437
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
4343543438
}
4343643439
}

src/compiler/emitter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,7 @@ namespace ts {
21082108
writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set");
21092109
writeSpace();
21102110
emit(node.name);
2111+
emit(node.questionToken);
21112112
emitSignatureAndBody(node, emitSignatureHead);
21122113
}
21132114

src/compiler/factory/nodeFactory.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -1502,9 +1502,10 @@ namespace ts {
15021502
name: string | PropertyName,
15031503
parameters: readonly ParameterDeclaration[],
15041504
type: TypeNode | undefined,
1505+
questionToken: QuestionToken | undefined,
15051506
body: Block | undefined
15061507
) {
1507-
return createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
1508+
const node = createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
15081509
SyntaxKind.GetAccessor,
15091510
decorators,
15101511
modifiers,
@@ -1514,6 +1515,8 @@ namespace ts {
15141515
type,
15151516
body
15161517
);
1518+
node.questionToken = questionToken;
1519+
return node;
15171520
}
15181521

15191522
// @api
@@ -1524,15 +1527,17 @@ namespace ts {
15241527
name: PropertyName,
15251528
parameters: readonly ParameterDeclaration[],
15261529
type: TypeNode | undefined,
1530+
questionToken: QuestionToken | undefined,
15271531
body: Block | undefined
15281532
) {
15291533
return node.decorators !== decorators
15301534
|| node.modifiers !== modifiers
15311535
|| node.name !== name
15321536
|| node.parameters !== parameters
1537+
|| node.questionToken !== questionToken
15331538
|| node.type !== type
15341539
|| node.body !== body
1535-
? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node)
1540+
? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body), node)
15361541
: node;
15371542
}
15381543

@@ -1542,9 +1547,10 @@ namespace ts {
15421547
modifiers: readonly Modifier[] | undefined,
15431548
name: string | PropertyName,
15441549
parameters: readonly ParameterDeclaration[],
1550+
questionToken: QuestionToken | undefined,
15451551
body: Block | undefined
15461552
) {
1547-
return createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
1553+
const node = createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
15481554
SyntaxKind.SetAccessor,
15491555
decorators,
15501556
modifiers,
@@ -1554,6 +1560,8 @@ namespace ts {
15541560
/*type*/ undefined,
15551561
body
15561562
);
1563+
node.questionToken = questionToken;
1564+
return node;
15571565
}
15581566

15591567
// @api
@@ -1563,14 +1571,16 @@ namespace ts {
15631571
modifiers: readonly Modifier[] | undefined,
15641572
name: PropertyName,
15651573
parameters: readonly ParameterDeclaration[],
1574+
questionToken: QuestionToken | undefined,
15661575
body: Block | undefined
15671576
) {
15681577
return node.decorators !== decorators
15691578
|| node.modifiers !== modifiers
15701579
|| node.name !== name
15711580
|| node.parameters !== parameters
1581+
|| node.questionToken !== questionToken
15721582
|| node.body !== body
1573-
? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node)
1583+
? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body), node)
15741584
: node;
15751585
}
15761586

@@ -5755,6 +5765,7 @@ namespace ts {
57555765
/*type*/ undefined,
57565766
/*initializer*/ undefined
57575767
)],
5768+
/*questionToken*/ undefined,
57585769
createBlock([
57595770
createExpressionStatement(expression)
57605771
])
@@ -6094,8 +6105,8 @@ namespace ts {
60946105
isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
60956106
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
60966107
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifierArray, node.parameters, node.body) :
6097-
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.body) :
6098-
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.body) :
6108+
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.questionToken, node.body) :
6109+
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.questionToken, node.body) :
60996110
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifierArray, node.parameters, node.type) :
61006111
isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
61016112
isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :

src/compiler/parser.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6747,13 +6747,14 @@ namespace ts {
67476747

67486748
function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: AccessorDeclaration["kind"]): AccessorDeclaration {
67496749
const name = parsePropertyName();
6750+
const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
67506751
const typeParameters = parseTypeParameters();
67516752
const parameters = parseParameters(SignatureFlags.None);
67526753
const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
67536754
const body = parseFunctionBlockOrSemicolon(SignatureFlags.None);
67546755
const node = kind === SyntaxKind.GetAccessor
6755-
? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body)
6756-
: factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body);
6756+
? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body)
6757+
: factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body);
67576758
// Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors
67586759
node.typeParameters = typeParameters;
67596760
if (type && node.kind === SyntaxKind.SetAccessor) (node as Mutable<SetAccessorDeclaration>).type = type;

src/compiler/transformers/declarations.ts

+2
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,7 @@ namespace ts {
950950
input.name,
951951
updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
952952
ensureType(input, accessorType),
953+
input.questionToken,
953954
/*body*/ undefined));
954955
}
955956
case SyntaxKind.SetAccessor: {
@@ -962,6 +963,7 @@ namespace ts {
962963
ensureModifiers(input),
963964
input.name,
964965
updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
966+
input.questionToken,
965967
/*body*/ undefined));
966968
}
967969
case SyntaxKind.PropertyDeclaration:

src/compiler/transformers/es2015.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3649,10 +3649,10 @@ namespace ts {
36493649
const parameters = visitParameterList(node.parameters, visitor, context);
36503650
const body = transformFunctionBody(node);
36513651
if (node.kind === SyntaxKind.GetAccessor) {
3652-
updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, body);
3652+
updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, node.questionToken, body);
36533653
}
36543654
else {
3655-
updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, body);
3655+
updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.questionToken, body);
36563656
}
36573657
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
36583658
convertedLoopState = savedConvertedLoopState;

src/compiler/transformers/es2018.ts

+2
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,7 @@ namespace ts {
864864
visitNode(node.name, visitor, isPropertyName),
865865
visitParameterList(node.parameters, parameterVisitor, context),
866866
/*type*/ undefined,
867+
visitNode<Token<SyntaxKind.QuestionToken>>(/*questionToken*/ undefined, visitor, isToken),
867868
transformFunctionBody(node)
868869
);
869870
enclosingFunctionFlags = savedEnclosingFunctionFlags;
@@ -882,6 +883,7 @@ namespace ts {
882883
node.modifiers,
883884
visitNode(node.name, visitor, isPropertyName),
884885
visitParameterList(node.parameters, parameterVisitor, context),
886+
visitNode<Token<SyntaxKind.QuestionToken>>(/*questionToken*/ undefined, visitor, isToken),
885887
transformFunctionBody(node)
886888
);
887889
enclosingFunctionFlags = savedEnclosingFunctionFlags;

src/compiler/transformers/ts.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,7 @@ namespace ts {
20702070
visitPropertyNameOfClassElement(node),
20712071
visitParameterList(node.parameters, visitor, context),
20722072
/*type*/ undefined,
2073+
/*questionToken*/ undefined,
20732074
visitFunctionBody(node.body, visitor, context) || factory.createBlock([])
20742075
);
20752076
if (updated !== node) {
@@ -2091,6 +2092,7 @@ namespace ts {
20912092
visitNodes(node.modifiers, modifierVisitor, isModifier),
20922093
visitPropertyNameOfClassElement(node),
20932094
visitParameterList(node.parameters, visitor, context),
2095+
/*questionToken*/ undefined,
20942096
visitFunctionBody(node.body, visitor, context) || factory.createBlock([])
20952097
);
20962098
if (updated !== node) {

0 commit comments

Comments
 (0)