chalk icon indicating copy to clipboard operation
chalk copied to clipboard

refactor: remove some chalkConfig field accesses

Open ee7 opened this issue 1 year ago • 0 comments

Issue

#214

Description

Continue from #235 and #236, removing every remaining access of a ChalkConfig field that has a built-in type.

With this PR, the remaining field accesses of chalkConfig are the below:

$ git log --oneline -1                                                                                                                                                                               ~/vcs/github/crashappsec/chalk/src
ddaca94 (HEAD -> ee7/avoid-c4autoconf-part3, crashappsec/ee7/avoid-c4autoconf-part3) refactor(subscan): remove chalkConfig field accesses
$ git grep --break --heading --ignore-case 'chalkConfig\.'
chalkjson.nim
446:    var order = chalkConfig.keySpecs[k].normalizedOrder
486:  for k, _ in chalkConfig.keySpecs:

collect.nim
26:  let spec = chalkConfig.keySpecs[key]
71:    chalkConfig.markTemplates[outConf.markTemplate].registerKeys()
74:    chalkConfig.reportTemplates[outConf.reportTemplate].registerKeys()
116:  for name, report in chalkConfig.reportSpecs:
124:      chalkConfig.reportTemplates[templName].registerKeys()

commands/cmd_docker.nim
136:  let labelTemplate = chalkConfig.markTemplates[labelTemplName]
351:  if key notin chalkConfig.keyspecs:
423:  let labelTemplate = chalkConfig.markTemplates[labelTemplName]

commands/cmd_help.nim
377:      for k, v in chalkConfig.markTemplates:
379:      for k, v in chalkConfig.reportTemplates:
383:        if item notin chalkConfig.markTemplates and
384:           item notin chalkConfig.reportTemplates:
387:          if item in chalkConfig.markTemplates:
389:          if item in chalkConfig.reportTemplates:
397:      let theTemplate = chalkConfig.markTemplates[markTmplName]
403:      let theTemplate = chalkConfig.reportTemplates[repTmplName]

config.nim
57:  return chalkConfig.outputConfigs[getBaseCommandName()]
61:    outconf  = chalkConfig.outputConfigs[getBaseCommandName()]
64:  chalkConfig.markTemplates[tmplName]
68:    outconf  = chalkConfig.outputConfigs[getBaseCommandName()]
71:  chalkConfig.reportTemplates[tmplName]
115:  if name in chalkConfig.keyspecs: return some(chalkConfig.keyspecs[name])
118:  if name in chalkConfig.plugins:
119:    return some(chalkConfig.plugins[name])

plugins/codecDocker.nim
451:  if not value.checkAutoType(chalkConfig.keyspecs[chalkKey].`type`):

plugins/conffile.nim
15:  for k, v in chalkConfig.keySpecs:

plugins/externalTool.nim
110:  for k, v in chalkConfig.tools:

plugins/system.nim
254:      templateToUse = chalkConfig.reportTemplates[templateName]

plugins/techStackGeneric.nim
244:    for langName, val in chalkConfig.linguistLanguages:
247:    for key, val in chalkConfig.techStackRules:
314:  for key, val in chalkConfig.techStackRules:

reporting.nim
109:  for topic, spec in chalkConfig.reportSpecs:
123:    let templateToUse = chalkConfig.reportTemplates[spec.reportTemplate]

run_management.nim
23:  get[T](chalkConfig.`@@attrscope@@`, fqn)
26:  getOpt[T](chalkConfig.`@@attrscope@@`, fqn)

sinks.nim
164:      attrRoot = chalkConfig.`@@attrscope@@`
185:    attrRoot = if attr != nil: attr else: chalkConfig.`@@attrscope@@`
233:    attrRoot = chalkConfig.`@@attrscope@@`

Just to illustrate the progress: with this PR, nimble build succeeds if we manually replace c4autoconf.nim with these ~430 lines (which is ~15% of the length of the autogenerated one):

Click to expand
import std/[options, tables]
import pkg/[con4m, nimutils/box]

type KeyConfig* = ref object
  `@@ attrscope @@`*: AttrScope
  use*: bool
  order*: Option[int]

