Skip to content

Commit

Permalink
Merge pull request #2399 from Microsoft/decorators_min
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton committed Mar 25, 2015
2 parents 4f0dc28 + f531193 commit ea15225
Show file tree
Hide file tree
Showing 162 changed files with 6,112 additions and 1,710 deletions.
167 changes: 150 additions & 17 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,39 @@ module ts {
return ~low;
}

export function foldLeft<T>(array: T[], f: (a: T, x: T) => T): T;
export function foldLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
export function foldLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
if (array) {
var count = array.length;
if (count > 0) {
var pos = 0;
var result = arguments.length <= 2 ? array[pos++] : initial;
while (pos < count) {
result = f(<U>result, array[pos++]);
}
return <U>result;
}
}
return initial;
}

export function foldRight<T>(array: T[], f: (a: T, x: T) => T): T;
export function foldRight<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
export function foldRight<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
if (array) {
var pos = array.length - 1;
if (pos >= 0) {
var result = arguments.length <= 2 ? array[pos--] : initial;
while (pos >= 0) {
result = f(<U>result, array[pos--]);
}
return <U>result;
}
}
return initial;
}

let hasOwnProperty = Object.prototype.hasOwnProperty;

export function hasProperty<T>(map: Map<T>, key: string): boolean {
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ module ts {
Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile external modules into amd or commonjs when targeting es6 or higher." },
Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
Decorators_are_not_valid_here: { code: 1206, category: DiagnosticCategory.Error, key: "Decorators are not valid here." },
Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
Expand Down
12 changes: 12 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,18 @@
"category": "Error",
"code": 1204
},
"Decorators are only available when targeting ECMAScript 5 and higher.": {
"category": "Error",
"code": 1205
},
"Decorators are not valid here.": {
"category": "Error",
"code": 1206
},
"Decorators cannot be applied to multiple get/set accessors of the same name.": {
"category": "Error",
"code": 1207
},

"Duplicate identifier '{0}'.": {
"category": "Error",
Expand Down
435 changes: 414 additions & 21 deletions src/compiler/emitter.ts

Large diffs are not rendered by default.

327 changes: 241 additions & 86 deletions src/compiler/parser.ts

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ module ts {
"&=": SyntaxKind.AmpersandEqualsToken,
"|=": SyntaxKind.BarEqualsToken,
"^=": SyntaxKind.CaretEqualsToken,
"@": SyntaxKind.AtToken,
};

/*
Expand Down Expand Up @@ -1284,6 +1285,8 @@ module ts {
return pos++, token = SyntaxKind.CloseBraceToken;
case CharacterCodes.tilde:
return pos++, token = SyntaxKind.TildeToken;
case CharacterCodes.at:
return pos++, token = SyntaxKind.AtToken;
case CharacterCodes.backslash:
let cookedChar = peekUnicodeEscape();
if (cookedChar >= 0 && isIdentifierStart(cookedChar)) {
Expand Down
60 changes: 40 additions & 20 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ module ts {
BarBarToken,
QuestionToken,
ColonToken,
AtToken,
// Assignments
EqualsToken,
PlusEqualsToken,
Expand Down Expand Up @@ -154,6 +155,7 @@ module ts {
// Signature elements
TypeParameter,
Parameter,
Decorator,
// TypeMember
PropertySignature,
PropertyDeclaration,
Expand Down Expand Up @@ -244,6 +246,7 @@ module ts {
ExportDeclaration,
NamedExports,
ExportSpecifier,
MissingDeclaration,

// Module references
ExternalModuleReference,
Expand Down Expand Up @@ -327,22 +330,25 @@ module ts {
// If this node was parsed in the parameters of a generator.
GeneratorParameter = 1 << 3,

// If this node was parsed as part of a decorator
Decorator = 1 << 4,

// If the parser encountered an error when parsing the code that created this node. Note
// the parser only sets this directly on the node it creates right after encountering the
// error.
ThisNodeHasError = 1 << 4,
ThisNodeHasError = 1 << 5,

// Context flags set directly by the parser.
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | ThisNodeHasError,
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,

// Context flags computed by aggregating child flags upwards.

// Used during incremental parsing to determine if this node or any of its children had an
// error. Computed only once and then cached.
ThisNodeOrAnySubNodesHasError = 1 << 5,
ThisNodeOrAnySubNodesHasError = 1 << 6,

// Used to know if we've computed data from children and cached it in this node.
HasAggregatedChildData = 1 << 6
HasAggregatedChildData = 1 << 7
}

export const enum RelationComparisonResult {
Expand All @@ -357,13 +363,14 @@ module ts {
// Specific context the parser was in when this node was created. Normally undefined.
// Only set when the parser was in some interesting context (like async/yield).
parserContextFlags?: ParserContextFlags;
modifiers?: ModifiersArray; // Array of modifiers
id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
symbol?: Symbol; // Symbol declared by node (initialized by binding)
locals?: SymbolTable; // Locals associated with node (initialized by binding)
nextContainer?: Node; // Next container in declaration order (initialized by binding)
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
modifiers?: ModifiersArray; // Array of modifiers
id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
symbol?: Symbol; // Symbol declared by node (initialized by binding)
locals?: SymbolTable; // Locals associated with node (initialized by binding)
nextContainer?: Node; // Next container in declaration order (initialized by binding)
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
}

export interface NodeArray<T> extends Array<T>, TextRange {
Expand Down Expand Up @@ -397,6 +404,10 @@ module ts {
expression: Expression;
}

export interface Decorator extends Node {
expression: LeftHandSideExpression;
}

export interface TypeParameterDeclaration extends Declaration {
name: Identifier;
constraint?: TypeNode;
Expand Down Expand Up @@ -531,6 +542,14 @@ module ts {
body: Block;
}

// A merged view of get/set accessors
export interface MergedAccessorDeclarations {
getAccessor: AccessorDeclaration;
setAccessor: AccessorDeclaration;
firstAccessor: AccessorDeclaration;
secondAccessor: AccessorDeclaration;
}

export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement {
_indexSignatureDeclarationBrand: any;
}
Expand Down Expand Up @@ -1337,17 +1356,18 @@ module ts {
}

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

// Values for enum members have been computed, and any errors have been reported for them.
EnumValuesComputed = 0x00000080,
BlockScopedBindingInLoop = 0x00000100,
EnumValuesComputed = 0x00000080,
BlockScopedBindingInLoop = 0x00000100,
EmitDecorate = 0x00000200, // Emit __decorate
}

export interface NodeLinks {
Expand Down
143 changes: 142 additions & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="types.ts" />
/// <reference path="binder.ts" />

module ts {
export interface ReferencePathMatchResult {
Expand Down Expand Up @@ -575,6 +575,133 @@ module ts {
return (<CallExpression>node).expression;
}

export function mergeAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration): MergedAccessorDeclarations {
let firstAccessor: AccessorDeclaration;
let secondAccessor: AccessorDeclaration;
let getAccessor: AccessorDeclaration;
let setAccessor: AccessorDeclaration;
if (hasDynamicName(accessor)) {
firstAccessor = accessor;
if (accessor.kind === SyntaxKind.GetAccessor) {
getAccessor = accessor;
}
else if (accessor.kind === SyntaxKind.SetAccessor) {
setAccessor = accessor;
}
else {
Debug.fail("Accessor has wrong kind");
}
}
else {
forEach(declarations, (member: Declaration) => {
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
&& (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
let memberName = getPropertyNameForPropertyNameNode(member.name);
let accessorName = getPropertyNameForPropertyNameNode(accessor.name);
if (memberName === accessorName) {
if (!firstAccessor) {
firstAccessor = <AccessorDeclaration>member;
}
else if (!secondAccessor) {
secondAccessor = <AccessorDeclaration>member;
}

if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
getAccessor = <AccessorDeclaration>member;
}

if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
setAccessor = <AccessorDeclaration>member;
}
}
}
});
}
return {
firstAccessor,
secondAccessor,
getAccessor,
setAccessor
};
}

export function nodeCanBeDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
// classes are valid targets
return true;

case SyntaxKind.PropertyDeclaration:
// property declarations are valid if their parent is a class declaration.
return node.parent.kind === SyntaxKind.ClassDeclaration;

case SyntaxKind.Parameter:
// if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target;
return (<FunctionLikeDeclaration>node.parent).body && node.parent.parent.kind === SyntaxKind.ClassDeclaration;

case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration:
// if this method has a body and its parent is a class declaration, this is a valid target.
return (<FunctionLikeDeclaration>node).body && node.parent.kind === SyntaxKind.ClassDeclaration;
}

return false;
}

export function nodeIsDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
if (node.decorators) {
return true;
}

return false;

case SyntaxKind.PropertyDeclaration:
case SyntaxKind.Parameter:
if (node.decorators) {
return true;
}

return false;

case SyntaxKind.GetAccessor:
if ((<FunctionLikeDeclaration>node).body && node.decorators) {
return true;
}

return false;

case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
if ((<FunctionLikeDeclaration>node).body && node.decorators) {
return true;
}

return false;
}

return false;
}

export function childIsDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);

case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
}

return false;
}

export function nodeOrChildIsDecorated(node: Node): boolean {
return nodeIsDecorated(node) || childIsDecorated(node);
}

export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
Expand Down Expand Up @@ -814,6 +941,20 @@ module ts {
}
}

export function isClassElement(n: Node): boolean {
switch (n.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.IndexSignature:
return true;
default:
return false;
}
}

// True if the given identifier, string literal, or number literal is the name of a declaration node
export function isDeclarationName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
Expand Down
14 changes: 14 additions & 0 deletions src/lib/core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1155,3 +1155,17 @@ interface ArrayConstructor {
}

declare var Array: ArrayConstructor;

interface TypedPropertyDescriptor<T> {
enumerable?: boolean;
configurable?: boolean;
writable?: boolean;
value?: T;
get?: () => T;
set?: (value: T) => void;
}

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Function, propertyKey: string | symbol, parameterIndex: number) => void;
Loading

0 comments on commit ea15225

Please sign in to comment.