code: def lint_not_used_params(
      self,
      rule,
      valid_names={
          "input",
          "output",
          "log",
          "params",
          "wildcards",
          "threads",
          "resources",
      },
      regex=re.compile(f"{{(?P<name>{NAME_PATTERN}).*?}}"),
  ):
      if rule.shellcmd:
          for match in regex.finditer(rule.shellcmd):
              name = match.group("name")
  
              before = match.start() - 1
              after = match.end()
  
              if name not in valid_names and (
                  not (before >= 0 and after < len(rule.shellcmd))
                  or (
                      rule.shellcmd[before] != "{"
                      and rule.shellcmd[after] != "}"
                  )
              ):
                  yield Lint(
                      title="Shell command directly uses variable {} from outside of the rule".format(
                          name
                      ),
                      body="It is recommended to pass all files as input and output, and non-file parameters "
                      "via the params directive. Otherwise, provenance tracking is less accurate.",
                      links=[links.params],
                  )
  
file_path: snakemake/snakemake/linting/rules.py
imports: from itertools import chain
  import re
  import sys
  from snakemake.io import is_flagged
  from snakemake.linting import Linter, Lint, links, NAME_PATTERN
label_desc: Use image node_id 5 for calling the RuleLinter obj's underlying member method code with example usage: obj.lint_not_used_params(rule, valid_names, regex) without return types