proc loadKeyConfig(scope: AttrScope): KeyConfig =
  result = new(KeyConfig)
  result.`@@ attrscope @@` = scope
  result.use = unpack[bool](scope.attrLookup("use").get())
  result.order = none(int)
  if "order" in scope.contents:
    var tmp = scope.attrLookup("order")
    if tmp.isSome():
      result.order = some(unpack[int](tmp.get()))

type OutputConfig* = ref object
  `@@ attrscope @@`*: AttrScope
  mark_template*: string
  report_template*: string
  doc*: Option[string]

proc loadOutputConfig(scope: AttrScope): OutputConfig =
  result = new(OutputConfig)
  result.`@@ attrscope @@` = scope
  result.mark_template = unpack[string](scope.attrLookup("mark_template").get())
  result.report_template = unpack[string](scope.attrLookup("report_template").get())
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

type LinguistLanguage* = ref object
  `@@ attrscope @@`*: AttrScope
  extension*: string

proc loadLinguistLanguage(scope: AttrScope): LinguistLanguage =
  result = new(LinguistLanguage)
  result.`@@ attrscope @@` = scope
  result.extension = unpack[string](scope.attrLookup("extension").get())

proc get_extension*(self: LinguistLanguage): string =
  return self.extension

type hostScope* = ref object
  `@@ attrscope @@`*: AttrScope
  filepaths*: Option[seq[string]]
  directories*: Option[seq[string]]
  process_names*: Option[seq[string]]
  strict*: bool

proc loadhostScope(scope: AttrScope): hostScope =
  result = new(hostScope)
  result.`@@ attrscope @@` = scope
  result.filepaths = none(seq[string])
  if "filepaths" in scope.contents:
    var tmp = scope.attrLookup("filepaths")
    if tmp.isSome():
      result.filepaths = some(unpack[seq[string]](tmp.get()))
  result.directories = none(seq[string])
  if "directories" in scope.contents:
    var tmp = scope.attrLookup("directories")
    if tmp.isSome():
      result.directories = some(unpack[seq[string]](tmp.get()))
  result.process_names = none(seq[string])
  if "process_names" in scope.contents:
    var tmp = scope.attrLookup("process_names")
    if tmp.isSome():
      result.process_names = some(unpack[seq[string]](tmp.get()))
  result.strict = unpack[bool](scope.attrLookup("strict").get())

proc get_filepaths*(self: hostScope): Option[seq[string]] =
  return self.filepaths

proc get_directories*(self: hostScope): Option[seq[string]] =
  return self.directories

proc get_process_names*(self: hostScope): Option[seq[string]] =
  return self.process_names

proc get_strict*(self: hostScope): bool =
  return self.strict

type MarkTemplate* = ref object
  `@@ attrscope @@`*: AttrScope
  keys*: OrderedTableRef[string, KeyConfig]
  shortdoc*: Option[string]
  doc*: Option[string]

