Skip to content

Commit 7b1fc75

Browse files
committed
feat(1534): add final keyword
1 parent ed6007d commit 7b1fc75

Some content is hidden

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

57 files changed

+1093
-516
lines changed

src/compiler/checker.ts

+27-3
Original file line numberDiff line numberDiff line change
@@ -11799,6 +11799,7 @@ namespace ts {
1179911799
(!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
1180011800
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
1180111801
(modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
11802+
(modifiers & ModifierFlags.Final ? CheckFlags.ContainsFinal : 0) |
1180211803
(modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
1180311804
if (!isPrototypeProperty(prop)) {
1180411805
syntheticFlag = CheckFlags.SyntheticProperty;
@@ -19031,6 +19032,13 @@ namespace ts {
1903119032
return Ternary.False;
1903219033
}
1903319034
}
19035+
else if (targetPropFlags & ModifierFlags.Final) {
19036+
if (reportErrors) {
19037+
reportError(Diagnostics.Property_0_is_final_in_type_1_that_cannot_be_overridden_in_type_2, symbolToString(targetProp),
19038+
typeToString(target), typeToString(source));
19039+
}
19040+
return Ternary.False;
19041+
}
1903419042
else if (targetPropFlags & ModifierFlags.Protected) {
1903519043
if (!isValidOverrideOf(sourceProp, targetProp)) {
1903619044
if (reportErrors) {
@@ -41091,7 +41099,7 @@ namespace ts {
4109141099
return quickResult;
4109241100
}
4109341101

41094-
let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastReadonly: Node | undefined, lastOverride: Node | undefined;
41102+
let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastReadonly: Node | undefined, lastOverride: Node | undefined, lastFinal: Node | undefined;
4109541103
let flags = ModifierFlags.None;
4109641104
for (const modifier of node.modifiers!) {
4109741105
if (modifier.kind !== SyntaxKind.ReadonlyKeyword) {
@@ -41233,6 +41241,19 @@ namespace ts {
4123341241

4123441242
flags |= ModifierFlags.Default;
4123541243
break;
41244+
case SyntaxKind.FinalKeyword:
41245+
if (flags & ModifierFlags.Final) {
41246+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "final");
41247+
}
41248+
if (flags & ModifierFlags.Private) {
41249+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "final", "private");
41250+
}
41251+
if (flags & ModifierFlags.Abstract) {
41252+
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "final", "abstract");
41253+
}
41254+
flags |= ModifierFlags.Final;
41255+
lastFinal = modifier;
41256+
break;
4123641257
case SyntaxKind.DeclareKeyword:
4123741258
if (flags & ModifierFlags.Ambient) {
4123841259
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
@@ -41323,12 +41344,15 @@ namespace ts {
4132341344
if (flags & ModifierFlags.Override) {
4132441345
return grammarErrorOnNode(lastOverride!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "override"); // TODO: GH#18217
4132541346
}
41326-
else if (flags & ModifierFlags.Async) {
41347+
if (flags & ModifierFlags.Async) {
4132741348
return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
4132841349
}
41329-
else if (flags & ModifierFlags.Readonly) {
41350+
if (flags & ModifierFlags.Readonly) {
4133041351
return grammarErrorOnNode(lastReadonly!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly");
4133141352
}
41353+
if (flags & ModifierFlags.Final) {
41354+
return grammarErrorOnNode(lastFinal!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "final");
41355+
}
4133241356
return false;
4133341357
}
4133441358
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -3356,6 +3356,10 @@
33563356
"category": "Error",
33573357
"code": 2818
33583358
},
3359+
"Property '{0}' is final in type '{1}' that cannot be overridden in type '{2}'.": {
3360+
"category": "Error",
3361+
"code": 2819
3362+
},
33593363

33603364
"Import declaration '{0}' is using private name '{1}'.": {
33613365
"category": "Error",

src/compiler/factory/nodeFactory.ts

+2
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ namespace ts {
983983
case SyntaxKind.PublicKeyword:
984984
case SyntaxKind.PrivateKeyword:
985985
case SyntaxKind.ProtectedKeyword:
986+
case SyntaxKind.FinalKeyword:
986987
case SyntaxKind.ReadonlyKeyword:
987988
case SyntaxKind.AbstractKeyword:
988989
case SyntaxKind.DeclareKeyword:
@@ -1064,6 +1065,7 @@ namespace ts {
10641065
if (flags & ModifierFlags.Default) { result.push(createModifier(SyntaxKind.DefaultKeyword)); }
10651066
if (flags & ModifierFlags.Const) { result.push(createModifier(SyntaxKind.ConstKeyword)); }
10661067
if (flags & ModifierFlags.Public) { result.push(createModifier(SyntaxKind.PublicKeyword)); }
1068+
if (flags & ModifierFlags.Final) { result.push(createModifier(SyntaxKind.FinalKeyword)); }
10671069
if (flags & ModifierFlags.Private) { result.push(createModifier(SyntaxKind.PrivateKeyword)); }
10681070
if (flags & ModifierFlags.Protected) { result.push(createModifier(SyntaxKind.ProtectedKeyword)); }
10691071
if (flags & ModifierFlags.Abstract) { result.push(createModifier(SyntaxKind.AbstractKeyword)); }

src/compiler/program.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,7 @@ namespace ts {
21582158
case SyntaxKind.PublicKeyword:
21592159
case SyntaxKind.PrivateKeyword:
21602160
case SyntaxKind.ProtectedKeyword:
2161+
case SyntaxKind.FinalKeyword:
21612162
case SyntaxKind.ReadonlyKeyword:
21622163
case SyntaxKind.DeclareKeyword:
21632164
case SyntaxKind.AbstractKeyword:

src/compiler/scanner.ts

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ namespace ts {
128128
private: SyntaxKind.PrivateKeyword,
129129
protected: SyntaxKind.ProtectedKeyword,
130130
public: SyntaxKind.PublicKeyword,
131+
final: SyntaxKind.FinalKeyword,
131132
override: SyntaxKind.OverrideKeyword,
132133
readonly: SyntaxKind.ReadonlyKeyword,
133134
require: SyntaxKind.RequireKeyword,

src/compiler/transformers/ts.ts

+1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ namespace ts {
368368
case SyntaxKind.PublicKeyword:
369369
case SyntaxKind.PrivateKeyword:
370370
case SyntaxKind.ProtectedKeyword:
371+
case SyntaxKind.FinalKeyword:
371372
case SyntaxKind.AbstractKeyword:
372373
case SyntaxKind.OverrideKeyword:
373374
case SyntaxKind.ConstKeyword:

src/compiler/types.ts

+21-14
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ namespace ts {
156156
ProtectedKeyword,
157157
PublicKeyword,
158158
StaticKeyword,
159+
FinalKeyword,
159160
YieldKeyword,
160161
// Contextual keywords
161162
AbstractKeyword,
@@ -594,6 +595,7 @@ namespace ts {
594595
| SyntaxKind.PrivateKeyword
595596
| SyntaxKind.ProtectedKeyword
596597
| SyntaxKind.PublicKeyword
598+
| SyntaxKind.FinalKeyword
597599
| SyntaxKind.ReadonlyKeyword
598600
| SyntaxKind.OverrideKeyword
599601
| SyntaxKind.RequireKeyword
@@ -630,6 +632,7 @@ namespace ts {
630632
| SyntaxKind.PrivateKeyword
631633
| SyntaxKind.ProtectedKeyword
632634
| SyntaxKind.PublicKeyword
635+
| SyntaxKind.FinalKeyword
633636
| SyntaxKind.ReadonlyKeyword
634637
| SyntaxKind.OverrideKeyword
635638
| SyntaxKind.StaticKeyword
@@ -802,9 +805,10 @@ namespace ts {
802805
Protected = 1 << 4, // Property/Method
803806
Static = 1 << 5, // Property/Method
804807
Readonly = 1 << 6, // Property/Method
805-
Abstract = 1 << 7, // Class/Method/ConstructSignature
806-
Async = 1 << 8, // Property/Method/Function
807-
Default = 1 << 9, // Function/Class (export default declaration)
808+
Final = 1 << 7, // Property/Method
809+
Abstract = 1 << 8, // Class/Method/ConstructSignature
810+
Async = 1 << 9, // Property/Method/Function
811+
Default = 1 << 10, // Function/Class (export default declaration)
808812
Const = 1 << 11, // Const enum
809813
HasComputedJSDocModifiers = 1 << 12, // Indicates the computed modifier flags include modifiers from JSDoc.
810814

@@ -817,9 +821,9 @@ namespace ts {
817821
ParameterPropertyModifier = AccessibilityModifier | Readonly | Override,
818822
NonPublicAccessibilityModifier = Private | Protected,
819823

820-
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override,
824+
TypeScriptModifier = Ambient | Public | Private | Protected | Final | Readonly | Abstract | Const | Override,
821825
ExportDefault = Export | Default,
822-
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Async | Default | Const | Deprecated | Override
826+
All = Export | Ambient | Public | Private | Protected | Final | Static | Readonly | Abstract | Async | Default | Const | Deprecated | Override
823827
}
824828

825829
export const enum JsxFlags {
@@ -1059,6 +1063,7 @@ namespace ts {
10591063
export type PrivateKeyword = ModifierToken<SyntaxKind.PrivateKeyword>;
10601064
export type ProtectedKeyword = ModifierToken<SyntaxKind.ProtectedKeyword>;
10611065
export type PublicKeyword = ModifierToken<SyntaxKind.PublicKeyword>;
1066+
export type FinalKeyword = ModifierToken<SyntaxKind.FinalKeyword>;
10621067
export type ReadonlyKeyword = ModifierToken<SyntaxKind.ReadonlyKeyword>;
10631068
export type OverrideKeyword = ModifierToken<SyntaxKind.OverrideKeyword>;
10641069
export type StaticKeyword = ModifierToken<SyntaxKind.StaticKeyword>;
@@ -1076,6 +1081,7 @@ namespace ts {
10761081
| PrivateKeyword
10771082
| ProtectedKeyword
10781083
| PublicKeyword
1084+
| FinalKeyword
10791085
| OverrideKeyword
10801086
| ReadonlyKeyword
10811087
| StaticKeyword
@@ -4901,15 +4907,16 @@ namespace ts {
49014907
ContainsPublic = 1 << 8, // Synthetic property with public constituent(s)
49024908
ContainsProtected = 1 << 9, // Synthetic property with protected constituent(s)
49034909
ContainsPrivate = 1 << 10, // Synthetic property with private constituent(s)
4904-
ContainsStatic = 1 << 11, // Synthetic property with static constituent(s)
4905-
Late = 1 << 12, // Late-bound symbol for a computed property with a dynamic name
4906-
ReverseMapped = 1 << 13, // Property of reverse-inferred homomorphic mapped type
4907-
OptionalParameter = 1 << 14, // Optional parameter
4908-
RestParameter = 1 << 15, // Rest parameter
4909-
DeferredType = 1 << 16, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
4910-
HasNeverType = 1 << 17, // Synthetic property with at least one never type in constituents
4911-
Mapped = 1 << 18, // Property of mapped type
4912-
StripOptional = 1 << 19, // Strip optionality in mapped property
4910+
ContainsFinal = 1 << 11,
4911+
ContainsStatic = 1 << 12, // Synthetic property with static constituent(s)
4912+
Late = 1 << 13, // Late-bound symbol for a computed property with a dynamic name
4913+
ReverseMapped = 1 << 14, // Property of reverse-inferred homomorphic mapped type
4914+
OptionalParameter = 1 << 15, // Optional parameter
4915+
RestParameter = 1 << 16, // Rest parameter
4916+
DeferredType = 1 << 17, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
4917+
HasNeverType = 1 << 18, // Synthetic property with at least one never type in constituents
4918+
Mapped = 1 << 19, // Property of mapped type
4919+
StripOptional = 1 << 20, // Strip optionality in mapped property
49134920
Synthetic = SyntheticProperty | SyntheticMethod,
49144921
Discriminant = HasNonUniformType | HasLiteralType,
49154922
Partial = ReadPartial | WritePartial

src/compiler/utilities.ts

+2
Original file line numberDiff line numberDiff line change
@@ -4858,6 +4858,7 @@ namespace ts {
48584858
case SyntaxKind.PublicKeyword: return ModifierFlags.Public;
48594859
case SyntaxKind.ProtectedKeyword: return ModifierFlags.Protected;
48604860
case SyntaxKind.PrivateKeyword: return ModifierFlags.Private;
4861+
case SyntaxKind.FinalKeyword: return ModifierFlags.Final;
48614862
case SyntaxKind.AbstractKeyword: return ModifierFlags.Abstract;
48624863
case SyntaxKind.ExportKeyword: return ModifierFlags.Export;
48634864
case SyntaxKind.DeclareKeyword: return ModifierFlags.Ambient;
@@ -5396,6 +5397,7 @@ namespace ts {
53965397
const checkFlags = (s as TransientSymbol).checkFlags;
53975398
const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private :
53985399
checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public :
5400+
checkFlags & CheckFlags.ContainsFinal ? ModifierFlags.Final :
53995401
ModifierFlags.Protected;
54005402
const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0;
54015403
return accessModifier | staticModifier;

src/compiler/utilitiesPublic.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,7 @@ namespace ts {
11771177
case SyntaxKind.PublicKeyword:
11781178
case SyntaxKind.PrivateKeyword:
11791179
case SyntaxKind.ProtectedKeyword:
1180+
case SyntaxKind.FinalKeyword:
11801181
case SyntaxKind.ReadonlyKeyword:
11811182
case SyntaxKind.StaticKeyword:
11821183
case SyntaxKind.OverrideKeyword:
@@ -1192,7 +1193,7 @@ namespace ts {
11921193

11931194
/* @internal */
11941195
export function isClassMemberModifier(idToken: SyntaxKind): boolean {
1195-
return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.StaticKeyword || idToken === SyntaxKind.OverrideKeyword;
1196+
return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.FinalKeyword || idToken === SyntaxKind.StaticKeyword || idToken === SyntaxKind.OverrideKeyword;
11961197
}
11971198

11981199
export function isModifier(node: Node): node is Modifier {

src/harness/fourslashInterfaceImpl.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ namespace FourSlashInterface {
11531153
case "private":
11541154
case "protected":
11551155
case "public":
1156+
case "final":
11561157
case "abstract":
11571158
case "any":
11581159
case "boolean":
@@ -1182,7 +1183,7 @@ namespace FourSlashInterface {
11821183
}
11831184

11841185
export const classElementKeywords: readonly ExpectedCompletionEntryObject[] =
1185-
["private", "protected", "public", "static", "abstract", "async", "constructor", "declare", "get", "readonly", "set", "override"].map(keywordEntry);
1186+
["private", "protected", "public", "static", "final", "abstract", "async", "constructor", "declare", "get", "readonly", "set", "override"].map(keywordEntry);
11861187

11871188
export const classElementInJsKeywords = getInJsKeywords(classElementKeywords);
11881189

src/services/completions.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -2080,6 +2080,7 @@ namespace ts.Completions {
20802080
case SyntaxKind.TemplateMiddle:
20812081
return containingNodeKind === SyntaxKind.TemplateSpan; // `aa ${10} dd ${|
20822082

2083+
case SyntaxKind.FinalKeyword:
20832084
case SyntaxKind.PublicKeyword:
20842085
case SyntaxKind.PrivateKeyword:
20852086
case SyntaxKind.ProtectedKeyword:
@@ -2303,6 +2304,9 @@ namespace ts.Completions {
23032304
case "private":
23042305
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Private;
23052306
break;
2307+
case "final":
2308+
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Final;
2309+
break;
23062310
case "static":
23072311
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Static;
23082312
break;
@@ -2316,7 +2320,7 @@ namespace ts.Completions {
23162320
}
23172321

23182322
// No member list for private methods
2319-
if (!(classElementModifierFlags & ModifierFlags.Private)) {
2323+
if (!(classElementModifierFlags & (ModifierFlags.Private | ModifierFlags.Final))) {
23202324
// List of property symbols of base type that are not private and already implemented
23212325
const baseTypeNodes = isClassLike(decl) && classElementModifierFlags & ModifierFlags.Override ? singleElementArray(getEffectiveBaseTypeNode(decl)) : getAllSuperTypeNodes(decl);
23222326
const baseSymbols = flatMap(baseTypeNodes, baseTypeNode => {
@@ -2578,6 +2582,7 @@ namespace ts.Completions {
25782582
case SyntaxKind.InterfaceKeyword:
25792583
case SyntaxKind.LetKeyword:
25802584
case SyntaxKind.PrivateKeyword:
2585+
case SyntaxKind.FinalKeyword:
25812586
case SyntaxKind.ProtectedKeyword:
25822587
case SyntaxKind.PublicKeyword:
25832588
case SyntaxKind.StaticKeyword:
@@ -2978,6 +2983,7 @@ namespace ts.Completions {
29782983
case SyntaxKind.PrivateKeyword:
29792984
case SyntaxKind.ProtectedKeyword:
29802985
case SyntaxKind.PublicKeyword:
2986+
case SyntaxKind.FinalKeyword:
29812987
case SyntaxKind.ReadonlyKeyword:
29822988
case SyntaxKind.StringKeyword:
29832989
case SyntaxKind.SymbolKeyword:

0 commit comments

Comments
 (0)