Skip to content

[Linting Rule] Syntactically Valid

github-actions[bot] edited this page Aug 20, 2026 · 1 revision

Generated from 'src/documentation/wiki-linter.ts' on 2026-08-16, 06:15:25 UTC (v2.13.16), so please do not edit it directly.

Syntactically Valid [overview]

bug quickfix robustness

This rule is a best-effort rule.

Checks whether the code is free of syntax errors, using the configured (error-tolerant) parser, and offers extensible quick-fixes to repair them.
This linting rule is implemented in src/linter/rules/syntactically-valid.ts.

Configuration

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

  • disabledFixes
    Names of auto-fix patterns to disable (default none).
  • preferFix
    Preferred FixDirection ; each error gets a single fix, favouring a candidate of this direction.

Examples

x <- c(1, 2

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

[ { "type": "linter",   "rules": [ { "name": "syntactically-valid",     "config": {} } ] } ]

Results (prettified and summarized):

Query: linter (1 ms)
   ╰ Syntactically Valid (syntactically-valid):
       ╰ certain:
           ╰ Missing ) at 1.12-11 (1 quick fix(es) available)
       ╰ Metadata: parser: "tree-sitter", errors: 1, fixable: 1, searchTimeMs: 0, processTimeMs: 1
All queries together required ≈1 ms (1ms accuracy, total 2 ms)

Show Detailed Results as Json

The analysis required 1.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": {
      "syntactically-valid": {
        "results": [
          {
            "certainty": "certain",
            "kind": "missing",
            "loc": [
              1,
              12,
              1,
              11
            ],
            "message": "Missing `)`",
            "quickFix": [
              {
                "type": "replace",
                "loc": [
                  1,
                  12,
                  1,
                  11
                ],
                "description": "Insert missing `)`",
                "replacement": ")"
              }
            ]
          }
        ],
        ".meta": {
          "parser": "tree-sitter",
          "errors": 1,
          "fixable": 1,
          "searchTimeMs": 0,
          "processTimeMs": 1
        }
      }
    },
    ".meta": {
      "timing": 1
    }
  },
  ".meta": {
    "timing": 1
  }
}

Additional Examples

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

Test Case: valid code has no syntax errors

Given the following input:

x <- c(1, 2)
print(x)

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: missing closing parenthesis

Given the following input:

x <- c(1, 2

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'missing',
message:   'Missing `)`',
loc:       [1, 12, 1, 11],
quickFix:  [{ type: 'replace', loc: [1, 12, 1, 11], description: 'Insert missing `)`', replacement: ')' }]

See here for the test-case implementation.

Test Case: unbalanced brace

Given the following input:

{ 1

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `{ 1`',
loc:       [1, 1, 1, 3],
quickFix:  [{ type: 'replace', loc: [1, 4, 1, 3], description: 'Add missing closing `}`', replacement: '}' }]

See here for the test-case implementation.

Test Case: dangling assignment operator

Given the following input:

x <-

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'missing',
message:   'Missing `identifier`',
loc:       [1, 5, 1, 4],
quickFix:  [{ type: 'remove', loc: [1, 3, 1, 4], description: 'Remove the dangling `<-`' }]

See here for the test-case implementation.

Test Case: dangling operator prefers the add direction when configured

// preferFix flips the direction: with add, the same error offers the NULL placeholder instead of the removal

Given the following input:

x <-

And using the following configuration:

{ preferFix: 'add' }

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'missing',
message:   'Missing `identifier`',
loc:       [1, 5, 1, 4],
quickFix:  [{ type: 'replace', loc: [1, 5, 1, 4], description: 'Insert placeholder `NULL`', replacement: ' NULL' }]

See here for the test-case implementation.

Test Case: fuzzy-completes an unfinished operator

Given the following input:

a %in b

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `%in b`',
loc:       [1, 3, 1, 7],
quickFix:  [{ type: 'replace', loc: [1, 3, 1, 5], description: 'Complete operator to `%in%`', replacement: '%in%' }]

See here for the test-case implementation.

Test Case: typographic quotes

// what a word processor or a PDF leaves behind

Given the following input:

x <-hi

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `“`',
loc:       [1, 6, 1, 6],
quickFix:  [{ type: 'replace', loc: [1, 6, 1, 6], description: 'Replace the typographic quote with a straight one', replacement: '"' }]
			}, {
certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `”`',
loc:       [1, 9, 1, 9],
quickFix:  [{ type: 'replace', loc: [1, 9, 1, 9], description: 'Replace the typographic quote with a straight one', replacement: '"' }]

See here for the test-case implementation.

Test Case: comment-out fallback for a stray token

// a stray token no other pattern can repair falls back to commenting it out

Given the following input:

,

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `,`',
loc:       [1, 1, 1, 1],
quickFix:  [{ type: 'replace', loc: [1, 1, 1, 1], description: 'Comment out the offending code', replacement: '# ,' }]

See here for the test-case implementation.

Test Case: disabling a fix drops its suggestion

// disabling the only applicable pattern leaves the error reported but without a quick-fix

Given the following input:

,

And using the following configuration:

{ disabledFixes: ['comment-out'] }

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `,`',
loc:       [1, 1, 1, 1],
quickFix:  undefined

See here for the test-case implementation.

Test Case: stray closing parenthesis

// a copy that stopped short of the opening bracket leaves closers that close nothing

Given the following input:

x <- c(1, 2))

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `)`',
loc:       [1, 13, 1, 13],
quickFix:  [{ type: 'remove', loc: [1, 13, 1, 13], description: 'Remove the stray `)`' }]

See here for the test-case implementation.

Test Case: copied REPL prompt

// lines copied out of the REPL keep their prompt

Given the following input:

> x <- 1

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `>`',
loc:       [1, 1, 1, 1],
quickFix:  [{ type: 'remove', loc: [1, 1, 1, 1], description: 'Remove the copied `>` prompt' }]

See here for the test-case implementation.

Test Case: pasted console output

// printed results pasted back into the script: the whole line is missing its #

Given the following input:

[1] 1 2 3

We expect the linter to report the following:

				certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `[`',
loc:       [1, 1, 1, 1],
quickFix:  [{ type: 'replace', loc: [1, 1, 1, 0], description: 'Comment out the pasted console output', replacement: '# ' }]
			}, {
certainty: LintingResultCertainty.Certain,
kind:      'error',
message:   'Unexpected `]`',
loc:       [1, 3, 1, 3],
quickFix:  [{ type: 'replace', loc: [1, 1, 1, 0], description: 'Comment out the pasted console output', replacement: '# ' }]

See here for the test-case implementation.

Clone this wiki locally