proc loadMarkTemplate(scope: AttrScope): MarkTemplate =
  result = new(MarkTemplate)
  result.`@@ attrscope @@` = scope
  result.keys = new(OrderedTableRef[string, KeyConfig])
  if scope.contents.contains("key"):
    let objlist = scope.contents["key"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.keys[item] = loadKeyConfig(aOrS.get(AttrScope))
  result.shortdoc = none(string)
  if "shortdoc" in scope.contents:
    var tmp = scope.attrLookup("shortdoc")
    if tmp.isSome():
      result.shortdoc = some(unpack[string](tmp.get()))
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

type ReportTemplate* = ref object
  `@@ attrscope @@`*: AttrScope
  keys*: OrderedTableRef[string, KeyConfig]
  shortdoc*: Option[string]
  doc*: Option[string]

proc loadReportTemplate(scope: AttrScope): ReportTemplate =
  result = new(ReportTemplate)
  result.`@@ attrscope @@` = scope
  result.keys = new(OrderedTableRef[string, KeyConfig])
  if scope.contents.contains("key"):
    let objlist = scope.contents["key"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.keys[item] = loadKeyConfig(aOrS.get(AttrScope))
  result.shortdoc = none(string)
  if "shortdoc" in scope.contents:
    var tmp = scope.attrLookup("shortdoc")
    if tmp.isSome():
      result.shortdoc = some(unpack[string](tmp.get()))
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

type ToolInfo* = ref object
  `@@ attrscope @@`*: AttrScope
  enabled*: bool
  kind*: string
  priority*: int
  stop_on_success*: bool
  get_tool_location*: CallbackObj
  attempt_install*: CallbackObj
  get_command_args*: CallbackObj
  produce_keys*: CallbackObj
  doc*: Option[string]

proc loadToolInfo(scope: AttrScope): ToolInfo =
  result = new(ToolInfo)
  result.`@@ attrscope @@` = scope
  result.enabled = unpack[bool](scope.attrLookup("enabled").get())
  result.kind = unpack[string](scope.attrLookup("kind").get())
  result.priority = unpack[int](scope.attrLookup("priority").get())
  result.stop_on_success = unpack[bool](scope.attrLookup("stop_on_success").get())
  result.get_tool_location =
    unpack[CallbackObj](scope.attrLookup("get_tool_location").get())
  result.attempt_install =
    unpack[CallbackObj](scope.attrLookup("attempt_install").get())
  result.get_command_args =
    unpack[CallbackObj](scope.attrLookup("get_command_args").get())
  result.produce_keys = unpack[CallbackObj](scope.attrLookup("produce_keys").get())
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

type FileScope* = ref object
  `@@ attrscope @@`*: AttrScope
  regex*: string
  filepaths*: Option[seq[string]]
  excluded_filepaths*: Option[seq[string]]
  filetypes*: Option[seq[string]]
  excluded_filetypes*: Option[seq[string]]
  head*: int

proc loadFileScope(scope: AttrScope): FileScope =
  result = new(FileScope)
  result.`@@ attrscope @@` = scope
  result.regex = unpack[string](scope.attrLookup("regex").get())
  result.filepaths = none(seq[string])
  if "filepaths" in scope.contents:
    var tmp = scope.attrLookup("filepaths")
    if tmp.isSome():
      result.filepaths = some(unpack[seq[string]](tmp.get()))
  result.excluded_filepaths = none(seq[string])
  if "excluded_filepaths" in scope.contents:
    var tmp = scope.attrLookup("excluded_filepaths")
    if tmp.isSome():
      result.excluded_filepaths = some(unpack[seq[string]](tmp.get()))
  result.filetypes = none(seq[string])
  if "filetypes" in scope.contents:
    var tmp = scope.attrLookup("filetypes")
    if tmp.isSome():
      result.filetypes = some(unpack[seq[string]](tmp.get()))
  result.excluded_filetypes = none(seq[string])
  if "excluded_filetypes" in scope.contents:
    var tmp = scope.attrLookup("excluded_filetypes")
    if tmp.isSome():
      result.excluded_filetypes = some(unpack[seq[string]](tmp.get()))
  result.head = unpack[int](scope.attrLookup("head").get())

proc get_regex*(self: FileScope): string =
  return self.regex

proc get_filepaths*(self: FileScope): Option[seq[string]] =
  return self.filepaths

proc get_excluded_filepaths*(self: FileScope): Option[seq[string]] =
  return self.excluded_filepaths

proc get_filetypes*(self: FileScope): Option[seq[string]] =
  return self.filetypes

proc get_excluded_filetypes*(self: FileScope): Option[seq[string]] =
  return self.excluded_filetypes

proc get_head*(self: FileScope): int =
  return self.head

type TechStackRule* = ref object
  `@@ attrscope @@`*: AttrScope
  fileScope*: FileScope
  hostScope*: hostScope
  description*: string
  category*: string
  subcategory*: string

proc loadTechStackRule(scope: AttrScope): TechStackRule =
  result = new(TechStackRule)
  result.`@@ attrscope @@` = scope
  if scope.contents.contains("file_scope"):
    result.fileScope = loadFileScope(scope.contents["file_scope"].get(AttrScope))
  if scope.contents.contains("host_scope"):
    result.hostScope = loadhostScope(scope.contents["host_scope"].get(AttrScope))
  result.description = unpack[string](scope.attrLookup("description").get())
  result.category = unpack[string](scope.attrLookup("category").get())
  result.subcategory = unpack[string](scope.attrLookup("subcategory").get())

proc get_category*(self: TechStackRule): string =
  return self.category

proc get_subcategory*(self: TechStackRule): string =
  return self.subcategory

type PluginSpec* = ref object
  `@@ attrscope @@`*: AttrScope
  priority*: int
  ignore*: seq[string]
  codec*: bool
  pre_run_keys*: seq[string]
  artifact_keys*: seq[string]
  post_chalk_keys*: seq[string]
  post_run_keys*: seq[string]
  enabled*: bool
  overrides*: seq[string]
  doc*: Option[string]

proc loadPluginSpec(scope: AttrScope): PluginSpec =
  result = new(PluginSpec)
  result.`@@ attrscope @@` = scope
  result.priority = unpack[int](scope.attrLookup("priority").get())
  result.ignore = unpack[seq[string]](scope.attrLookup("ignore").get())
  result.codec = unpack[bool](scope.attrLookup("codec").get())
  result.pre_run_keys = unpack[seq[string]](scope.attrLookup("pre_run_keys").get())
  result.artifact_keys = unpack[seq[string]](scope.attrLookup("artifact_keys").get())
  result.post_chalk_keys =
    unpack[seq[string]](scope.attrLookup("post_chalk_keys").get())
  result.post_run_keys = unpack[seq[string]](scope.attrLookup("post_run_keys").get())
  result.enabled = unpack[bool](scope.attrLookup("enabled").get())
  result.overrides = unpack[seq[string]](scope.attrLookup("overrides").get())
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

proc get_priority*(self: PluginSpec): int =
  return self.priority

proc get_enabled*(self: PluginSpec): bool =
  return self.enabled

type ReportSpec* = ref object
  `@@ attrscope @@`*: AttrScope
  enabled*: bool
  report_template*: string
  sink_configs*: seq[string]
  use_when*: seq[string]
  doc*: Option[string]

proc loadReportSpec(scope: AttrScope): ReportSpec =
  result = new(ReportSpec)
  result.`@@ attrscope @@` = scope
  result.enabled = unpack[bool](scope.attrLookup("enabled").get())
  result.report_template = unpack[string](scope.attrLookup("report_template").get())
  result.sink_configs = unpack[seq[string]](scope.attrLookup("sink_configs").get())
  result.use_when = unpack[seq[string]](scope.attrLookup("use_when").get())
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))

