Skip to content

Commit b3487dc

Browse files
committed
Support for auto-accessor fields
1 parent e9ba547 commit b3487dc

File tree

150 files changed

+4462
-833
lines changed

Some content is hidden

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

150 files changed

+4462
-833
lines changed

scripts/eslint/rules/debug-assert.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export = createRule({
4343
context.report({ messageId: "secondArgumentDebugAssertError", node: message1Node });
4444
}
4545

46-
if (argsLen < 3) {
46+
if (argsLen < 3 || argsLen > 3) {
4747
return;
4848
}
4949

src/compiler/binder.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -2744,7 +2744,10 @@ namespace ts {
27442744
}
27452745

27462746
function bindPropertyWorker(node: PropertyDeclaration | PropertySignature) {
2747-
return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
2747+
const isAutoAccessor = isAutoAccessorPropertyDeclaration(node);
2748+
const includes = isAutoAccessor ? SymbolFlags.Accessor : SymbolFlags.Property;
2749+
const excludes = isAutoAccessor ? SymbolFlags.AccessorExcludes : SymbolFlags.PropertyExcludes;
2750+
return bindPropertyOrMethodOrAccessor(node, includes | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), excludes);
27482751
}
27492752

27502753
function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral) {

src/compiler/checker.ts

+67-15
Original file line numberDiff line numberDiff line change
@@ -9658,21 +9658,25 @@ namespace ts {
96589658
return type;
96599659
}
96609660

9661-
function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | undefined): TypeNode | undefined {
9661+
function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | PropertyDeclaration | undefined): TypeNode | undefined {
96629662
if (accessor) {
9663-
if (accessor.kind === SyntaxKind.GetAccessor) {
9664-
const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor);
9665-
return getterTypeAnnotation;
9666-
}
9667-
else {
9668-
const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor);
9669-
return setterTypeAnnotation;
9663+
switch (accessor.kind) {
9664+
case SyntaxKind.GetAccessor:
9665+
const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor);
9666+
return getterTypeAnnotation;
9667+
case SyntaxKind.SetAccessor:
9668+
const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor);
9669+
return setterTypeAnnotation;
9670+
case SyntaxKind.PropertyDeclaration:
9671+
Debug.assert(hasAccessorModifier(accessor));
9672+
const accessorTypeAnnotation = getEffectiveTypeAnnotationNode(accessor);
9673+
return accessorTypeAnnotation;
96709674
}
96719675
}
96729676
return undefined;
96739677
}
96749678

