Skip to content

Commit

Permalink
feat(api): added composite API
Browse files Browse the repository at this point in the history
  • Loading branch information
fenying committed Jun 19, 2021
1 parent 61d96dc commit 184a414
Show file tree
Hide file tree
Showing 9 changed files with 604 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changes Logs

## v0.2.0

- feat(api): added `composite` API.
16 changes: 16 additions & 0 deletions docs/zh-CN/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## API 篇

### composite

```ts
function composite<
T extends IGeneralDecorator | IClassDecorator | IMethodParameterDecorator |
IMethodDecorator | IConstructorParameterDecorator | IStaticMethodDecorator |
IStaticMethodParameterDecorator | IPropertyDecorator | IStaticPropertyDecorator
>(decorators: T[]): T;
```

这个方法用于将多个同类装饰器合成一个装饰器。

> 多个装饰器,按数组排序顺序执行。
参考示例:[00-ClassDecorator.ts](../../src/examples/00-ClassDecorator.ts)[01-MemberMethodDecorator.ts](../../src/examples/01-MemberMethodDecorator.ts)

### createAccessorDecorator

```ts
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@litert/decorator",
"version": "0.1.0",
"version": "0.2.0",
"description": "The utility set of decorators.",
"main": "./lib/index.js",
"scripts": {
Expand Down
29 changes: 27 additions & 2 deletions src/examples/00-ClassDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,34 @@

import $Decorators from '../lib';

@$Decorators.createClassDecorator((ctor) => console.log(`Decorated class ${ctor.name}`))

@$Decorators.composite([
$Decorators.createClassDecorator((ctor) => console.log(`3. Class name before secord decorated: ${ctor.name}`)),
$Decorators.createClassDecorator((ctor) => (class Test2 extends ctor {

public name: string = 'Mick';

public printName(): void {

console.log(this.name);
}
})),
$Decorators.createClassDecorator((ctor) => console.log(`4. Class name after secord decorated: ${ctor.name}`)),
$Decorators.createClassDecorator((ctor) => console.log(Object.getOwnPropertyNames(ctor.prototype))),
])
@$Decorators.createClassDecorator((ctor) => console.log(`2. Class name after first decorated: ${ctor.name}`))
@$Decorators.createClassDecorator((ctor) => (class Test1 extends ctor {

public age: number = 312;

public printAge(): void {

console.log(this.age);
}
}))
@$Decorators.createClassDecorator((ctor) => console.log(`1. Class name before decorated: ${ctor.name}`))
class DemoClassDecorator {

}

new DemoClassDecorator();
console.log(`Final class: ${DemoClassDecorator.name}`);
56 changes: 52 additions & 4 deletions src/examples/01-MemberMethodDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,58 @@ import $Decorators from '../lib';

class DemoMemberMethodDecorator {

@$Decorators.createMethodDecorator(function(proto, name) {
console.log(`Decorated method ${proto.constructor.name}::${name as string}`);
@$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log('test1: After decorated:')
console.log(`test1: configurable: ${dtr.configurable}`);
console.log(`test1: value: ${dtr.value}`);
})
public test(): void {}
@$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log('test1: Before decorated:')
console.log(`test1: configurable: ${dtr.configurable}`);
console.log(`test1: value: ${dtr.value}`);

dtr.value = function hello() { console.log('this is test 1 hello'); };
dtr.configurable = false;
})
@$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log(`test1: Decorated method ${proto.constructor.name}::${name as string}`);
})
public test1(): void {

console.log('this is test 1');
}

@$Decorators.composite([

$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log(`test2: Decorated method ${proto.constructor.name}::${name as string}`);
}),
$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log('test2: Before decorated:')
console.log(`test2: configurable: ${dtr.configurable}`);
console.log(`test2: value: ${dtr.value}`);

dtr.value = function go() { console.log('this is test 2 go'); };
dtr.configurable = false;
}),
$Decorators.createMethodDecorator(function(proto, name, dtr) {
console.log('test2: After decorated:')
console.log(`test2: configurable: ${dtr.configurable}`);
console.log(`test2: value: ${dtr.value}`);
})
])
public test2(): void {
console.log('this is test 2');
}
}

new DemoMemberMethodDecorator();
console.log('test1: Final:')
console.log(`test1: configurable: ${Object.getOwnPropertyDescriptor(DemoMemberMethodDecorator.prototype, 'test1')!.configurable}`);
console.log(`test1: value: ${DemoMemberMethodDecorator.prototype.test1}`);

console.log('test2: Final:')
console.log(`test2: configurable: ${Object.getOwnPropertyDescriptor(DemoMemberMethodDecorator.prototype, 'test2')!.configurable}`);
console.log(`test2: value: ${DemoMemberMethodDecorator.prototype.test2}`);

new DemoMemberMethodDecorator().test1();
new DemoMemberMethodDecorator().test2();
17 changes: 15 additions & 2 deletions src/lib/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ export type IConstructorParameterDecoratorProcessor = (ctor: IClassCtor, index:
* Signature of any decorator.
*/
export interface IGeneralDecorator {
(target: IClassCtor): void;
(target: IObject, propertyKey: string | symbol, index?: any): void;
(target: IClassCtor): any;
(target: IObject, propertyKey: string | symbol, index?: any): any;
}

export interface IGeneralDecoratorProcessorSet {
Expand Down Expand Up @@ -530,4 +530,17 @@ export interface IDecoratorUtility {
* @param name The name of static member in class.
*/
isStaticAccessor(ctor: IClassCtor, name: string | symbol): boolean;

/**
* Composite multiple same-type decorator into a one.
*
* > The decorators will be applied in order of the decorator array.
*
* @param decorators The decorators list.
*/
composite<
T extends IGeneralDecorator | IClassDecorator | IMethodParameterDecorator |
IMethodDecorator | IConstructorParameterDecorator | IStaticMethodDecorator |
IStaticMethodParameterDecorator | IPropertyDecorator | IStaticPropertyDecorator
>(decorators: T[]): T;
}
32 changes: 32 additions & 0 deletions src/lib/DecoratorUtility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,4 +687,36 @@ export class DecoratorUtility implements C.IDecoratorUtility {

this._hookNativeReflectMetadata = true;
}

public composite(decorators: any[]): any {

return function(a: any, b: any, c: any): any {

for (const d of (decorators as Array<(...args: any[]) => any>)) {

if (typeof c === 'object') {

c = d(a, b, c) ?? c;
}
else if (b === undefined && c === undefined) {

a = d(a, b, c) ?? a;
}
else {

d(a, b, c);
}
}

if (typeof c === 'object') {

return c;
}
else if (b === undefined && c === undefined) {

return a;
}

} as any;
}
}
Loading

0 comments on commit 184a414

Please sign in to comment.