Skip to content

[Query] Linter

github-actions[bot] edited this page Jul 21, 2026 · 1 revision

This document was generated from 'src/documentation/wiki-query.ts' on 2026-07-20, 17:48:27 UTC presenting an overview of flowR's query API (v2.12.3). Please do not edit this file/wiki page directly.

Linter Query [overview]

Lints a given R script for common issues.
This query is requested with the type linter.
Run in the REPL: :query @linter [rules:<r1>,<r2>,...] [format:<fmt>] <code | file://path>

This query lints a given R script for common issues, such as missing files, unused variables, and more.

In other words, if you have a script simply reading: read.csv("i_do_not_exist.csv"), the following query returns all smells detected:

[ { "type": "linter" } ]

(This can be shortened to @linter when used with the REPL command :query).

Results (prettified and summarized):

Query: linter (55 ms)
   ╰ Deprecated Functions (deprecated-functions): no findings
   ╰ File Path Validity (file-path-validity):
       ╰ certain:
           ╰ Path i_do_not_exist.csv at 1.1-30
       ╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 2, processTimeMs: 1
   ╰ Seeded Randomness (seeded-randomness): no findings
   ╰ Absolute Paths (absolute-file-paths): no findings
   ╰ Unused Definitions (unused-definitions): no findings
   ╰ Network Functions (network-functions): no findings
   ╰ Dataframe Access Validation (dataframe-access-validation): no findings
   ╰ Dead Code (dead-code): no findings
   ╰ Useless Loops (useless-loop): no findings
   ╰ Problematic inputs (problematic-inputs): no findings
   ╰ Stop without call.=False argument (stop-call): no findings
   ╰ Roxygen Arguments (roxygen-arguments): no findings
   ╰ No Leaked Credentials (no-leaked-credentials): no findings
   ╰ Undefined Symbol (undefined-symbol): no findings
All queries together required ≈55 ms (1ms accuracy, total 56 ms)

Show Detailed Results as Json

The analysis required 55.9 ms (including parsing and normalization and the query) within the generation environment.

In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the Interface wiki page for more information on how to get those.

{
  "linter": {
    "results": {
      "deprecated-functions": {
        "results": [],
        ".meta": {
          "totalCalls": 0,
          "totalFunctionDefinitions": 0,
          "searchTimeMs": 10,
          "processTimeMs": 9
        }
      },
      "file-path-validity": {
        "results": [
          {
            "involvedId": 3,
            "loc": [
              1,
              1,
              1,
              30
            ],
            "filePath": "i_do_not_exist.csv",
            "certainty": "certain"
          }
        ],
        ".meta": {
          "totalReads": 1,
          "totalUnknown": 0,
          "totalWritesBeforeAlways": 0,
          "totalValid": 0,
          "searchTimeMs": 2,
          "processTimeMs": 1
        }
      },
      "seeded-randomness": {
        "results": [],
        ".meta": {
          "consumerCalls": 0,
          "callsWithFunctionProducers": 0,
          "callsWithAssignmentProducers": 0,
          "callsWithNonConstantProducers": 0,
          "callsWithOtherBranchProducers": 0,
          "searchTimeMs": 0,
          "processTimeMs": 1
        }
      },
      "absolute-file-paths": {
        "results": [],
        ".meta": {
          "totalConsidered": 1,
          "totalUnknown": 0,
          "searchTimeMs": 0,
          "processTimeMs": 1
        }
      },
      "unused-definitions": {
        "results": [],
        ".meta": {
          "totalConsidered": 0,
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "network-functions": {
        "results": [],
        ".meta": {
          "totalCalls": 0,
          "totalFunctionDefinitions": 0,
          "searchTimeMs": 0,
          "processTimeMs": 1
        }
      },
      "dataframe-access-validation": {
        "results": [],
        ".meta": {
          "numOperations": 0,
          "numAccesses": 0,
          "totalAccessed": 0,
          "searchTimeMs": 0,
          "processTimeMs": 1
        }
      },
      "dead-code": {
        "results": [],
        ".meta": {
          "searchTimeMs": 1,
          "processTimeMs": 0
        }
      },
      "useless-loop": {
        "results": [],
        ".meta": {
          "numOfUselessLoops": 0,
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "problematic-inputs": {
        "results": [],
        ".meta": {
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "stop-call": {
        "results": [],
        ".meta": {
          "consideredNodes": 0,
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "roxygen-arguments": {
        "results": [],
        ".meta": {
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "no-leaked-credentials": {
        "results": [],
        ".meta": {
          "totalChecked": 0,
          "searchTimeMs": 0,
          "processTimeMs": 0
        }
      },
      "undefined-symbol": {
        "results": [],
        ".meta": {
          "totalFunctionCalls": 1,
          "totalVariableUses": 0,
          "suppressed": {
            "installed": 0,
            "loadedPackage": 0,
            "enclosingScope": 0,
            "nonStandardEval": 0,
            "subscript": 0
          },
          "searchTimeMs": 0,
          "processTimeMs": 27
        }
      }
    },
    ".meta": {
      "timing": 55
    }
  },
  ".meta": {
    "timing": 55
  }
}

You can also configure which rules to apply and what settings to use for these rules:

[ { "type": "linter",   "rules": [ "file-path-validity" ] } ]

(This can be shortened to @linter rules:file-path-validity "read.csv("i_do_not_exist.csv")" when used with the REPL command :query).

Results (prettified and summarized):

Query: linter (15 ms)
   ╰ File Path Validity (file-path-validity):
       ╰ certain:
           ╰ Path i_do_not_exist.csv at 1.1-30
       ╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 15, processTimeMs: 0
All queries together required ≈15 ms (1ms accuracy, total 16 ms)

Show Detailed Results as Json

The analysis required 16.2 ms (including parsing and normalization and the query) within the generation environment.

In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the Interface wiki page for more information on how to get those.

{
  "linter": {
    "results": {
      "file-path-validity": {
        "results": [
          {
            "involvedId": 3,
            "loc": [
              1,
              1,
              1,
              30
            ],
            "filePath": "i_do_not_exist.csv",
            "certainty": "certain"
          }
        ],
        ".meta": {
          "totalReads": 1,
          "totalUnknown": 0,
          "totalWritesBeforeAlways": 0,
          "totalValid": 0,
          "searchTimeMs": 15,
          "processTimeMs": 0
        }
      }
    },
    ".meta": {
      "timing": 15
    }
  },
  ".meta": {
    "timing": 15
  }
}

We welcome any feedback and suggestions for new rules on this (consider opening a new issue).

Implementation Details

Responsible for the execution of the Linter Query query is executeDependenciesQuery in ./src/queries/catalog/linter-query/linter-query-executor.ts.

Clone this wiki locally