Skip to content

Commit

Permalink
feat(1534): add sealed keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
a-tarasyuk committed Jul 9, 2022
1 parent 1622247 commit bf06da6
Show file tree
Hide file tree
Showing 57 changed files with 1,106 additions and 527 deletions.
26 changes: 25 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12439,6 +12439,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
checkFlags |= (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
(modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
(modifiers & ModifierFlags.Sealed ? CheckFlags.ContainsSealed : 0) |
(modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
if (!isPrototypeProperty(prop)) {
syntheticFlag = CheckFlags.SyntheticProperty;
Expand Down Expand Up @@ -20149,6 +20150,13 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
return Ternary.False;
}
}
else if (targetPropFlags & ModifierFlags.Sealed) {
if (reportErrors) {
reportError(Diagnostics.Property_0_is_sealed_in_type_1_that_cannot_be_overridden_in_type_2, symbolToString(targetProp),
typeToString(target), typeToString(source));
}
return Ternary.False;
}
else if (targetPropFlags & ModifierFlags.Protected) {
if (!isValidOverrideOf(sourceProp, targetProp)) {
if (reportErrors) {
Expand Down Expand Up @@ -43857,7 +43865,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
return quickResult;
}

let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined;
let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined, lastSealed: Node | undefined;
let flags = ModifierFlags.None;
for (const modifier of node.modifiers!) {
if (isDecorator(modifier)) continue;
Expand Down Expand Up @@ -44004,6 +44012,19 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")

flags |= ModifierFlags.Default;
break;
case SyntaxKind.SealedKeyword:
if (flags & ModifierFlags.Sealed) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "sealed");
}
if (flags & ModifierFlags.Private) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "sealed", "private");
}
if (flags & ModifierFlags.Abstract) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "sealed", "abstract");
}
flags |= ModifierFlags.Sealed;
lastSealed = modifier;
break;
case SyntaxKind.DeclareKeyword:
if (flags & ModifierFlags.Ambient) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
Expand Down Expand Up @@ -44110,6 +44131,9 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
}
if (flags & ModifierFlags.Sealed) {
return grammarErrorOnNode(lastSealed!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "sealed");
}
return false;
}
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3511,6 +3511,10 @@
"category": "Error",
"code": 2844
},
"Property '{0}' is sealed in type '{1}' that cannot be overridden in type '{2}'.": {
"category": "Error",
"code": 2845
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ namespace ts {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.AbstractKeyword:
case SyntaxKind.DeclareKeyword:
Expand Down Expand Up @@ -1055,6 +1056,7 @@ namespace ts {
if (flags & ModifierFlags.Public) result.push(createModifier(SyntaxKind.PublicKeyword));
if (flags & ModifierFlags.Private) result.push(createModifier(SyntaxKind.PrivateKeyword));
if (flags & ModifierFlags.Protected) result.push(createModifier(SyntaxKind.ProtectedKeyword));
if (flags & ModifierFlags.Sealed) result.push(createModifier(SyntaxKind.SealedKeyword));
if (flags & ModifierFlags.Abstract) result.push(createModifier(SyntaxKind.AbstractKeyword));
if (flags & ModifierFlags.Static) result.push(createModifier(SyntaxKind.StaticKeyword));
if (flags & ModifierFlags.Override) result.push(createModifier(SyntaxKind.OverrideKeyword));
Expand Down
1 change: 1 addition & 0 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2433,6 +2433,7 @@ namespace ts {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.AbstractKeyword:
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ namespace ts {
private: SyntaxKind.PrivateKeyword,
protected: SyntaxKind.ProtectedKeyword,
public: SyntaxKind.PublicKeyword,
sealed: SyntaxKind.SealedKeyword,
override: SyntaxKind.OverrideKeyword,
out: SyntaxKind.OutKeyword,
readonly: SyntaxKind.ReadonlyKeyword,
Expand Down
1 change: 1 addition & 0 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ namespace ts {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.AbstractKeyword:
case SyntaxKind.OverrideKeyword:
case SyntaxKind.ConstKeyword:
Expand Down
36 changes: 22 additions & 14 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ namespace ts {
ProtectedKeyword,
PublicKeyword,
StaticKeyword,
SealedKeyword,
YieldKeyword,
// Contextual keywords
AbstractKeyword,
Expand Down Expand Up @@ -602,6 +603,7 @@ namespace ts {
| SyntaxKind.PrivateKeyword
| SyntaxKind.ProtectedKeyword
| SyntaxKind.PublicKeyword
| SyntaxKind.SealedKeyword
| SyntaxKind.ReadonlyKeyword
| SyntaxKind.OutKeyword
| SyntaxKind.OverrideKeyword
Expand Down Expand Up @@ -640,6 +642,7 @@ namespace ts {
| SyntaxKind.PrivateKeyword
| SyntaxKind.ProtectedKeyword
| SyntaxKind.PublicKeyword
| SyntaxKind.SealedKeyword
| SyntaxKind.ReadonlyKeyword
| SyntaxKind.OutKeyword
| SyntaxKind.OverrideKeyword
Expand Down Expand Up @@ -814,9 +817,10 @@ namespace ts {
Protected = 1 << 4, // Property/Method
Static = 1 << 5, // Property/Method
Readonly = 1 << 6, // Property/Method
Abstract = 1 << 7, // Class/Method/ConstructSignature
Async = 1 << 8, // Property/Method/Function
Default = 1 << 9, // Function/Class (export default declaration)
Sealed = 1 << 7, // Property/Method
Abstract = 1 << 8, // Class/Method/ConstructSignature
Async = 1 << 9, // Property/Method/Function
Default = 1 << 10, // Function/Class (export default declaration)
Const = 1 << 11, // Const enum
HasComputedJSDocModifiers = 1 << 12, // Indicates the computed modifier flags include modifiers from JSDoc.

Expand All @@ -832,9 +836,9 @@ namespace ts {
ParameterPropertyModifier = AccessibilityModifier | Readonly | Override,
NonPublicAccessibilityModifier = Private | Protected,

TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override | In | Out,
TypeScriptModifier = Ambient | Public | Private | Protected | Sealed | Readonly | Abstract | Const | Override | In | Out,
ExportDefault = Export | Default,
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Async | Default | Const | Deprecated | Override | In | Out | Decorator,
All = Export | Ambient | Public | Private | Protected | Sealed | Static | Readonly | Abstract | Async | Default | Const | Deprecated | Override | In | Out | Decorator,
Modifier = All & ~Decorator
}

Expand Down Expand Up @@ -1149,6 +1153,7 @@ namespace ts {
export type PrivateKeyword = ModifierToken<SyntaxKind.PrivateKeyword>;
export type ProtectedKeyword = ModifierToken<SyntaxKind.ProtectedKeyword>;
export type PublicKeyword = ModifierToken<SyntaxKind.PublicKeyword>;
export type SealedKeyword = ModifierToken<SyntaxKind.SealedKeyword>;
export type ReadonlyKeyword = ModifierToken<SyntaxKind.ReadonlyKeyword>;
export type OutKeyword = ModifierToken<SyntaxKind.OutKeyword>;
export type OverrideKeyword = ModifierToken<SyntaxKind.OverrideKeyword>;
Expand All @@ -1169,6 +1174,7 @@ namespace ts {
| ProtectedKeyword
| PublicKeyword
| OutKeyword
| SealedKeyword
| OverrideKeyword
| ReadonlyKeyword
| StaticKeyword
Expand Down Expand Up @@ -5199,15 +5205,17 @@ namespace ts {
ContainsProtected = 1 << 9, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 10, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 11, // Synthetic property with static constituent(s)
Late = 1 << 12, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 13, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 14, // Optional parameter
RestParameter = 1 << 15, // Rest parameter
DeferredType = 1 << 16, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
HasNeverType = 1 << 17, // Synthetic property with at least one never type in constituents
Mapped = 1 << 18, // Property of mapped type
StripOptional = 1 << 19, // Strip optionality in mapped property
Unresolved = 1 << 20, // Unresolved type alias symbol
ContainsSealed = 1 << 12,

Late = 1 << 13, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 14, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 15, // Optional parameter
RestParameter = 1 << 16, // Rest parameter
DeferredType = 1 << 17, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
HasNeverType = 1 << 18, // Synthetic property with at least one never type in constituents
Mapped = 1 << 19, // Property of mapped type
StripOptional = 1 << 20, // Strip optionality in mapped property
Unresolved = 1 << 21, // Unresolved type alias symbol
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType,
Partial = ReadPartial | WritePartial
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5025,6 +5025,7 @@ namespace ts {
case SyntaxKind.PublicKeyword: return ModifierFlags.Public;
case SyntaxKind.ProtectedKeyword: return ModifierFlags.Protected;
case SyntaxKind.PrivateKeyword: return ModifierFlags.Private;
case SyntaxKind.SealedKeyword: return ModifierFlags.Sealed;
case SyntaxKind.AbstractKeyword: return ModifierFlags.Abstract;
case SyntaxKind.ExportKeyword: return ModifierFlags.Export;
case SyntaxKind.DeclareKeyword: return ModifierFlags.Ambient;
Expand Down Expand Up @@ -5574,6 +5575,7 @@ namespace ts {
const checkFlags = (s as TransientSymbol).checkFlags;
const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private :
checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public :
checkFlags & CheckFlags.ContainsSealed ? ModifierFlags.Sealed :
ModifierFlags.Protected;
const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0;
return accessModifier | staticModifier;
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,7 @@ namespace ts {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.OutKeyword:
Expand All @@ -1235,7 +1236,7 @@ namespace ts {

/* @internal */
export function isClassMemberModifier(idToken: SyntaxKind): boolean {
return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.StaticKeyword || idToken === SyntaxKind.OverrideKeyword;
return isParameterPropertyModifier(idToken) || idToken === SyntaxKind.SealedKeyword || idToken === SyntaxKind.StaticKeyword || idToken === SyntaxKind.OverrideKeyword;
}

export function isModifier(node: Node): node is Modifier {
Expand Down
2 changes: 2 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ namespace FourSlashInterface {
case "private":
case "protected":
case "public":
case "sealed":
case "abstract":
case "any":
case "boolean":
Expand Down Expand Up @@ -1276,6 +1277,7 @@ namespace FourSlashInterface {
"protected",
"public",
"readonly",
"sealed",
"set",
"static",
].map(keywordEntry);
Expand Down
7 changes: 6 additions & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3225,6 +3225,9 @@ namespace ts.Completions {
case "private":
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Private;
break;
case "sealed":
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Sealed;
break;
case "static":
classElementModifierFlags = classElementModifierFlags | ModifierFlags.Static;
break;
Expand All @@ -3238,7 +3241,7 @@ namespace ts.Completions {
}

// No member list for private methods
if (!(classElementModifierFlags & ModifierFlags.Private)) {
if (!(classElementModifierFlags & (ModifierFlags.Private | ModifierFlags.Sealed))) {
// List of property symbols of base type that are not private and already implemented
const baseTypeNodes = isClassLike(decl) && classElementModifierFlags & ModifierFlags.Override ? singleElementArray(getEffectiveBaseTypeNode(decl)) : getAllSuperTypeNodes(decl);
const baseSymbols = flatMap(baseTypeNodes, baseTypeNode => {
Expand Down Expand Up @@ -3488,6 +3491,7 @@ namespace ts.Completions {
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.StaticKeyword:
Expand Down Expand Up @@ -3925,6 +3929,7 @@ namespace ts.Completions {
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.SealedKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.SymbolKeyword:
Expand Down
Loading

0 comments on commit bf06da6

Please sign in to comment.