Skip to content

Commit 39001f5

Browse files
committed
Checker updates for decorators
1 parent 8282a0b commit 39001f5

File tree

3 files changed

+187
-25
lines changed

3 files changed

+187
-25
lines changed

src/compiler/checker.ts

+162-16
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,18 @@ module ts {
100100
let globalIterableType: ObjectType;
101101

102102
let anyArrayType: Type;
103+
let globalTypedPropertyDescriptorType: ObjectType;
104+
let globalClassDecoratorType: ObjectType;
105+
let globalClassAnnotationType: ObjectType;
106+
let globalParameterAnnotationType: ObjectType;
107+
let globalPropertyAnnotationType: ObjectType;
108+
let globalPropertyDecoratorType: ObjectType;
103109

104110
let tupleTypes: Map<TupleType> = {};
105111
let unionTypes: Map<UnionType> = {};
106112
let stringLiteralTypes: Map<StringLiteralType> = {};
107113
let emitExtends = false;
114+
let emitDecorate = false;
108115

109116
let mergedSymbols: Symbol[] = [];
110117
let symbolLinks: SymbolLinks[] = [];
@@ -311,6 +318,7 @@ module ts {
311318
let lastLocation: Node;
312319
let propertyWithInvalidInitializer: Node;
313320
let errorLocation = location;
321+
let grandparent: Node;
314322

315323
loop: while (location) {
316324
// Locals of a source file are not in scope (because they get merged into the global symbol table)
@@ -376,7 +384,7 @@ module ts {
376384
// }
377385
//
378386
case SyntaxKind.ComputedPropertyName:
379-
let grandparent = location.parent.parent;
387+
grandparent = location.parent.parent;
380388
if (grandparent.kind === SyntaxKind.ClassDeclaration || grandparent.kind === SyntaxKind.InterfaceDeclaration) {
381389
// A reference to this grandparent's type parameters would be an error
382390
if (result = getSymbol(getSymbolOfNode(grandparent).members, name, meaning & SymbolFlags.Type)) {
@@ -408,6 +416,26 @@ module ts {
408416
break loop;
409417
}
410418
break;
419+
case SyntaxKind.Decorator:
420+
if (location.parent) {
421+
lastLocation = location;
422+
grandparent = location.parent.parent;
423+
if (location.parent.kind === SyntaxKind.Parameter) {
424+
// Parameter decorators are resolved in the context of their great-grandparent
425+
if (grandparent) {
426+
location = grandparent.parent;
427+
}
428+
else {
429+
break loop;
430+
}
431+
}
432+
else {
433+
// all other decorators are resolved in the context of their grandparent
434+
location = grandparent;
435+
}
436+
continue;
437+
}
438+
break;
411439
}
412440
lastLocation = location;
413441
location = location.parent;
@@ -7852,7 +7880,7 @@ module ts {
78527880
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
78537881

78547882
// Grammar checking
7855-
checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
7883+
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
78567884

78577885
checkVariableLikeDeclaration(node);
78587886
let func = getContainingFunction(node);
@@ -7954,7 +7982,7 @@ module ts {
79547982

79557983
function checkPropertyDeclaration(node: PropertyDeclaration) {
79567984
// Grammar checking
7957-
checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
7985+
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
79587986

79597987
checkVariableLikeDeclaration(node);
79607988
}
@@ -8093,6 +8121,10 @@ module ts {
80938121
checkFunctionLikeDeclaration(node);
80948122
}
80958123

8124+
function checkIncompleteDeclaration(node: Declaration) {
8125+
error(node, Diagnostics.Declaration_expected);
8126+
}
8127+
80968128
function checkTypeReference(node: TypeReferenceNode) {
80978129
// Grammar checking
80988130
checkGrammarTypeArguments(node, node.typeArguments);
@@ -8484,6 +8516,70 @@ module ts {
84848516
}
84858517
}
84868518

8519+
function checkDecoratorSignature(node: Decorator, exprType: Type, expectedAnnotationType: Type, parentType?: Type, expectedDecoratorType?: Type, message?: DiagnosticMessage) {
8520+
if (checkTypeAssignableTo(exprType, expectedAnnotationType, node) && expectedDecoratorType) {
8521+
let signature = getSingleCallSignature(expectedDecoratorType);
8522+
if (!signature) {
8523+
// if we couldn't get the signature of the decorator function type, it is likely because we are using an out-of-date lib.d.ts
8524+
// and we have already reported an error in initializeTypeChecker.
8525+
return;
8526+
}
8527+
8528+
let instantiatedSignature = getSignatureInstantiation(signature, [parentType]);
8529+
let instantiatedSignatureType = getOrCreateTypeFromSignature(instantiatedSignature);
8530+
checkTypeAssignableTo(exprType, instantiatedSignatureType, node, message);
8531+
}
8532+
}
8533+
8534+
/** Check a decorator */
8535+
function checkDecorator(node: Decorator): void {
8536+
let expression: Expression = node.expression;
8537+
let exprType = checkExpression(expression);
8538+
8539+
switch (node.parent.kind) {
8540+
case SyntaxKind.ClassDeclaration:
8541+
let classSymbol = getSymbolOfNode(node.parent);
8542+
let classType = getTypeOfSymbol(classSymbol);
8543+
checkDecoratorSignature(node, exprType, globalClassAnnotationType, classType, globalClassDecoratorType, Diagnostics.Decorators_may_not_change_the_type_of_a_class);
8544+
break;
8545+
8546+
case SyntaxKind.PropertyDeclaration:
8547+
case SyntaxKind.MethodDeclaration:
8548+
case SyntaxKind.GetAccessor:
8549+
case SyntaxKind.SetAccessor:
8550+
let propertyType = getTypeOfNode(node.parent);
8551+
checkDecoratorSignature(node, exprType, globalPropertyAnnotationType, propertyType, globalPropertyDecoratorType, Diagnostics.Decorators_may_not_change_the_type_of_a_member);
8552+
break;
8553+
8554+
case SyntaxKind.Parameter:
8555+
checkDecoratorSignature(node, exprType, globalParameterAnnotationType);
8556+
break;
8557+
}
8558+
}
8559+
8560+
/** Check the decorators of a node */
8561+
function checkDecorators(node: Node): void {
8562+
if (!node.decorators) {
8563+
return;
8564+
}
8565+
8566+
switch (node.kind) {
8567+
case SyntaxKind.ClassDeclaration:
8568+
case SyntaxKind.MethodDeclaration:
8569+
case SyntaxKind.GetAccessor:
8570+
case SyntaxKind.SetAccessor:
8571+
case SyntaxKind.PropertyDeclaration:
8572+
case SyntaxKind.Parameter:
8573+
emitDecorate = true;
8574+
break;
8575+
8576+
default:
8577+
return;
8578+
}
8579+
8580+
forEach(node.decorators, checkDecorator);
8581+
}
8582+
84878583
function checkFunctionDeclaration(node: FunctionDeclaration): void {
84888584
if (produceDiagnostics) {
84898585
checkFunctionLikeDeclaration(node) ||
@@ -8498,6 +8594,7 @@ module ts {
84988594
}
84998595

85008596
function checkFunctionLikeDeclaration(node: FunctionLikeDeclaration): void {
8597+
checkDecorators(node);
85018598
checkSignatureDeclaration(node);
85028599

85038600
// Do not use hasDynamicName here, because that returns false for well known symbols.
@@ -8780,6 +8877,7 @@ module ts {
87808877

87818878
// Check variable, parameter, or property declaration
87828879
function checkVariableLikeDeclaration(node: VariableLikeDeclaration) {
8880+
checkDecorators(node);
87838881
checkSourceElement(node.type);
87848882
// For a computed property, just check the initializer and exit
87858883
// Do not use hasDynamicName here, because that returns false for well known symbols.
@@ -8852,7 +8950,7 @@ module ts {
88528950

88538951
function checkVariableStatement(node: VariableStatement) {
88548952
// Grammar checking
8855-
checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
8953+
checkGrammarDecorators(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
88568954

88578955
forEach(node.declarationList.declarations, checkSourceElement);
88588956
}
@@ -9483,7 +9581,7 @@ module ts {
94839581
function checkClassDeclaration(node: ClassDeclaration) {
94849582
// Grammar checking
94859583
checkGrammarClassDeclarationHeritageClauses(node);
9486-
9584+
checkDecorators(node);
94879585
if (node.name) {
94889586
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
94899587
checkCollisionWithCapturedThisVariable(node, node.name);
@@ -9688,7 +9786,7 @@ module ts {
96889786

96899787
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
96909788
// Grammar checking
9691-
checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
9789+
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
96929790

96939791
checkTypeParameters(node.typeParameters);
96949792
if (produceDiagnostics) {
@@ -9725,7 +9823,7 @@ module ts {
97259823

97269824
function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
97279825
// Grammar checking
9728-
checkGrammarModifiers(node);
9826+
checkGrammarDecorators(node) || checkGrammarModifiers(node);
97299827

97309828
checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0);
97319829
checkSourceElement(node.type);
@@ -9894,7 +9992,7 @@ module ts {
98949992
}
98959993

98969994
// Grammar checking
9897-
checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
9995+
checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
98989996

98999997
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
99009998
checkCollisionWithCapturedThisVariable(node, node.name);
@@ -9960,7 +10058,7 @@ module ts {
996010058
function checkModuleDeclaration(node: ModuleDeclaration) {
996110059
if (produceDiagnostics) {
996210060
// Grammar checking
9963-
if (!checkGrammarModifiers(node)) {
10061+
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node)) {
996410062
if (!isInAmbientContext(node) && node.name.kind === SyntaxKind.StringLiteral) {
996510063
grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
996610064
}
@@ -10055,7 +10153,7 @@ module ts {
1005510153
}
1005610154

1005710155
function checkImportDeclaration(node: ImportDeclaration) {
10058-
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
10156+
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
1005910157
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
1006010158
}
1006110159
if (checkExternalImportOrExportDeclaration(node)) {
@@ -10077,7 +10175,7 @@ module ts {
1007710175
}
1007810176

1007910177
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
10080-
checkGrammarModifiers(node);
10178+
checkGrammarDecorators(node) || checkGrammarModifiers(node);
1008110179
if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
1008210180
checkImportBinding(node);
1008310181
if (node.flags & NodeFlags.Export) {
@@ -10108,7 +10206,7 @@ module ts {
1010810206
}
1010910207

1011010208
function checkExportDeclaration(node: ExportDeclaration) {
10111-
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
10209+
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
1011210210
grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers);
1011310211
}
1011410212
if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
@@ -10132,7 +10230,7 @@ module ts {
1013210230
return;
1013310231
}
1013410232
// Grammar checking
10135-
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
10233+
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
1013610234
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
1013710235
}
1013810236
if (node.expression) {
@@ -10232,6 +10330,8 @@ module ts {
1023210330
case SyntaxKind.GetAccessor:
1023310331
case SyntaxKind.SetAccessor:
1023410332
return checkAccessorDeclaration(<AccessorDeclaration>node);
10333+
case SyntaxKind.IncompleteDeclaration:
10334+
return checkIncompleteDeclaration(<Declaration>node);
1023510335
case SyntaxKind.TypeReference:
1023610336
return checkTypeReference(<TypeReferenceNode>node);
1023710337
case SyntaxKind.TypeQuery:
@@ -10436,6 +10536,10 @@ module ts {
1043610536
links.flags |= NodeCheckFlags.EmitExtends;
1043710537
}
1043810538

10539+
if (emitDecorate) {
10540+
links.flags |= NodeCheckFlags.EmitDecorate;
10541+
}
10542+
1043910543
links.flags |= NodeCheckFlags.TypeChecked;
1044010544
}
1044110545
}
@@ -11235,6 +11339,12 @@ module ts {
1123511339
globalNumberType = getGlobalType("Number");
1123611340
globalBooleanType = getGlobalType("Boolean");
1123711341
globalRegExpType = getGlobalType("RegExp");
11342+
globalTypedPropertyDescriptorType = getTypeOfGlobalSymbol(getGlobalTypeSymbol("TypedPropertyDescriptor"), 1);
11343+
globalClassDecoratorType = getGlobalType("ClassDecorator");
11344+
globalPropertyDecoratorType = getGlobalType("PropertyDecorator");
11345+
globalClassAnnotationType = getGlobalType("ClassAnnotation");
11346+
globalPropertyAnnotationType = getGlobalType("PropertyAnnotation");
11347+
globalParameterAnnotationType = getGlobalType("ParameterAnnotation");
1123811348

1123911349
// If we're in ES6 mode, load the TemplateStringsArray.
1124011350
// Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
@@ -11259,6 +11369,42 @@ module ts {
1125911369

1126011370

1126111371
// GRAMMAR CHECKING
11372+
function checkGrammarDecorators(node: Node): boolean {
11373+
if (!node.decorators) {
11374+
return false;
11375+
}
11376+
11377+
let target = node;
11378+
while (target) {
11379+
switch (target.kind) {
11380+
case SyntaxKind.ClassDeclaration:
11381+
return false;
11382+
11383+
case SyntaxKind.Constructor:
11384+
if (node.kind !== SyntaxKind.Parameter) {
11385+
break;
11386+
}
11387+
11388+
case SyntaxKind.PropertyDeclaration:
11389+
case SyntaxKind.Parameter:
11390+
target = target.parent;
11391+
continue;
11392+
11393+
11394+
case SyntaxKind.MethodDeclaration:
11395+
case SyntaxKind.GetAccessor:
11396+
case SyntaxKind.SetAccessor:
11397+
if ((<FunctionLikeDeclaration>target).body) {
11398+
target = target.parent;
11399+
continue;
11400+
}
11401+
break;
11402+
}
11403+
break;
11404+
}
11405+
return grammarErrorOnNode(node, Diagnostics.Decorators_are_not_valid_on_this_declaration_type);
11406+
}
11407+
1126211408
function checkGrammarModifiers(node: Node): boolean {
1126311409
switch (node.kind) {
1126411410
case SyntaxKind.GetAccessor:
@@ -11455,7 +11601,7 @@ module ts {
1145511601
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
1145611602
// Prevent cascading error by short-circuit
1145711603
let file = getSourceFileOfNode(node);
11458-
return checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
11604+
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
1145911605
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
1146011606
}
1146111607

@@ -11512,7 +11658,7 @@ module ts {
1151211658

1151311659
function checkGrammarIndexSignature(node: SignatureDeclaration) {
1151411660
// Prevent cascading error by short-circuit
11515-
checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
11661+
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
1151611662
}
1151711663

1151811664
function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray<TypeNode>): boolean {
@@ -11561,7 +11707,7 @@ module ts {
1156111707
let seenExtendsClause = false;
1156211708
let seenImplementsClause = false;
1156311709

11564-
if (!checkGrammarModifiers(node) && node.heritageClauses) {
11710+
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) {
1156511711
for (let heritageClause of node.heritageClauses) {
1156611712
if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
1156711713
if (seenExtendsClause) {

src/compiler/types.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1346,17 +1346,18 @@ module ts {
13461346
}
13471347

13481348
export const enum NodeCheckFlags {
1349-
TypeChecked = 0x00000001, // Node has been type checked
1350-
LexicalThis = 0x00000002, // Lexical 'this' reference
1351-
CaptureThis = 0x00000004, // Lexical 'this' used in body
1352-
EmitExtends = 0x00000008, // Emit __extends
1353-
SuperInstance = 0x00000010, // Instance 'super' reference
1354-
SuperStatic = 0x00000020, // Static 'super' reference
1355-
ContextChecked = 0x00000040, // Contextual types have been assigned
1349+
TypeChecked = 0x00000001, // Node has been type checked
1350+
LexicalThis = 0x00000002, // Lexical 'this' reference
1351+
CaptureThis = 0x00000004, // Lexical 'this' used in body
1352+
EmitExtends = 0x00000008, // Emit __extends
1353+
SuperInstance = 0x00000010, // Instance 'super' reference
1354+
SuperStatic = 0x00000020, // Static 'super' reference
1355+
ContextChecked = 0x00000040, // Contextual types have been assigned
13561356

13571357
// Values for enum members have been computed, and any errors have been reported for them.
1358-
EnumValuesComputed = 0x00000080,
1359-
BlockScopedBindingInLoop = 0x00000100,
1358+
EnumValuesComputed = 0x00000080,
1359+
BlockScopedBindingInLoop = 0x00000100,
1360+
EmitDecorate = 0x00000200, // Emit __decorate
13601361
}
13611362

13621363
export interface NodeLinks {

0 commit comments

Comments
 (0)