1
1
import { Position } from "./position" ;
2
2
import "reflect-metadata" ;
3
- import { ReferenceByName } from "./naming" ;
3
+ import { PossiblyNamed , ReferenceByName } from "./naming" ;
4
4
5
5
export const NODE_DEFINITION_SYMBOL = Symbol ( "nodeDefinition" ) ;
6
6
@@ -24,6 +24,7 @@ export type PropertyDefinition = {
24
24
child ?: boolean ,
25
25
multiple ?: boolean ,
26
26
inherited ?: boolean ,
27
+ reference ?: boolean ,
27
28
type ?: any ,
28
29
arrayType ?: any
29
30
}
@@ -163,8 +164,8 @@ export abstract class Node extends Origin implements Destination {
163
164
const props = this . nodeDefinition ?. properties || { } ;
164
165
return Object . getOwnPropertyNames ( props ) . map ( p => {
165
166
const value = props [ p ] . child ?
166
- ( props [ p ] . multiple ? this . getChildren ( p ) : this . getChild ( p ) ) :
167
- this . getAttributeValue ( p ) ;
167
+ ( props [ p ] . multiple ? this . getChildren ( p ) : this . getChild ( p ) ) :
168
+ ( props [ p ] . reference ? this . getReference ( p ) : this . getAttributeValue ( p ) ) ;
168
169
return { name : p , value } ;
169
170
} ) ;
170
171
}
@@ -278,7 +279,11 @@ export abstract class Node extends Origin implements Destination {
278
279
if ( prop . child ) {
279
280
throw new Error ( name . toString ( ) + " is a containment, please use getChild" ) ;
280
281
} else {
281
- return this . doGetAttributeValue ( name ) ;
282
+ const attributeValue = this . doGetAttributeValue ( name ) ;
283
+ if ( attributeValue instanceof ReferenceByName ) {
284
+ throw new Error ( name . toString ( ) + " is a reference, please use getReference" ) ;
285
+ }
286
+ return attributeValue ;
282
287
}
283
288
} else {
284
289
throw new Error ( `${ name . toString ( ) } is not a feature of ${ this } (${ this . nodeDefinition } ).` ) ;
@@ -308,7 +313,11 @@ export abstract class Node extends Origin implements Destination {
308
313
}
309
314
310
315
getReference ( name : string | symbol ) : ReferenceByName < any > | undefined {
311
- return this [ name ] as ReferenceByName < any > ;
316
+ return this . doGetReference ( name ) as ReferenceByName < any > ;
317
+ }
318
+
319
+ protected doGetReference ( name : string | symbol ) {
320
+ return this [ name ] ;
312
321
}
313
322
314
323
withParent ( parent ?: Node ) : this {
@@ -434,7 +443,7 @@ export function ensureNodeDefinition(node: Node | { new (...args: any[]): Node }
434
443
return definition ;
435
444
}
436
445
437
- export function registerNodeProperty < T extends Node > (
446
+ export function registerNodeAttribute < T extends Node > (
438
447
type : { new ( ...args : any [ ] ) : T } , methodName : string | symbol
439
448
) : PropertyDefinition {
440
449
if ( methodName == "parent" || methodName == "children" || methodName == "origin" ) {
@@ -451,12 +460,19 @@ export function registerNodeProperty<T extends Node>(
451
460
452
461
export function registerNodeChild < T extends Node > (
453
462
type : new ( ...args : any [ ] ) => T , methodName : string , multiple : boolean = false ) : PropertyDefinition {
454
- const propInfo = registerNodeProperty ( type , methodName ) ;
463
+ const propInfo = registerNodeAttribute ( type , methodName ) ;
455
464
propInfo . child = true ;
456
465
propInfo . multiple = multiple ;
457
466
return propInfo ;
458
467
}
459
468
469
+ export function registerNodeReference < T extends Node & PossiblyNamed > (
470
+ type : new ( ...args : any [ ] ) => T , methodName : string ) : PropertyDefinition {
471
+ const propInfo = registerNodeAttribute ( type , methodName ) ;
472
+ propInfo . reference = true ;
473
+ return propInfo ;
474
+ }
475
+
460
476
//------------//
461
477
// Decorators //
462
478
//------------//
@@ -485,9 +501,30 @@ export function Children(): (target, methodName: string) => void {
485
501
} ;
486
502
}
487
503
488
-
504
+ /**
505
+ * Declares the decorated property as an attribute.
506
+ * @deprecated use Attribute instead.
507
+ */
489
508
export function Property ( ) : ( target , methodName : string ) => void {
490
509
return function ( target , methodName : string ) {
491
- registerNodeProperty ( target , methodName ) ;
510
+ registerNodeAttribute ( target , methodName ) ;
511
+ } ;
512
+ }
513
+
514
+ /**
515
+ * Declares the decorated property as an attribute.
516
+ */
517
+ export function Attribute ( ) : ( target , methodName : string ) => void {
518
+ return function ( target , methodName : string ) {
519
+ registerNodeAttribute ( target , methodName ) ;
520
+ } ;
521
+ }
522
+
523
+ /**
524
+ * Declares the decorated property as a reference.
525
+ */
526
+ export function Reference ( ) : ( target , methodName : string ) => void {
527
+ return function ( target , methodName : string ) {
528
+ registerNodeReference ( target , methodName ) ;
492
529
} ;
493
530
}
0 commit comments