Skip to content

Commit fcec15d

Browse files
committed
Re-org EOProp classes
1 parent e823847 commit fcec15d

14 files changed

Lines changed: 262 additions & 298 deletions

File tree

transforms/helpers/ast.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import { LAYOUT_DECORATOR_NAME } from './util/index';
3131
import { isRecord } from './util/types';
3232

3333
export type { ClassBodyBuilder } from 'ast-types/gen/builders';
34-
export type { CommentKind } from 'ast-types/gen/kinds';
3534
export type {
3635
ASTNode,
3736
CallExpression,

transforms/helpers/eo-extend-expression.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export default class EOExtendExpression {
6969
existingDecoratorImportInfos,
7070
options
7171
);
72-
if ('isClassDecorator' in eoProp) {
72+
if (eoProp.isClassDecorator) {
7373
decorators.push(eoProp);
7474
} else {
7575
properties.push(eoProp);
Lines changed: 69 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {
2-
CommentKind,
32
Decorator,
43
EOExpressionProp,
54
EOMethod,
@@ -23,23 +22,33 @@ type EOPropValue = EOProperty['value'] | EOMethod;
2322
* A wrapper object for ember object properties
2423
*/
2524
export default abstract class AbstractEOProp<P extends EOExpressionProp, B> {
26-
readonly _prop: P & {
27-
// ast-types missing these properties that exist on @babel/types
28-
decorators?: Decorator[] | null;
29-
};
25+
abstract readonly isClassDecorator: boolean;
3026

31-
protected decorators: DecoratorImportInfo[] = [];
27+
protected abstract readonly value: EOPropValue;
28+
29+
protected readonly key = this.rawProp.key;
30+
31+
protected readonly comments = this.rawProp.comments ?? null;
3232

33-
/** Runtime Data */
34-
readonly runtimeData: RuntimeData;
35-
private readonly runtimeType: string | undefined;
33+
protected readonly existingDecorators = this.rawProp.decorators ?? null;
3634

37-
constructor(eoProp: P, protected readonly options: Options) {
38-
this._prop = eoProp;
35+
protected decorators: DecoratorImportInfo[] = [];
36+
37+
protected readonly runtimeData: RuntimeData;
3938

39+
/** Override to `true` if the property type supports object literal decorators. */
40+
protected readonly supportsObjectLiteralDecorators: boolean = false;
41+
42+
constructor(
43+
protected readonly rawProp: P & {
44+
// ast-types missing these properties that exist on @babel/types
45+
decorators?: Decorator[] | null;
46+
},
47+
protected readonly options: Options
48+
) {
4049
this.runtimeData = options.runtimeData;
4150
if (this.runtimeData.type) {
42-
const { type, offProperties, unobservedProperties } = this.runtimeData;
51+
const { offProperties, unobservedProperties } = this.runtimeData;
4352

4453
const unobservedArgs = unobservedProperties[this.name];
4554
if (unobservedArgs) {
@@ -53,15 +62,12 @@ export default abstract class AbstractEOProp<P extends EOExpressionProp, B> {
5362
if (offArgs) {
5463
this.decorators.push({ name: 'off', args: offArgs });
5564
}
56-
this.runtimeType = type;
5765
}
5866
}
5967

60-
// FIXME: Verify that everything on these classes is still needed
61-
// FIXME: Verify access modifiers
62-
abstract value: EOPropValue;
63-
64-
abstract build(): B;
68+
get name(): string {
69+
return this.key.name;
70+
}
6571

6672
/**
6773
* Get the map of decorators to import other than the computed props, services etc
@@ -81,75 +87,6 @@ export default abstract class AbstractEOProp<P extends EOExpressionProp, B> {
8187
};
8288
}
8389

84-
get type(): EOPropValue['type'] {
85-
return this.value.type;
86-
}
87-
88-
get key(): P['key'] {
89-
return this._prop.key;
90-
}
91-
92-
get name(): string {
93-
return this._prop.key.name;
94-
}
95-
96-
get comments(): CommentKind[] | null {
97-
return this._prop.comments ?? null;
98-
}
99-
100-
get computed(): boolean {
101-
return this._prop.computed ?? false;
102-
}
103-
104-
get isComputed(): boolean {
105-
return this.runtimeData.computedProperties.includes(this.name);
106-
}
107-
108-
get isOverridden(): boolean {
109-
return this.runtimeData.overriddenProperties.includes(this.name);
110-
}
111-
112-
get hasRuntimeData(): boolean {
113-
return !!this.runtimeType;
114-
}
115-
116-
get replaceSuperWithUndefined(): boolean {
117-
return this.hasRuntimeData && !this.isOverridden;
118-
}
119-
120-
get existingDecorators(): Decorator[] | null {
121-
return this._prop.decorators ?? null;
122-
}
123-
124-
get hasDecorators(): boolean {
125-
return this.decorators.length > 0;
126-
}
127-
128-
get hasUnobservesDecorator(): boolean {
129-
return this.decorators.some((d) => d.name === 'unobserves');
130-
}
131-
132-
get hasOffDecorator(): boolean {
133-
return this.decorators.some((d) => d.name === 'off');
134-
}
135-
136-
get hasMetaDecorator(): boolean {
137-
return this.decorators.some((d) => d.isMetaDecorator);
138-
}
139-
140-
/** Override to `true` if the property type supports object literal decorators. */
141-
protected supportsObjectLiteralDecorators = false;
142-
143-
protected get needsDecorators(): boolean {
144-
return this.hasExistingDecorators || this.hasDecorators;
145-
}
146-
147-
private get hasExistingDecorators(): boolean {
148-
return (
149-
this.existingDecorators !== null && this.existingDecorators.length > 0
150-
);
151-
}
152-
15390
get errors(): string[] {
15491
let errors: string[] = [];
15592

@@ -164,7 +101,6 @@ export default abstract class AbstractEOProp<P extends EOExpressionProp, B> {
164101
);
165102
}
166103

167-
// FIXME: only include if existing decorators are supported?
168104
for (const decorator of this.existingDecorators) {
169105
const decoratorName = isNode(decorator.expression, 'Identifier')
170106
? decorator.expression.name
@@ -205,17 +141,58 @@ export default abstract class AbstractEOProp<P extends EOExpressionProp, B> {
205141
);
206142
}
207143

208-
errors = [...errors, ...this._errors];
144+
errors = [...errors, ...this.typeErrors];
209145

210146
return errors;
211147
}
212148

149+
/** Returns the appropriate ClassBody member for the property type. */
150+
abstract build(): B;
151+
152+
protected makeError(message: string): string {
153+
return `[${this.name}]: Transform not supported - ${message}`;
154+
}
155+
213156
/** Override to add errors specific to the property type. */
214-
protected get _errors(): string[] {
157+
protected get typeErrors(): string[] {
215158
return [];
216159
}
217160

218-
protected makeError(message: string): string {
219-
return `[${this.name}]: Transform not supported - ${message}`;
161+
protected get type(): EOPropValue['type'] {
162+
return this.value.type;
163+
}
164+
165+
protected get isOverridden(): boolean {
166+
return this.runtimeData.overriddenProperties.includes(this.name);
167+
}
168+
169+
protected get replaceSuperWithUndefined(): boolean {
170+
return this.hasRuntimeData && !this.isOverridden;
171+
}
172+
173+
private get hasRuntimeData(): boolean {
174+
return !!this.runtimeData.type;
175+
}
176+
177+
protected get hasDecorators(): boolean {
178+
return this.decorators.length > 0;
179+
}
180+
181+
protected get needsDecorators(): boolean {
182+
return this.hasExistingDecorators || this.hasDecorators;
183+
}
184+
185+
private get hasUnobservesDecorator(): boolean {
186+
return this.decorators.some((d) => d.name === 'unobserves');
187+
}
188+
189+
private get hasOffDecorator(): boolean {
190+
return this.decorators.some((d) => d.name === 'off');
191+
}
192+
193+
private get hasExistingDecorators(): boolean {
194+
return (
195+
this.existingDecorators !== null && this.existingDecorators.length > 0
196+
);
220197
}
221198
}

transforms/helpers/eo-prop/private/actions/index.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ export default class EOActionsProp extends AbstractEOProp<
1414
EOPropertyWithActionsObject,
1515
ClassMethod[]
1616
> {
17+
readonly isClassDecorator = false as const;
18+
19+
protected readonly value = this.rawProp.value;
20+
21+
override get decoratorImportSpecs(): DecoratorImportSpecs {
22+
return {
23+
...super.decoratorImportSpecs,
24+
action: true,
25+
};
26+
}
27+
1728
/**
1829
* FIXME: Verify docs
1930
*
@@ -34,21 +45,14 @@ export default class EOActionsProp extends AbstractEOProp<
3445
* }
3546
* ```
3647
*/
37-
override build(): ClassMethod[] {
48+
build(): ClassMethod[] {
3849
return this.actions.map((action) => {
3950
return action.build();
4051
});
4152
}
4253

43-
override get decoratorImportSpecs(): DecoratorImportSpecs {
44-
return {
45-
...super.decoratorImportSpecs,
46-
action: true,
47-
};
48-
}
49-
50-
get value(): EOPropertyWithActionsObject['value'] {
51-
return this._prop.value;
54+
protected override get typeErrors(): string[] {
55+
return [...this.lifecycleHookErrors, ...this.infiniteLoopErrors];
5256
}
5357

5458
private get actions(): Array<ActionProp | ActionMethod> {
@@ -59,10 +63,6 @@ export default class EOActionsProp extends AbstractEOProp<
5963
);
6064
}
6165

62-
protected override get _errors(): string[] {
63-
return [...this.lifecycleHookErrors, ...this.infiniteLoopErrors];
64-
}
65-
6666
/**
6767
* Iterate over actions and verify that the action name does not match the lifecycle hooks
6868
* The transformation is not supported if an action has the same name as lifecycle hook

transforms/helpers/eo-prop/private/actions/method.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,6 @@ import EOMethodProp from '../method';
1111
import type { Action } from './index';
1212

1313
export default class ActionMethod extends EOMethodProp implements Action {
14-
override build(): ClassMethod {
15-
return replaceActionSuperExpressions(
16-
j.classMethod.from({
17-
kind: this.kind,
18-
key: this.key,
19-
params: this.params,
20-
body: this.body,
21-
comments: this.comments,
22-
decorators: buildActionDecorator(),
23-
}),
24-
this.replaceSuperWithUndefined
25-
);
26-
}
27-
28-
override get isOverridden(): boolean {
29-
return this.runtimeData.overriddenActions.includes(this.name);
30-
}
31-
3214
get hasInfiniteLoop(): boolean {
3315
const { name, value } = this;
3416
const collection = j(value.body) as Collection;
@@ -52,4 +34,22 @@ export default class ActionMethod extends EOMethodProp implements Action {
5234

5335
return actionLiterals.length > 0 || actionCalls.length > 0;
5436
}
37+
38+
override build(): ClassMethod {
39+
return replaceActionSuperExpressions(
40+
j.classMethod.from({
41+
kind: this.kind,
42+
key: this.key,
43+
params: this.params,
44+
body: this.body,
45+
comments: this.comments,
46+
decorators: buildActionDecorator(),
47+
}),
48+
this.replaceSuperWithUndefined
49+
);
50+
}
51+
52+
protected override get isOverridden(): boolean {
53+
return this.runtimeData.overriddenActions.includes(this.name);
54+
}
5555
}

transforms/helpers/eo-prop/private/actions/property.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ export default class ActionProp
88
extends AbstractEOProp<EOActionProperty, ClassMethod>
99
implements Action
1010
{
11-
hasInfiniteLoop = false;
11+
readonly isClassDecorator = false as const;
1212

13-
get value(): EOActionProperty['value'] {
14-
return this._prop.value;
15-
}
13+
readonly hasInfiniteLoop = false;
14+
15+
protected readonly value = this.rawProp.value;
1616

1717
/**
1818
* Actions with identifier converted to method definition
@@ -41,7 +41,7 @@ export default class ActionProp
4141
* });
4242
* ```
4343
*/
44-
override build(): ClassMethod {
44+
build(): ClassMethod {
4545
const body = j.blockStatement([
4646
j.returnStatement(
4747
j.callExpression(j.memberExpression(this.value, j.identifier('call')), [

0 commit comments

Comments
 (0)