Skip to content

Commit d2f306f

Browse files
committed
feat(14417): add optionality to accessors
1 parent 107c556 commit d2f306f

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
@@ -5512,8 +5512,8 @@ namespace ts {
55125512
kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
55135513
kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
55145514
kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) :
5515-
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
5516-
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
5515+
kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*questionToken*/ undefined, /*body*/ undefined) :
5516+
kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*questionToken*/ undefined, /*body*/ undefined) :
55175517
kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, modifiers, parameters, returnTypeNode) :
55185518
kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) :
55195519
kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
@@ -7544,6 +7544,7 @@ namespace ts {
75447544
/*questionToken*/ undefined,
75457545
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled)
75467546
)],
7547+
/*questionToken*/ undefined,
75477548
/*body*/ undefined
75487549
), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl));
75497550
}
@@ -7555,6 +7556,7 @@ namespace ts {
75557556
name,
75567557
[],
75577558
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
7559+
/*questionToken*/ undefined,
75587560
/*body*/ undefined
75597561
), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl));
75607562
}
@@ -9223,15 +9225,14 @@ namespace ts {
92239225
}
92249226

92259227
let type = resolveTypeOfAccessors(symbol, writing);
9226-
92279228
if (!popTypeResolution()) {
92289229
type = anyType;
92299230
if (noImplicitAny) {
92309231
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
92319232
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));
92329233
}
92339234
}
9234-
return type;
9235+
return type ? addOptionality(type, /*isProperty*/ true, !!(symbol.flags & SymbolFlags.Optional)) : undefined;
92359236
}
92369237

92379238
function resolveTypeOfAccessors(symbol: Symbol, writing = false) {
@@ -42026,9 +42027,11 @@ namespace ts {
4202642027
currentKind = DeclarationMeaning.Method;
4202742028
break;
4202842029
case SyntaxKind.GetAccessor:
42030+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4202942031
currentKind = DeclarationMeaning.GetAccessor;
4203042032
break;
4203142033
case SyntaxKind.SetAccessor:
42034+
checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
4203242035
currentKind = DeclarationMeaning.SetAccessor;
4203342036
break;
4203442037
default:
@@ -42212,7 +42215,7 @@ namespace ts {
4221242215
if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) {
4221342216
return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
4221442217
}
42215-
if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
42218+
if (accessor.body === undefined && !hasQuestionToken(accessor) && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
4221642219
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
4221742220
}
4221842221
}

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,7 @@ namespace ts {
20842084
writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set");
20852085
writeSpace();
20862086
emit(node.name);
2087+
emit(node.questionToken);
20872088
emitSignatureAndBody(node, emitSignatureHead);
20882089
}
20892090

src/compiler/factory/nodeFactory.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,9 +1498,10 @@ namespace ts {
14981498
name: string | PropertyName,
14991499
parameters: readonly ParameterDeclaration[],
15001500
type: TypeNode | undefined,
1501+
questionToken: QuestionToken | undefined,
15011502
body: Block | undefined
15021503
) {
1503-
return createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
1504+
const node = createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
15041505
SyntaxKind.GetAccessor,
15051506
decorators,
15061507
modifiers,
@@ -1510,6 +1511,8 @@ namespace ts {
15101511
type,
15111512
body
15121513
);
1514+
node.questionToken = questionToken;
1515+
return node;
15131516
}
15141517

15151518
// @api
@@ -1520,15 +1523,17 @@ namespace ts {
15201523
name: PropertyName,
15211524
parameters: readonly ParameterDeclaration[],
15221525
type: TypeNode | undefined,
1526+
questionToken: QuestionToken | undefined,
15231527
body: Block | undefined
15241528
) {
15251529
return node.decorators !== decorators
15261530
|| node.modifiers !== modifiers
15271531
|| node.name !== name
15281532
|| node.parameters !== parameters
1533+
|| node.questionToken !== questionToken
15291534
|| node.type !== type
15301535
|| node.body !== body
1531-
? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node)
1536+
? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body), node)
15321537
: node;
15331538
}
15341539

@@ -1538,9 +1543,10 @@ namespace ts {
15381543
modifiers: readonly Modifier[] | undefined,
15391544
name: string | PropertyName,
15401545
parameters: readonly ParameterDeclaration[],
1546+
questionToken: QuestionToken | undefined,
15411547
body: Block | undefined
15421548
) {
1543-
return createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
1549+
const node = createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
15441550
SyntaxKind.SetAccessor,
15451551
decorators,
15461552
modifiers,
@@ -1550,6 +1556,8 @@ namespace ts {
15501556
/*type*/ undefined,
15511557
body
15521558
);
1559+
node.questionToken = questionToken;
1560+
return node;
15531561
}
15541562

15551563
// @api
@@ -1559,14 +1567,16 @@ namespace ts {
15591567
modifiers: readonly Modifier[] | undefined,
15601568
name: PropertyName,
15611569
parameters: readonly ParameterDeclaration[],
1570+
questionToken: QuestionToken | undefined,
15621571
body: Block | undefined
15631572
) {
15641573
return node.decorators !== decorators
15651574
|| node.modifiers !== modifiers
15661575
|| node.name !== name
15671576
|| node.parameters !== parameters
1577+
|| node.questionToken !== questionToken
15681578
|| node.body !== body
1569-
? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node)
1579+
? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body), node)
15701580
: node;
15711581
}
15721582

@@ -5700,6 +5710,7 @@ namespace ts {
57005710
/*type*/ undefined,
57015711
/*initializer*/ undefined
57025712
)],
5713+
/*questionToken*/ undefined,
57035714
createBlock([
57045715
createExpressionStatement(expression)
57055716
])
@@ -6034,8 +6045,8 @@ namespace ts {
60346045
isMethodSignature(node) ? updateMethodSignature(node, modifiers, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
60356046
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
60366047
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifiers, node.parameters, node.body) :
6037-
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.body) :
6038-
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.body) :
6048+
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.questionToken, node.body) :
6049+
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.questionToken, node.body) :
60396050
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifiers, node.parameters, node.type) :
60406051
isFunctionExpression(node) ? updateFunctionExpression(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
60416052
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
@@ -6720,13 +6720,14 @@ namespace ts {
67206720

67216721
function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: AccessorDeclaration["kind"]): AccessorDeclaration {
67226722
const name = parsePropertyName();
6723+
const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
67236724
const typeParameters = parseTypeParameters();
67246725
const parameters = parseParameters(SignatureFlags.None);
67256726
const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
67266727
const body = parseFunctionBlockOrSemicolon(SignatureFlags.None);
67276728
const node = kind === SyntaxKind.GetAccessor
6728-
? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body)
6729-
: factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body);
6729+
? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, questionToken, body)
6730+
: factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, questionToken, body);
67306731
// Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors
67316732
node.typeParameters = typeParameters;
67326733
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
@@ -947,6 +947,7 @@ namespace ts {
947947
input.name,
948948
updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
949949
ensureType(input, accessorType),
950+
input.questionToken,
950951
/*body*/ undefined));
951952
}
952953
case SyntaxKind.SetAccessor: {
@@ -959,6 +960,7 @@ namespace ts {
959960
ensureModifiers(input),
960961
input.name,
961962
updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
963+
input.questionToken,
962964
/*body*/ undefined));
963965
}
964966
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)