Skip to content

Commit

Permalink
- fix of decorators from different modules (issue #27)
Browse files Browse the repository at this point in the history
- new! literal arguments of decorators captured -> Decorator.getArguments(): Array<any>
- decorator can be CallExpression`@decorator()` or (new) just Identifier `@decorator`
- TypeBuilders
- getType(val: any) on runtime value - preparation
- fix of some circular dependencies in runtime package
- Null metadata Store
  • Loading branch information
Hookyns committed Feb 11, 2022
1 parent 5a654be commit 596b6d5
Show file tree
Hide file tree
Showing 25 changed files with 629 additions and 166 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,7 @@ export interface Property
/**
* Decoration description
*/
export interface Decorator
{
export class Decorator {
/**
* Decorator name
*/
Expand All @@ -849,6 +848,10 @@ export interface Decorator
* Decorator full name
*/
fullName?: string;
/**
* List of literal arguments
*/
getArguments(): Array<any>;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions dev/quick-tests/SomeEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum SomeEnum
{
One,
Two
}
3 changes: 3 additions & 0 deletions dev/quick-tests/SomeType.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export const SomeString = "SomeTypeString";

export class SomeType {

foo() {

}
Expand Down
41 changes: 25 additions & 16 deletions dev/quick-tests/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { getType } from "tst-reflect";
import { getType } from "tst-reflect";
import { property } from "./property";
import { SomeEnum } from "./SomeEnum";
import { SomeString } from "./SomeType";

enum SomeEnum
{
One,
Two
}
const MyString = "SomeType";

interface Foo
/**
* @reflectDecorator
*/
function klass<TType>(str: string, num: number, enu: SomeEnum)
{
enum: SomeEnum;
console.log("klass", str, num, enu);
const t = getType<TType>();

console.log(t.getDecorators().map(d => "\tdecorator: " + d.name + " args:" + d.getArguments().join(", ")));
return function <T>(Constructor: { new(...args: any[]): T }) {
};
}

const type = getType<Foo>();

console.log(type);

const enumProperty = type.getProperties().find(prop => prop.type.isEnum());

if (enumProperty)
@klass(MyString, 5, SomeEnum.One)
class A
{
console.log(enumProperty.type.name, enumProperty.type.getEnum().getEnumerators());
@property("Foo property", 5, SomeEnum.One, { foo: "f", bar: 5, baz: SomeEnum.Two })
foo: string;

@property(SomeString, 5, SomeEnum.Two, true)
get bar(): number
{
return 0;
}
}
7 changes: 7 additions & 0 deletions dev/quick-tests/property.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { SomeEnum } from "./SomeEnum";

export function property(str: string, num: number, enu: SomeEnum, any: any)
{
console.log("property", str, num, enu, any);
return function (_, __) {};
}
51 changes: 35 additions & 16 deletions runtime/src/Type.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import type { MetadataStore } from "./meta-stores/MetadataStore";
import type { MetadataStore } from "./meta-stores";
import {
Constructor,
Method,
} from "./descriptions/method";
import type { Decorator } from "./descriptions/decorator";
import type { IndexedAccessType } from "./descriptions/indexed-access-type";
import type { ConditionalType } from "./descriptions/conditional-type";
} from "./descriptions/method";
import type { Decorator } from "./descriptions/decorator";
import type { IndexedAccessType } from "./descriptions/indexed-access-type";
import type { ConditionalType } from "./descriptions/conditional-type";
import {
ConstructorImport,
ConstructorImportActivator
} from "./descriptions/constructor-import";
import type { Property, } from "./descriptions/property";
import type { MethodParameter, } from "./descriptions/parameter";
import type { EnumInfo } from "./descriptions/enum-info";
import type { TypeProperties } from "./descriptions/type-properties";
import { TypeKind } from "./enums";
} from "./descriptions/constructor-import";
import type { Property, } from "./descriptions/property";
import type { MethodParameter, } from "./descriptions/parameter";
import type { EnumInfo } from "./descriptions/enum-info";
import type { TypeProperties } from "./descriptions/type-properties";
import { TypeKind } from "./enums";
import {
Mapper,
resolveLazyType
} from "./mapper";
import { InlineMetadataStore } from "./meta-stores/InlineMetadataStore";
} from "./mapper";

/**
* Object representing TypeScript type in memory
Expand All @@ -34,6 +33,8 @@ export class Type
public static readonly Number: Type;
public static readonly Boolean: Type;
public static readonly Date: Type;
public static readonly Null: Type;
public static readonly Undefined: Type;

/** @internal */
private _ctor?: () => Function;
Expand Down Expand Up @@ -79,7 +80,25 @@ export class Type
private _genericTypeDefault?: Type;

/** @internal */
private static _store: MetadataStore = InlineMetadataStore.initiate();
private static _store: MetadataStore = {
store: {},
get(id: number)
{
return undefined;
},
set(id: number, description: any)
{
return Type.Unknown;
},
getLazy(id: number)
{
return () => undefined;
},
wrap(description: any)
{
return Type.Unknown;
}
};

/**
* Internal Type constructor
Expand Down Expand Up @@ -308,7 +327,7 @@ export class Type
{
return false;
}

return type != undefined && this._fullName == type._fullName && !!this._fullName;
}

Expand Down Expand Up @@ -507,7 +526,7 @@ export class Type
}
{
// TODO: Important to handle Unions and Intersections

const interfaceMembers = this.interface?.flattenInheritedMembers() ?? { properties: {}, methods: {} };
const baseTypeMembers = this.baseType?.flattenInheritedMembers() ?? { properties: {}, methods: {} };

Expand Down
5 changes: 5 additions & 0 deletions runtime/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ export const GET_TYPE_FNC_NAME = "getType";
* Symbol used as key in objects, holding metadata
*/
export const REFLECT_STORE_SYMBOL = Symbol("tst_reflect_store");

/**
* Name of the property used to store Type instance on constructors
*/
export const REFLECTED_TYPE = "__reflectedType__";
36 changes: 35 additions & 1 deletion runtime/src/descriptions/decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ export interface DecoratorDescription
* Decorator full name
*/
fn: string;

/**
* List of literal arguments
*/
args?: Array<any>;
}

