/ lib / decorators.js
decorators.js
 1  import { printType } from '@bablr/agast-helpers/print';
 2  import * as sym from './symbols.js';
 3  
 4  export const AllowEmpty = (desc, context) => {
 5    context.addInitializer(function () {
 6      let emptyables = this.emptyables;
 7  
 8      if (!emptyables) {
 9        emptyables = this.emptyables = new Set();
10      }
11  
12      emptyables.add(context.name);
13    });
14  };
15  
16  export const CoveredBy = (type) => {
17    return (desc, context) => {
18      if (!/^[a-zA-Z]+$/.test(printType(type))) throw new Error();
19  
20      context.addInitializer(function () {
21        let covers = this.covers;
22  
23        if (!covers) {
24          covers = this.covers = new Map();
25        }
26  
27        let coveredTypes = covers.get(type);
28  
29        if (!coveredTypes) {
30          coveredTypes = new Set();
31          covers.set(type, coveredTypes);
32        }
33  
34        coveredTypes.add(context.name);
35      });
36    };
37  };
38  
39  export const InjectFrom = (obj) => (_stub, context) => {
40    if (!Object.hasOwn(obj, context.name)) {
41      throw new Error('Bad injection');
42    }
43  
44    return obj[context.name];
45  };
46  
47  export const Node = (desc, context) => {
48    return CoveredBy(sym.node)(desc, context);
49  };
50  
51  export const Attributes = (attributes) => (desc, context) => {
52    context.addInitializer(function () {
53      this.attributes = this.attributes || new Map();
54      this.attributes.set(context.name, attributes);
55    });
56  };
57  
58  export const UnboundAttributes = (attributes) => (desc, context) => {
59    context.addInitializer(function () {
60      this.unboundAttributes = this.unboundAttributes || new Map();
61      this.unboundAttributes.set(context.name, attributes);
62    });
63  };