type KeySpec* = ref object
  `@@ attrscope @@`*: AttrScope
  required_in_chalk_mark*: bool
  required_in_self_mark*: bool
  kind*: int
  never_early*: bool
  `type`*: Con4mType
  standard*: Option[bool]
  system*: bool
  conf_as_system*: bool
  codec*: bool
  value*: Option[Box]
  callback*: Option[CallbackObj]
  since*: Option[string]
  normalized_order*: int
  apply_substitutions*: bool
  doc*: Option[string]
  shortdoc*: Option[string]

proc loadKeySpec(scope: AttrScope): KeySpec =
  result = new(KeySpec)
  result.`@@ attrscope @@` = scope
  result.required_in_chalk_mark =
    unpack[bool](scope.attrLookup("required_in_chalk_mark").get())
  result.required_in_self_mark =
    unpack[bool](scope.attrLookup("required_in_self_mark").get())
  result.kind = unpack[int](scope.attrLookup("kind").get())
  result.never_early = unpack[bool](scope.attrLookup("never_early").get())
  result.`type` = unpack[Con4mType](scope.attrLookup("type").get())
  result.standard = none(bool)
  if "standard" in scope.contents:
    var tmp = scope.attrLookup("standard")
    if tmp.isSome():
      result.standard = some(unpack[bool](tmp.get()))
  result.system = unpack[bool](scope.attrLookup("system").get())
  result.conf_as_system = unpack[bool](scope.attrLookup("conf_as_system").get())
  result.codec = unpack[bool](scope.attrLookup("codec").get())
  result.value = none(Box)
  if "value" in scope.contents:
    var tmp = scope.attrLookup("value")
    if tmp.isSome():
      result.value = some(unpack[Box](tmp.get()))
  result.callback = none(CallbackObj)
  if "callback" in scope.contents:
    var tmp = scope.attrLookup("callback")
    if tmp.isSome():
      result.callback = some(unpack[CallbackObj](tmp.get()))
  result.since = none(string)
  if "since" in scope.contents:
    var tmp = scope.attrLookup("since")
    if tmp.isSome():
      result.since = some(unpack[string](tmp.get()))
  result.normalized_order = unpack[int](scope.attrLookup("normalized_order").get())
  result.apply_substitutions =
    unpack[bool](scope.attrLookup("apply_substitutions").get())
  result.doc = none(string)
  if "doc" in scope.contents:
    var tmp = scope.attrLookup("doc")
    if tmp.isSome():
      result.doc = some(unpack[string](tmp.get()))
  result.shortdoc = none(string)
  if "shortdoc" in scope.contents:
    var tmp = scope.attrLookup("shortdoc")
    if tmp.isSome():
      result.shortdoc = some(unpack[string](tmp.get()))