/**
* Decoration description
*/
export interface Decorator
export class Decorator
{
/**
* Decorator name
Expand All @@ -28,4 +33,33 @@ export interface Decorator
* Decorator full name
*/
fullName?: string;

/**
* @internal
*/
private args: Array<any>;

/**
* Internal constructor
* @internal
*/
protected constructor(description: DecoratorDescription)
{
this.name = description.n;
this.fullName = description.fn;
this.args = description.args || [];
}

/**
* List of literal arguments
*/
getArguments(): Array<any>
{
return this.args.slice();
}
}

/**
* @internal
*/
export class DecoratorActivator extends Decorator {}
13 changes: 7 additions & 6 deletions runtime/src/mapper.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import {
AccessModifier,
Accessor
} from "./enums";
} from "./enums";
import type { Type } from "./Type";
import {
Decorator,
DecoratorActivator,
DecoratorDescription
} from "./descriptions/decorator";
} from "./descriptions/decorator";
import {
Constructor,
ConstructorActivator,
ConstructorDescription,
Method,
MethodActivator,
MethodDescription
} from "./descriptions/method";
} from "./descriptions/method";
import {
MethodParameter,
ParameterDescription
} from "./descriptions/parameter";
} from "./descriptions/parameter";
import {
Property,
PropertyDescription
} from "./descriptions/property";
} from "./descriptions/property";

/**
* @internal
Expand All @@ -44,7 +45,7 @@ export const Mapper = {
*/
mapDecorators(d: DecoratorDescription): Decorator
{
return ({ name: d.n, fullName: d.fn });
return Reflect.construct(Decorator, [d], DecoratorActivator);
},

/**
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/meta-stores/MetadataStoreBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export abstract class MetadataStoreBase implements MetadataStore
}
}

const type = Reflect.construct(Type, [], TypeActivator);
const type: Type = Reflect.construct(Type, [], TypeActivator);
type.initialize(description);
return type;
}
Expand Down
4 changes: 4 additions & 0 deletions runtime/src/meta-stores/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InlineMetadataStore } from "./InlineMetadataStore";
import { MetadataStore } from "./MetadataStore";
import { NodeProcessMetadataStore } from "./NodeProcessMetadataStore";
import { WindowMetadataStore } from "./WindowMetadataStore";
Expand All @@ -7,6 +8,9 @@ export * from "./InlineMetadataStore";
export * from "./WindowMetadataStore";
export * from "./NodeProcessMetadataStore";

// Default store
InlineMetadataStore.initiate();

/**
* Function used in transformer templates for metadata files.
* @return {MetadataStore}
Expand Down
Loading

0 comments on commit 596b6d5

Please sign in to comment.