Skip to content

[Linting Rule] Namespace Access

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

Generated from 'wiki-linter.ts' on 2026-09-10, 07:04:46 UTC (v2.15.8), do not edit directly.

Namespace Access Validity [overview]

bug

This rule is a best-effort rule.

Flags pkg:::name where name is actually exported by pkg (so :: would do), and pkg::name where the signature database knows name is not exported (which fails at runtime in R). Stays silent whenever the database has no definite answer for the name.
This linting rule is implemented in src/linter/rules/namespace-access.ts.

Configuration

Linting rules can be configured by passing a configuration object to the linter query as shown in the example below. The namespace-access rule accepts the following configuration options:

Examples

dplyr:::filter(df, x > 1)

The linting query can be used to run this rule on the above example:

[ { "type": "linter",   "rules": [ { "name": "namespace-access",     "config": {} } ] } ]

Results (prettified and summarized):

Query: linter (2 ms)
   ╰ Namespace Access Validity (namespace-access):
       ╰ certain:
           ╰ dplyr:::filter at 1.1-25\

Show Detailed Results as Json

The analysis ran (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": {
      "namespace-access": {"results":[{"certainty":"certain","involvedId":0,"loc":[1,1,1,25],"pkg":"dplyr","name":"filter","kind":"unnecessary-internal"}],".meta":{"unresolved":0}}
    },
    ".meta": {}
  },
  ".meta": {}
}

Additional Examples

These examples are synthesized from the test cases in: test/functionality/linter/lint-namespace-access.test.ts

Test Case: unnecessary `:::` on an exported name

Given the following input:

stats:::median

And using the following configuration:

{sigDb: sigDbWithNames('stats', {median: true})}

We expect the linter to report the following:

  • certain at 1.1-1.14: pkg = 'stats', name = 'median', kind = 'unnecessary-internal'

See here for the test-case implementation.

Test Case: `::` on a name that is not exported

Given the following input:

stats::C_cor

And using the following configuration:

{sigDb: sigDbWithNames('stats', {C_cor: false})}

We expect the linter to report the following:

  • certain at 1.1-1.12: pkg = 'stats', name = 'C_cor', kind = 'not-exported'

See here for the test-case implementation.

Test Case: unnecessary `:::` in a call

Given the following input:

stats:::median(1:3)

And using the following configuration:

{sigDb: sigDbWithNames('stats', {median: true})}

We expect the linter to report the following:

  • certain at 1.1-1.19: pkg = 'stats', name = 'median', kind = 'unnecessary-internal'

See here for the test-case implementation.

Test Case: `::` on a non-exported name in a call

Given the following input:

stats::C_cor(1:3)

And using the following configuration:

{sigDb: sigDbWithNames('stats', {C_cor: false})}

We expect the linter to report the following:

  • certain at 1.1-1.17: pkg = 'stats', name = 'C_cor', kind = 'not-exported'

See here for the test-case implementation.

Test Case: `::` on an exported name is fine

Given the following input:

stats::median

And using the following configuration:

{sigDb: sigDbWithNames('stats', {median: true})}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Test Case: `:::` on a genuinely internal name is fine

Given the following input:

stats:::C_cor

And using the following configuration:

{sigDb: sigDbWithNames('stats', {C_cor: false})}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Test Case: unknown package is not flagged

Given the following input:

notAPackage:::secret

And using the following configuration:

{sigDb: sigDbWithNames('stats', {median: true})}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Test Case: name absent from the database is not flagged

Given the following input:

stats:::undocumentedInternal

And using the following configuration:

{sigDb: controlledSigDb('stats', ['median'])}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Test Case: `::` on a name absent from the database is not flagged either

Given the following input:

stats::undocumentedInternal

And using the following configuration:

{sigDb: controlledSigDb('stats', ['median'])}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Test Case: no signature database mounted

Given the following input:

stats:::median

And using the following configuration:

{noSigDb: true}

We expect the linter to report the following:

  • no lints

See here for the test-case implementation.

Clone this wiki locally