Skip to content

[Query] Input Sources

github-actions[bot] edited this page Sep 3, 2026 · 1 revision

Generated from 'wiki-query.ts' on 2026-08-29, 17:39:04 UTC (v2.15.8), please do not edit directly.

Input Sources Query [overview]

Classify the input sources of function calls
This query is requested with the type input-sources.
Run in the REPL: :query @input-sources (<criterion>) <code | file://path>

Given a slicing criterion to something like a function call, flowR classifies the types of all input sources (e.g., arguments).

To exemplify the query, consider the following code:

f <- function(x) {
	x <- x * 2
	print(x)
}

If you are interested in the input-sources of the print call, you can use:

[
  {
    "type": "input-sources",
    "criterion": "3@print"
  }
]

(This can be shortened to @input-sources (3@print) "f <- function(x) {\n x <- x * 2\n print(x)\n}" when used with the REPL command :query).

Results (prettified and summarized):

Query: input-sources (3 ms)
   ╰ Input Sources for 3@print
           ╰ 3.15 (id: 11), type: ["param","const","dconst"], trace: alias
All queries together required ≈3 ms (1ms accuracy, total 4 ms)

Show Detailed Results as Json

The analysis required 3.6 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.

{
  "input-sources": {
    ".meta": {
      "timing": 3
    },
    "results": {
      "3@print": [
        {
          "id": 11,
          "types": [
            "param",
            "const",
            "dconst"
          ],
          "trace": "alias"
        }
      ]
    }
  },
  ".meta": {
    "timing": 3
  }
}

Some objects are handed to the code by a framework rather than defined in it, like the input of a shiny server function. The InputClassifierConfig::linkedObjects configuration lists them, so that reads of such an object (and of its fields) classify as user input instead of stopping at a InputType::Parameter:

server <- function(input, output, session) {
	system(paste("convert", input$file))
}
[
  {
    "type": "input-sources",
    "criterion": "2@system"
  }
]

(This can be shortened to @input-sources (2@system) "server <- function(input, output, session) {\n system(paste("convert", input$file))\n}" when used with the REPL command :query).

Results (prettified and summarized):

Query: input-sources (3 ms)
   ╰ Input Sources for 2@system
           ╰ 2.16-43 (id: 18), type: ["const","param","unknown","dconst"], trace: known
All queries together required ≈3 ms (1ms accuracy, total 4 ms)

Show Detailed Results as Json

The analysis required 3.7 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.

{
  "input-sources": {
    ".meta": {
      "timing": 3
    },
    "results": {
      "2@system": [
        {
          "id": 18,
          "types": [
            "const",
            "param",
            "unknown",
            "dconst"
          ],
          "trace": "known"
        }
      ]
    }
  },
  ".meta": {
    "timing": 3
  }
}

Every LinkedInputObject names the object, the InputType to use for it, and optionally the parameters the binding function has to declare as well (LinkedInputObject::withParams) - shiny's input only counts as such if the function also takes an output, so that an ordinary function with a parameter named input is left alone. Where the framework is handed the function instead of the code naming it, a LinkedInputEntryPoint is exact: it says which object goes to which parameter by position, just like R does, so shinyApp(ui, function(i, o, s)) works no matter what those parameters are called. With LinkedInputObject::declaredBy a read even links back to its definition - the textInput("n", …) behind an input$n shows up as InputSource::declaredAt.

You do not have to pass any of this per query: the inputSources section of flowR's configuration file carries the same shape and is added to what flowR already knows, so your framework joins shiny instead of replacing it (and specializeConfig can scope it to one ProjectKind). Functions may be written as plain fn or namespaced pkg::fn strings; a bare call only counts as the namespaced one while that package is attached, exactly as R would resolve it.

{
  "inputSources": {
    "user": [
      "myframework::read_form"
    ],
    "linkedObjects": [
      {
        "name": "ctx",
        "type": "user",
        "declaredBy": {
          "calls": [
            "myframework::field"
          ],
          "argName": "id",
          "argIdx": 0
        }
      }
    ],
    "linkedEntryPoints": [
      {
        "call": "myframework::serve",
        "argName": "handler",
        "argIdx": 0,
        "params": [
          "ctx",
          null
        ]
      }
    ]
  }
}
Implementation Details

Responsible for the execution of the Input Sources Query query is executeInputSourcesQuery in ./src/queries/catalog/input-sources-query/input-sources-query-executor.ts.

Clone this wiki locally