9675-
function getAnnotatedAccessorType(accessor: AccessorDeclaration | undefined): Type | undefined {
9679+
function getAnnotatedAccessorType(accessor: AccessorDeclaration | PropertyDeclaration | undefined): Type | undefined {
96769680
const node = getAnnotatedAccessorTypeNode(accessor);
96779681
return node && getTypeFromTypeNode(node);
96789682
}
@@ -9694,19 +9698,26 @@ namespace ts {
96949698
}
96959699
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
96969700
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
9701+
const accessor = tryCast(getDeclarationOfKind<PropertyDeclaration>(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration);
9702+
96979703
// We try to resolve a getter type annotation, a setter type annotation, or a getter function
96989704
// body return type inference, in that order.
96999705
let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) ||
97009706
getAnnotatedAccessorType(getter) ||
97019707
getAnnotatedAccessorType(setter) ||
9702-
getter && getter.body && getReturnTypeFromBody(getter);
9708+
getAnnotatedAccessorType(accessor) ||
9709+
getter && getter.body && getReturnTypeFromBody(getter) ||
9710+
accessor && accessor.initializer && getWidenedTypeForVariableLikeDeclaration(accessor, /*includeOptionality*/ true);
97039711
if (!type) {
97049712
if (setter && !isPrivateWithinAmbient(setter)) {
97059713
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
97069714
}
97079715
else if (getter && !isPrivateWithinAmbient(getter)) {
97089716
errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
97099717
}
9718+
else if (accessor && !isPrivateWithinAmbient(accessor)) {
9719+
errorOrSuggestion(noImplicitAny, accessor, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), "any");
9720+
}
97109721
type = anyType;
97119722
}
97129723
if (!popTypeResolution()) {
@@ -9716,6 +9727,9 @@ namespace ts {
97169727
else if (getAnnotatedAccessorTypeNode(setter)) {
97179728
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
97189729
}
9730+
else if (getAnnotatedAccessorTypeNode(accessor)) {
9731+
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
9732+
}
97199733
else if (getter && noImplicitAny) {
97209734
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));
97219735
}
@@ -9732,7 +9746,9 @@ namespace ts {
97329746
if (!pushTypeResolution(symbol, TypeSystemPropertyName.WriteType)) {
97339747
return errorType;
97349748
}
9735-
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
9749+
9750+
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor)
9751+
?? tryCast(getDeclarationOfKind<PropertyDeclaration>(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration);
97369752
let writeType = getAnnotatedAccessorType(setter);
97379753
if (!popTypeResolution()) {
97389754
if (getAnnotatedAccessorTypeNode(setter)) {
@@ -10890,8 +10906,10 @@ namespace ts {
1089010906
const members = getMembersOfDeclaration(decl);
1089110907
if (members) {
1089210908
for (const member of members) {
10893-
if (isStatic === hasStaticModifier(member) && hasLateBindableName(member)) {
10894-
lateBindMember(symbol, earlySymbols, lateSymbols, member);
10909+
if (isStatic === hasStaticModifier(member)) {
10910+
if (hasLateBindableName(member)) {
10911+
lateBindMember(symbol, earlySymbols, lateSymbols, member);
10912+
}
1089510913
}
1089610914
}
1089710915
}
@@ -10905,8 +10923,10 @@ namespace ts {
1090510923
|| isBinaryExpression(member) && isPossiblyAliasedThisProperty(member, assignmentKind)
1090610924
|| assignmentKind === AssignmentDeclarationKind.ObjectDefinePrototypeProperty
1090710925
|| assignmentKind === AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name
10908-
if (isStatic === !isInstanceMember && hasLateBindableName(member)) {
10909-
lateBindMember(symbol, earlySymbols, lateSymbols, member);
10926+
if (isStatic === !isInstanceMember) {
10927+
if (hasLateBindableName(member)) {
10928+
lateBindMember(symbol, earlySymbols, lateSymbols, member);
10929+
}
1091010930
}
1091110931
}
1091210932
}
@@ -43572,6 +43592,9 @@ namespace ts {
4357243592
else if (flags & ModifierFlags.Readonly) {
4357343593
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly");
4357443594
}
43595+
else if (flags & ModifierFlags.Accessor) {
43596+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "accessor");
43597+
}
4357543598
else if (flags & ModifierFlags.Async) {
4357643599
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async");
4357743600
}
@@ -43593,6 +43616,9 @@ namespace ts {
4359343616
else if (flags & ModifierFlags.Static) {
4359443617
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
4359543618
}
43619+
else if (flags & ModifierFlags.Accessor) {
43620+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "accessor");
43621+
}
4359643622
else if (flags & ModifierFlags.Readonly) {
4359743623
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly");
4359843624
}
@@ -43626,6 +43652,9 @@ namespace ts {
4362643652
else if (flags & ModifierFlags.Async) {
4362743653
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async");
4362843654
}
43655+
else if (flags & ModifierFlags.Accessor) {
43656+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "accessor");
43657+
}
4362943658
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
4363043659
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static");
4363143660
}
@@ -43642,6 +43671,23 @@ namespace ts {
4364243671
lastStatic = modifier;
4364343672
break;
4364443673

43674+
case SyntaxKind.AccessorKeyword:
43675+
if (flags & ModifierFlags.Accessor) {
43676+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "accessor");
43677+
}
43678+
else if (flags & ModifierFlags.Readonly) {
43679+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "readonly");
43680+
}
43681+
else if (flags & ModifierFlags.Ambient) {
43682+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "declare");
43683+
}
43684+
else if (node.kind !== SyntaxKind.PropertyDeclaration) {
43685+
return grammarErrorOnNode(modifier, Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration);
43686+
}
43687+
43688+
flags |= ModifierFlags.Accessor;
43689+
break;
43690+
4364543691
case SyntaxKind.ReadonlyKeyword:
4364643692
if (flags & ModifierFlags.Readonly) {
4364743693
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly");
@@ -43738,6 +43784,9 @@ namespace ts {
4373843784
if (flags & ModifierFlags.Override) {
4373943785
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "override");
4374043786
}
43787+
if (flags & ModifierFlags.Accessor) {
43788+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "accessor");
43789+
}
4374143790
}
4374243791
if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.PrivateIdentifier) {
4374343792
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "abstract");
@@ -44939,6 +44988,9 @@ namespace ts {
4493944988
if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) {
4494044989
return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
4494144990
}
44991+
if (languageVersion < ScriptTarget.ES2015 && hasAccessorModifier(node)) {
44992+
return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher);
44993+
}
4494244994
}
4494344995
else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) {
4494444996
if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) {

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,10 @@
899899
"category": "Error",
900900
"code": 1274
901901
},
902+
"'accessor' modifier can only appear on a property declaration.": {
903+
"category": "Error",
904+
"code": 1275
905+
},
902906

903907
"'with' statements are not allowed in an async function block.": {
904908
"category": "Error",
@@ -7380,5 +7384,9 @@
73807384
"A 'return' statement cannot be used inside a class static block.": {
73817385
"category": "Error",
73827386
"code": 18041
7387+
},
7388+
"Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher.": {
7389+
"category": "Error",
7390+
"code": 18042
73837391
}
73847392
}

0 commit comments

Comments
 (0)