type ChalkConfig* = ref object
  `@@ attrscope @@`*: AttrScope
  keyspecs*: OrderedTableRef[string, KeySpec]
  plugins*: OrderedTableRef[string, PluginSpec]
  markTemplates*: OrderedTableRef[string, MarkTemplate]
  reportTemplates*: OrderedTableRef[string, ReportTemplate]
  outputConfigs*: OrderedTableRef[string, OutputConfig]
  reportSpecs*: OrderedTableRef[string, ReportSpec]
  tools*: OrderedTableRef[string, ToolInfo]
  techStackRules*: OrderedTableRef[string, TechStackRule]
  linguist_languages*: OrderedTableRef[string, LinguistLanguage]

proc loadChalkConfig*(scope: AttrScope): ChalkConfig =
  result = new(ChalkConfig)
  result.`@@ attrscope @@` = scope
  result.keyspecs = new(OrderedTableRef[string, KeySpec])
  if scope.contents.contains("keyspec"):
    let objlist = scope.contents["keyspec"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.keyspecs[item] = loadKeySpec(aOrS.get(AttrScope))
  result.plugins = new(OrderedTableRef[string, PluginSpec])
  if scope.contents.contains("plugin"):
    let objlist = scope.contents["plugin"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.plugins[item] = loadPluginSpec(aOrS.get(AttrScope))
  result.markTemplates = new(OrderedTableRef[string, MarkTemplate])
  if scope.contents.contains("mark_template"):
    let objlist = scope.contents["mark_template"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.markTemplates[item] = loadMarkTemplate(aOrS.get(AttrScope))
  result.reportTemplates = new(OrderedTableRef[string, ReportTemplate])
  if scope.contents.contains("report_template"):
    let objlist = scope.contents["report_template"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.reportTemplates[item] = loadReportTemplate(aOrS.get(AttrScope))
  result.outputConfigs = new(OrderedTableRef[string, OutputConfig])
  if scope.contents.contains("outconf"):
    let objlist = scope.contents["outconf"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.outputConfigs[item] = loadOutputConfig(aOrS.get(AttrScope))
  result.reportSpecs = new(OrderedTableRef[string, ReportSpec])
  if scope.contents.contains("custom_report"):
    let objlist = scope.contents["custom_report"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.reportSpecs[item] = loadReportSpec(aOrS.get(AttrScope))
  result.tools = new(OrderedTableRef[string, ToolInfo])
  if scope.contents.contains("tool"):
    let objlist = scope.contents["tool"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.tools[item] = loadToolInfo(aOrS.get(AttrScope))
  result.techStackRules = new(OrderedTableRef[string, TechStackRule])
  if scope.contents.contains("tech_stack_rule"):
    let objlist = scope.contents["tech_stack_rule"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.techStackRules[item] = loadTechStackRule(aOrS.get(AttrScope))
  result.linguist_languages = new(OrderedTableRef[string, LinguistLanguage])
  if scope.contents.contains("linguist_language"):
    let objlist = scope.contents["linguist_language"].get(AttrScope)
    for item, aOrS in objlist.contents:
      result.linguist_languages[item] = loadLinguistLanguage(aOrS.get(AttrScope))

Testing

Hopefully the existing tests are sufficient.

ee7 avatar Mar 12 '24 13:03 ee7