Skip to content

Commit 298ea35

Browse files
committed
feat(14417): add optionality to accessors
1 parent fd620c9 commit 298ea35

Some content is hidden

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

45 files changed

+452
-37
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 2 deletions
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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5663,8 +5663,8 @@ namespace ts {
56635663
kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
56645664
kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
56655665
kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) :
5666-
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
5667-
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
5666+
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*questionToken*/ undefined, /*body*/ undefined) :
5667+
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*questionToken*/ undefined, /*body*/ undefined) :
56685668
kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, modifiers, parameters, returnTypeNode) :
56695669
kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) :
56705670
kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
@@ -7731,6 +7731,7 @@ namespace ts {
77317731
/*questionToken*/ undefined,
77327732
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled)
77337733
)],
7734+
/*questionToken*/ undefined,
77347735
/*body*/ undefined
77357736
), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl));
77367737
}
@@ -7742,6 +7743,7 @@ namespace ts {
77427743
name,
77437744
[],
77447745
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
7746+
/*questionToken*/ undefined,
77457747
/*body*/ undefined
77467748
), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl));
77477749
}
@@ -9416,15 +9418,14 @@ namespace ts {
94169418
}
94179419

94189420
let type = resolveTypeOfAccessors(symbol, writing);
9419-
94209421
if (!popTypeResolution()) {
94219422
type = anyType;
94229423
if (noImplicitAny) {
94239424
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
94249425
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));
94259426
}
94269427
}
9427-
return type;
9428+
return type ? addOptionality(type, /*isProperty*/ true, !!(symbol.flags & SymbolFlags.Optional)) : undefined;
94289429
}
94299430

94309431
function resolveTypeOfAccessors(symbol: Symbol, writing = false) {
@@ -42972,9 +42973,11 @@ namespace ts {
4297242973
currentKind = DeclarationMeaning.Method;
4297342974
break;
4297442975
case SyntaxKind.GetAccessor:
42976+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4297542977
currentKind = DeclarationMeaning.GetAccessor;
4297642978
break;
4297742979
case SyntaxKind.SetAccessor:
42980+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4297842981
currentKind = DeclarationMeaning.SetAccessor;
4297942982
break;
4298042983
default:
@@ -43158,7 +43161,7 @@ namespace ts {
4315843161
if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) {
4315943162
return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
4316043163
}
43161-
if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
43164+
if (accessor.body === undefined && !hasQuestionToken(accessor) && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
4316243165
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
4316343166
}
4316443167
}

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,6 +2103,7 @@ namespace ts {
21032103
writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set");
21042104
writeSpace();
21052105
emit(node.name);
2106+
emit(node.questionToken);
21062107
emitSignatureAndBody(node, emitSignatureHead);
21072108
}
21082109

src/compiler/factory/nodeFactory.ts

Lines changed: 17 additions & 6 deletions
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
])
@@ -6089,8 +6100,8 @@ namespace ts {
60896100
isMethodSignature(node) ? updateMethodSignature(node, modifiers, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
60906101
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
60916102
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifiers, node.parameters, node.body) :
6092-
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.body) :
6093-
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.body) :
6103+
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.questionToken, node.body) :
6104+
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.questionToken, node.body) :
60946105
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifiers, node.parameters, node.type) :
60956106
isFunctionExpression(node) ? updateFunctionExpression(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
60966107
isArrowFunction(node) ? updateArrowFunction(node, modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :

src/compiler/parser.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6740,13 +6740,14 @@ namespace ts {
67406740

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

src/compiler/transformers/declarations.ts

Lines changed: 2 additions & 0 deletions
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3586,10 +3586,10 @@ namespace ts {
35863586
const parameters = visitParameterList(node.parameters, visitor, context);
35873587
const body = transformFunctionBody(node);
35883588
if (node.kind === SyntaxKind.GetAccessor) {
3589-
updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, body);
3589+
updated = factory.updateGetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.type, node.questionToken, body);
35903590
}
35913591
else {
3592-
updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, body);
3592+
updated = factory.updateSetAccessorDeclaration(node, node.decorators, node.modifiers, node.name, parameters, node.questionToken, body);
35933593
}
35943594
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
35953595
convertedLoopState = savedConvertedLoopState;

src/compiler/transformers/es2018.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ namespace ts {
827827
visitNode(node.name, visitor, isPropertyName),
828828
visitParameterList(node.parameters, visitor, context),
829829
/*type*/ undefined,
830+
visitNode<Token<SyntaxKind.QuestionToken>>(/*questionToken*/ undefined, visitor, isToken),
830831
transformFunctionBody(node)
831832
);
832833
enclosingFunctionFlags = savedEnclosingFunctionFlags;
@@ -842,6 +843,7 @@ namespace ts {
842843
node.modifiers,
843844
visitNode(node.name, visitor, isPropertyName),
844845
visitParameterList(node.parameters, visitor, context),
846+
visitNode<Token<SyntaxKind.QuestionToken>>(/*questionToken*/ undefined, visitor, isToken),
845847
transformFunctionBody(node)
846848
);
847849
enclosingFunctionFlags = savedEnclosingFunctionFlags;

src/compiler/transformers/ts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,7 @@ namespace ts {
20522052
visitPropertyNameOfClassElement(node),
20532053
visitParameterList(node.parameters, visitor, context),
20542054
/*type*/ undefined,
2055+
/*questionToken*/ undefined,
20552056
visitFunctionBody(node.body, visitor, context) || factory.createBlock([])
20562057
);
20572058
if (updated !== node) {
@@ -2073,6 +2074,7 @@ namespace ts {
20732074
visitNodes(node.modifiers, modifierVisitor, isModifier),
20742075
visitPropertyNameOfClassElement(node),
20752076
visitParameterList(node.parameters, visitor, context),
2077+
/*questionToken*/ undefined,
20762078
visitFunctionBody(node.body, visitor, context) || factory.createBlock([])
20772079
);
20782080
if (updated !== node) {

0 commit comments

Comments
 (0)