repackaging: all the file moves
This commit is contained in:
1
modules/@angular/core/src/util/decorators.dart
Normal file
1
modules/@angular/core/src/util/decorators.dart
Normal file
@ -0,0 +1 @@
|
||||
library angular2.core.util.decorators;
|
329
modules/@angular/core/src/util/decorators.ts
Normal file
329
modules/@angular/core/src/util/decorators.ts
Normal file
@ -0,0 +1,329 @@
|
||||
import {ConcreteType, global, Type, isFunction, stringify} from 'angular2/src/facade/lang';
|
||||
|
||||
var _nextClassId = 0;
|
||||
|
||||
/**
|
||||
* Declares the interface to be used with {@link Class}.
|
||||
*/
|
||||
export interface ClassDefinition {
|
||||
/**
|
||||
* Optional argument for specifying the superclass.
|
||||
*/
|
||||
extends?: Type;
|
||||
|
||||
/**
|
||||
* Required constructor function for a class.
|
||||
*
|
||||
* The function may be optionally wrapped in an `Array`, in which case additional parameter
|
||||
* annotations may be specified.
|
||||
* The number of arguments and the number of parameter annotations must match.
|
||||
*
|
||||
* See {@link Class} for example of usage.
|
||||
*/
|
||||
constructor: Function | any[];
|
||||
|
||||
/**
|
||||
* Other methods on the class. Note that values should have type 'Function' but TS requires
|
||||
* all properties to have a narrower type than the index signature.
|
||||
*/
|
||||
[x: string]: Type | Function | any[];
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface implemented by all Angular type decorators, which allows them to be used as ES7
|
||||
* decorators as well as
|
||||
* Angular DSL syntax.
|
||||
*
|
||||
* DSL syntax:
|
||||
*
|
||||
* ```
|
||||
* var MyClass = ng
|
||||
* .Component({...})
|
||||
* .View({...})
|
||||
* .Class({...});
|
||||
* ```
|
||||
*
|
||||
* ES7 syntax:
|
||||
*
|
||||
* ```
|
||||
* @ng.Component({...})
|
||||
* @ng.View({...})
|
||||
* class MyClass {...}
|
||||
* ```
|
||||
*/
|
||||
export interface TypeDecorator {
|
||||
/**
|
||||
* Invoke as ES7 decorator.
|
||||
*/
|
||||
<T extends Type>(type: T): T;
|
||||
|
||||
// Make TypeDecorator assignable to built-in ParameterDecorator type.
|
||||
// ParameterDecorator is declared in lib.d.ts as a `declare type`
|
||||
// so we cannot declare this interface as a subtype.
|
||||
// see https://github.com/angular/angular/issues/3379#issuecomment-126169417
|
||||
(target: Object, propertyKey?: string | symbol, parameterIndex?: number): void;
|
||||
|
||||
/**
|
||||
* Storage for the accumulated annotations so far used by the DSL syntax.
|
||||
*
|
||||
* Used by {@link Class} to annotate the generated class.
|
||||
*/
|
||||
annotations: any[];
|
||||
|
||||
/**
|
||||
* Generate a class from the definition and annotate it with {@link TypeDecorator#annotations}.
|
||||
*/
|
||||
Class(obj: ClassDefinition): ConcreteType;
|
||||
}
|
||||
|
||||
function extractAnnotation(annotation: any): any {
|
||||
if (isFunction(annotation) && annotation.hasOwnProperty('annotation')) {
|
||||
// it is a decorator, extract annotation
|
||||
annotation = annotation.annotation;
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
|
||||
function applyParams(fnOrArray: (Function | any[]), key: string): Function {
|
||||
if (fnOrArray === Object || fnOrArray === String || fnOrArray === Function ||
|
||||
fnOrArray === Number || fnOrArray === Array) {
|
||||
throw new Error(`Can not use native ${stringify(fnOrArray)} as constructor`);
|
||||
}
|
||||
if (isFunction(fnOrArray)) {
|
||||
return <Function>fnOrArray;
|
||||
} else if (fnOrArray instanceof Array) {
|
||||
var annotations: any[] = fnOrArray;
|
||||
var fn: Function = fnOrArray[fnOrArray.length - 1];
|
||||
if (!isFunction(fn)) {
|
||||
throw new Error(
|
||||
`Last position of Class method array must be Function in key ${key} was '${stringify(fn)}'`);
|
||||
}
|
||||
var annoLength = annotations.length - 1;
|
||||
if (annoLength != fn.length) {
|
||||
throw new Error(
|
||||
`Number of annotations (${annoLength}) does not match number of arguments (${fn.length}) in the function: ${stringify(fn)}`);
|
||||
}
|
||||
var paramsAnnotations: any[][] = [];
|
||||
for (var i = 0, ii = annotations.length - 1; i < ii; i++) {
|
||||
var paramAnnotations: any[] = [];
|
||||
paramsAnnotations.push(paramAnnotations);
|
||||
var annotation = annotations[i];
|
||||
if (annotation instanceof Array) {
|
||||
for (var j = 0; j < annotation.length; j++) {
|
||||
paramAnnotations.push(extractAnnotation(annotation[j]));
|
||||
}
|
||||
} else if (isFunction(annotation)) {
|
||||
paramAnnotations.push(extractAnnotation(annotation));
|
||||
} else {
|
||||
paramAnnotations.push(annotation);
|
||||
}
|
||||
}
|
||||
Reflect.defineMetadata('parameters', paramsAnnotations, fn);
|
||||
return fn;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Only Function or Array is supported in Class definition for key '${key}' is '${stringify(fnOrArray)}'`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a way for expressing ES6 classes with parameter annotations in ES5.
|
||||
*
|
||||
* ## Basic Example
|
||||
*
|
||||
* ```
|
||||
* var Greeter = ng.Class({
|
||||
* constructor: function(name) {
|
||||
* this.name = name;
|
||||
* },
|
||||
*
|
||||
* greet: function() {
|
||||
* alert('Hello ' + this.name + '!');
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* is equivalent to ES6:
|
||||
*
|
||||
* ```
|
||||
* class Greeter {
|
||||
* constructor(name) {
|
||||
* this.name = name;
|
||||
* }
|
||||
*
|
||||
* greet() {
|
||||
* alert('Hello ' + this.name + '!');
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* or equivalent to ES5:
|
||||
*
|
||||
* ```
|
||||
* var Greeter = function (name) {
|
||||
* this.name = name;
|
||||
* }
|
||||
*
|
||||
* Greeter.prototype.greet = function () {
|
||||
* alert('Hello ' + this.name + '!');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ### Example with parameter annotations
|
||||
*
|
||||
* ```
|
||||
* var MyService = ng.Class({
|
||||
* constructor: [String, [new Query(), QueryList], function(name, queryList) {
|
||||
* ...
|
||||
* }]
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* is equivalent to ES6:
|
||||
*
|
||||
* ```
|
||||
* class MyService {
|
||||
* constructor(name: string, @Query() queryList: QueryList) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ### Example with inheritance
|
||||
*
|
||||
* ```
|
||||
* var Shape = ng.Class({
|
||||
* constructor: (color) {
|
||||
* this.color = color;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* var Square = ng.Class({
|
||||
* extends: Shape,
|
||||
* constructor: function(color, size) {
|
||||
* Shape.call(this, color);
|
||||
* this.size = size;
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function Class(clsDef: ClassDefinition): ConcreteType {
|
||||
var constructor = applyParams(
|
||||
clsDef.hasOwnProperty('constructor') ? clsDef.constructor : undefined, 'constructor');
|
||||
var proto = constructor.prototype;
|
||||
if (clsDef.hasOwnProperty('extends')) {
|
||||
if (isFunction(clsDef.extends)) {
|
||||
(<Function>constructor).prototype = proto =
|
||||
Object.create((<Function>clsDef.extends).prototype);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Class definition 'extends' property must be a constructor function was: ${stringify(clsDef.extends)}`);
|
||||
}
|
||||
}
|
||||
for (var key in clsDef) {
|
||||
if (key != 'extends' && key != 'prototype' && clsDef.hasOwnProperty(key)) {
|
||||
proto[key] = applyParams(clsDef[key], key);
|
||||
}
|
||||
}
|
||||
|
||||
if (this && this.annotations instanceof Array) {
|
||||
Reflect.defineMetadata('annotations', this.annotations, constructor);
|
||||
}
|
||||
|
||||
if (!constructor['name']) {
|
||||
constructor['overriddenName'] = `class${_nextClassId++}`;
|
||||
}
|
||||
|
||||
return <ConcreteType>constructor;
|
||||
}
|
||||
|
||||
var Reflect = global.Reflect;
|
||||
// Throw statement at top-level is disallowed by closure compiler in ES6 input.
|
||||
// Wrap in an IIFE as a work-around.
|
||||
(function checkReflect() {
|
||||
if (!(Reflect && Reflect.getMetadata)) {
|
||||
throw 'reflect-metadata shim is required when using class decorators';
|
||||
}
|
||||
})();
|
||||
|
||||
export function makeDecorator(
|
||||
annotationCls, chainFn: (fn: Function) => void = null): (...args: any[]) => (cls: any) => any {
|
||||
function DecoratorFactory(objOrType): (cls: any) => any {
|
||||
var annotationInstance = new (<any>annotationCls)(objOrType);
|
||||
if (this instanceof annotationCls) {
|
||||
return annotationInstance;
|
||||
} else {
|
||||
var chainAnnotation =
|
||||
isFunction(this) && this.annotations instanceof Array ? this.annotations : [];
|
||||
chainAnnotation.push(annotationInstance);
|
||||
var TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls) {
|
||||
var annotations = Reflect.getOwnMetadata('annotations', cls);
|
||||
annotations = annotations || [];
|
||||
annotations.push(annotationInstance);
|
||||
Reflect.defineMetadata('annotations', annotations, cls);
|
||||
return cls;
|
||||
};
|
||||
TypeDecorator.annotations = chainAnnotation;
|
||||
TypeDecorator.Class = Class;
|
||||
if (chainFn) chainFn(TypeDecorator);
|
||||
return TypeDecorator;
|
||||
}
|
||||
}
|
||||
DecoratorFactory.prototype = Object.create(annotationCls.prototype);
|
||||
return DecoratorFactory;
|
||||
}
|
||||
|
||||
export function makeParamDecorator(annotationCls): any {
|
||||
function ParamDecoratorFactory(...args): any {
|
||||
var annotationInstance = Object.create(annotationCls.prototype);
|
||||
annotationCls.apply(annotationInstance, args);
|
||||
if (this instanceof annotationCls) {
|
||||
return annotationInstance;
|
||||
} else {
|
||||
(<any>ParamDecorator).annotation = annotationInstance;
|
||||
return ParamDecorator;
|
||||
}
|
||||
|
||||
|
||||
function ParamDecorator(cls, unusedKey, index): any {
|
||||
var parameters: any[][] = Reflect.getMetadata('parameters', cls);
|
||||
parameters = parameters || [];
|
||||
|
||||
// there might be gaps if some in between parameters do not have annotations.
|
||||
// we pad with nulls.
|
||||
while (parameters.length <= index) {
|
||||
parameters.push(null);
|
||||
}
|
||||
|
||||
parameters[index] = parameters[index] || [];
|
||||
var annotationsForParam: any[] = parameters[index];
|
||||
annotationsForParam.push(annotationInstance);
|
||||
|
||||
Reflect.defineMetadata('parameters', parameters, cls);
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
ParamDecoratorFactory.prototype = Object.create(annotationCls.prototype);
|
||||
return ParamDecoratorFactory;
|
||||
}
|
||||
|
||||
export function makePropDecorator(decoratorCls): any {
|
||||
function PropDecoratorFactory(...args): any {
|
||||
var decoratorInstance = Object.create(decoratorCls.prototype);
|
||||
decoratorCls.apply(decoratorInstance, args);
|
||||
|
||||
if (this instanceof decoratorCls) {
|
||||
return decoratorInstance;
|
||||
} else {
|
||||
return function PropDecorator(target: any, name: string) {
|
||||
var meta = Reflect.getOwnMetadata('propMetadata', target.constructor);
|
||||
meta = meta || {};
|
||||
meta[name] = meta[name] || [];
|
||||
meta[name].unshift(decoratorInstance);
|
||||
Reflect.defineMetadata('propMetadata', meta, target.constructor);
|
||||
};
|
||||
}
|
||||
}
|
||||
PropDecoratorFactory.prototype = Object.create(decoratorCls.prototype);
|
||||
return PropDecoratorFactory;
|
||||
}
|
Reference in New Issue
Block a user