Example #1
0
test.group('parseModelDependencies', models(async (t, file) => {
  const model = to.clone(contents[file]);

  model.data.dependencies = t.context.resolvePaths(model.data.dependencies, path.resolve(t.context.options.root, path.dirname(file)));

  await t.context.parseModelDependencies(model);
  if (model.data.dependencies.length === 0) {
    t.plan(0);
  } else {
    const length = t.context.models.length;
    t.is(length, to.unique(t.context.registered_models).length);
  }

  let count = 0;

  function check(dependencies) {
    if (count++ >= 20) {
      t.fail('parseModelDependencies has ran too many checks');
      return;
    }

    for (let dependency_path of dependencies) {
      t.truthy(t.context.registered_models.includes(dependency_path));
      const dependency = _.find(t.context.models, [ 'file', dependency_path ]);
      if (dependency_path === file) {
        t.falsy(dependency.is_dependency);
      } else {
        t.truthy(dependency.is_dependency);
      }
      if (dependency.data.dependencies.length) {
        check(dependency.data.dependencies);
      }
    }
  }

  check(model.data.dependencies);
}));
Example #2
0
  setOptions(options) {
    options = to.arguments({
      language: {
        prefix: '@',

        // header comment style
        // @note {10} only 1 of these can be used per file
        header: { start: '////', line: '///', end: '////', type: 'header' },

        // body comment style
        body: { start: '', line: '///', end: '', type: 'body' },

        // inline comment style
        inline: { start: '', line: '///#', end: '', type: 'inline' },

        // this is used for any interpolations that might occur in annotations.
        // I don't see this needing to change but just incase I'm making it a setting.
        // @note {10} This setting is used to create a RegExp so certain characters need to be escaped
        interpolation: { start: '\\${', end: '}' },
      },
      type: undefined,
      blank_lines: 4,
      indent: true,
      annotations: {},
      sort: [],
      log: logger
    }, arguments)

    let { annotations, type, log, ...rest } = options
    this.log = log
    this.options = rest
    this.api = new AnnotationApi({ annotations, type })

    // this is used to pass to the annotations when they're called
    this.annotation_options = { log: this.log, options: this.options }

    const { language } = this.options

    this.comment_values = to.flatten([
      ...to.values(language.header, '!type'),
      ...to.values(language.body, '!type'),
      ...to.values(language.inline, '!type')
    ])
    this.comment_values = to.unique(this.comment_values).filter(Boolean)

    {
      let { alias, parse } = this.api.annotations
      parse = to.keys(parse)
      const reverse_alias_list = to.reduce(alias, (previous, { key, value }) => {
        value = value
          .filter((_alias) => !is.in(parse, _alias))
          .reduce((a, b) => to.extend(a, { [b]: key }), {})
        return to.extend(previous, value)
      }, {})
      const regex = new RegExp(`^\s*${language.prefix}(?:(${to.keys(reverse_alias_list).join('|')})|(${parse.join('|')}))\\b\\s*`)
      const available = to.unique(to.reduce(this.api.annotations, (previous, { value }) => previous.concat(to.keys(value)), []))
      this.annotations_list = { available, reverse_alias_list, regex }
    }

    this.options.order = sort(this.options.sort, {
      extras: this.annotations_list.available,
      amount: 3
    })
    this.options.order.push('inline') // this is for the inline part of the annotation
  }