Skip to content
| Marketplace
Sign in
Visual Studio Code>Linters>Dryer LintNew to Visual Studio Code? Get it now.
Dryer Lint

Dryer Lint

Paul Wintz

|
735 installs
| (2) | Free
Regex-based linting for any language. Based on relint by n0brain3r.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Dryer Lint: A Do-Regex-Yourself (DRY) Linter Extension for VS Code

Dryer Lint Logo

Dryer Lint is a language- and framework-agnostic linter for VS Code. It is designed to

  • allow syntax checking for programming languages that do not yet have their own specialized linters
  • define user-specific lint rules for a given project or code style.
  • Enable automated fixes to rule violations.

Dryer Link is available in the VS Code Extension Marketplace and GitHub.

Dryer Lint is based on the relint extension by Ryan Blonna (GitHub user n0bra1n3r).

Features

Dryer Lint produces configurable diagnostics for rule violations, each of which are described by a regular expression. Rules can also be assigned fixes that define replacements for rule violations. The behavior similar to VS Code's built-in regex find-and-replace functionality.

Usage Guide

Dryer Lint rules are created by adding them to .vscode/settings.json within your workspace.
Rules are grouped into one or more "rule sets". For each rule set, you can set one or more languages where the rule applies and a file glob (such as **/settings.json). Here is an example:

"dryerLint.ruleSets": {
    "Example Rule Set 1": {
        // Set the name of the languages where your rules apply
        "language": "c++",
        // Set a file glob (optional)
        "glob": "**/filename.c",
        // Set a list of rules.
        "rules": {
            "No apples or oranges. Only bananas": {
                // "pattern" is a JavaScript regular expression that shows diagnostic when matched
                "pattern": "(apple|orange)",
                // "message" is a string to show in the "Problems" VS Code panel or other places that diagnostics are shown.
                "message": "Don't use apples or oranges. Only bananas!",
                // "fix" (optional) is a string to replace the matched pattern.
                "fix": "banana",
                // "severity" (optional) is a string that must contain one of these values: "Hint", "Information", "Warning", or "Error". The default is "Warning".
                "severity": "Error",
                // "maxLines" (optional) is a positive integer that sets the max number of lines that the pattern is checked against at one time. The default is 1.
                "maxLines": 2, 
                // "caseInsensitive" (optional) is a boolean value that sets whether the regular expression uses the case insensitive flag "i". Default is false. 
                "caseInsensitive": true
            },
        }
    }, 
    "Example Rule Set 2": {
        "language": ["javascript", "typescript"],
        "rules": [
            {
                "name": "Rule 1",
                // ...
            },
            {
                "name": "Rule 2",
                // ...
            }
        ]
    },
    // ...
}

The following animation shows errors diagnostics added by Dryer Lint, matching the above rule, and quick actions used to apply the replacement “fix”. In the first step, an individual rule violation is selected and fixed. In the second step, multiple rule violations are selected in the text and a “Fix all” option is used to fix all of them in a single step.

Dryer Lint Animation

In this animation, the highlighting and inline display of error messages is achieved with Error Lens extension. We highly recommend the use of Error Lens with Dryer Lint.

To apply all of the fixes in the active editor at once (or, as many as possible that don't overlap), run "Dryer Lint: Fix All" from the VS Code command pallet.

screenshot of "fix all" command in command pallet

Writing Regular Expressions for Dryer Lint

Dryer Lint uses JavaScript regular expressions the Regex+ package for extended functionality and the following flags are always enabled:

  • g flag: Global matching (rules will match all violations in a line, instead only the first).
  • m flag: Multiline mode.
  • v flag: Enables "upgraded Unicode features", improved character classes, and stricter syntax. Can be disabled for backward compatibility by switching to the "legacy" regex engine.

The following flags are used if enabled in a rule's settings:

  • i flag: Ignore case. Off by default.
  • x flag: Ignore white space in pattern string. Off by default. (Simulated by Regex+)

More details are in the sections below.

A great tool for learning regex and writing and testing rules is https://regex101.com/. Regex101.com allows you to save a regular expression. You can then place a link to the saved regex so you can return to it in the future.

"\"l\" instead of \"\\ell\"": {
    // Link: https://regex101.com/r/QsDziM/latest
    // Match any single letter "l" that is not part of a word or wrapped in "\textsc{...}".
    "pattern": "(?<![a-zA-Z]|\\\\textsc\\{)l(?=[ _\\r\\n]|\\W)",
    "message": "Avoid \"l\" as a symbol. Use \"\\ell\" instead.",
    "severity": "Warning",
    "fix": "\\ell"
}

(See the section “Escaping Regular Expressions”, below, regarding copying expression from regex101.com into settings JSON file.)

Regex Flags

In Dryer Lint, all regex searches use the g flag (to find multiple matches instead of only the first) and the m flag (so that ^ matches the start of each line and $ matches the end of each line). If "caseInsensitive": true for a given rule, then the i flag is also used.

Dryer Lint also uses the v regex flag for "upgraded Unicode support".

Regex+: Expanded Regular Expression Syntax

Dryer Lint uses the Regex+ JavaScript package as its regex processing engine. Regex+ requires stricter syntax for regular expressions while adding many features to the built-in JavaScript engine. In particular, Regex+ uses the for expanded regular expression pattern definitions in JavaScript.

which provides many new regex features, including

  • Possessive quantifiers ("*+", "++", and "?") to block a quantifier from backtracking (or "returning characters"). Thus, "a*+" means
  • Ignores white space in patterns and allows for comments.
  • Subroutines (using a group subpattern using \g<groupname>)
  • Subroutine definition groups (i.e., using (?(DEFINE) ... ))
  • Atomic groups to block backtracking to before the start of the group (can improve performance).

Matching Line Breaks

By default, each regex rule is applied to a single line at a time, in which case ^ matches the start of a line and $ matches the end. When maxLines is more than 1 (the default), however, each regex searches over the given number lines. Since the m flag is used, ^ matches the start of each line and $ matches the end of each line.

Group Replacements in "fix" and "message" Properties

In each rule definition, the "fix" and "message" fields can use replacements from the matched Regex groups. The string $0 is replaced by the entire match, $1 is replaced with the contents of the first group capture, and "$2" is replaced with the second, and so on. The following is an example of a rule for LaTeX, where the first group (cref|eqref|ref|cite) is substituted into the error message.

"Empty Reference or Citation": {
    // Check for \cref{}, \cite{}, \ref{}, or \eqref{} occurring without arguments.
    "message": "Empty \\$1{}.",
    "pattern": "\\\\(cref|eqref|ref|cite)\\{\\s*\\}",
    "severity": "Error"
},

The resulting error message from

\cite{}

is “Empty \cite{}."

Escaping Regular Expressions

In JSON, the backslash character \ is used to escape other characters, so, for example, \t is a tab character, \n is a new line character, and (critically) \\ is a backslash. Backslashes are used extensively in regular expressions. To write regex in JSON, replace every occurrence of \ with \\.

There are several VS Code extensions that provide this functionality. I use vscode-json.

Disable/Enable Dryer Lint via Inline Comment

You can disable Dryer Lint for portions of a file using an inline comment such as (in C++):

// dryer-lint: disable

The following comments also disable Dryer Lint:

// dryer-lint: disabled
// dryer-lint: enable=false
// dryer-lint: enabled=false

To re-enable Dryer Lint, use any of the following:

// dryer-lint: enable
// dryer-lint: enabled
// dryer-lint: enable=true
// dryer-lint: enabled=true

The inline comment must be the only contents of the line except for empty space.

The inline comment characters for the following languages are recognized:

    c: "//",
    cpp: "//",
    java: "//",
    javascript: "//",
    latex: "%",
    python: "#",
    ruby: "#",
    shellscript: "#",
    typescript: "//",

If a language is not recognized, then lines starting with // or # are treated as comments for the purpose of toggling Dryer Lint on and off.

Disable/Enable Specific Rule Sets via Inline Comment

In addition to enabling or disabling Dryer Lint completely, you can also turn specific rule sets on and off. The comment syntax is identical, except it is followed by the name of a rule set in quotes. E.g., to disable a rule set named "my cool rulz", use

// dryer-lint: disable "my cool rulz"

NOTE: If you have disabled Dryer Lint using

// dryer-lint: disabled

then all rules are disabled until

// dryer-lint: enabled

occurs (or an equivalent). Placing

// dryer-lint: enabled "my cool rulz"

in a section of code where Dryer Lint is disabled will not cause "my cool rulz" rules to become active again until Dryer Lint is reenabled.

More examples

The following is a simple configuration that issues diagnostics for maximum characters exceeded in a line:

{
    ...
    "dryerLint.ruleSets": {
        "Max column width": {
            "language": ["python", "javascript", "typescript"],
            "rules": {
                "format-line": {
                    "message": "format: 80 columns exceeded",
                    "name": ,
                    "pattern": "^.{81,120}$",
                    "severity": "Warning"
                },
                "format-line": {
                    "message": "format: 120 columns exceeded",
                    "pattern": "^.{121,}$",
                    "severity": "Error"
                }
            }
        }
    }
    ...
}

Changes to Dryer-Lint Settings Format

I am trying to make Dryer Lint backwards compatible while also making changes that dramatically improve the extension. This means that I have defined a new format for the "dryerLint.ruleSets" setting in v2.0 while also continuing to support the v1.4 format (at least for now). The two formats are incompatible, so you need to modify your settings before you can start taking advantage of the new v2.0 features.

Transition to v2.0 ownward

In v2.0, the list of rule sets is given as


"dryerLint.ruleSets": {
    "rule set 1": {   // First rule set
        "name": "Example Rule Set 1",
        "language": "c++",
        "rules": {

            "Rule 1": {
                "name": "No apples or oranges. Only bananas",
                "pattern": "(apple|orange)",
                "message": "Don't use apples or oranges. Only bananas!",
            },
        }
    }, 
    "rule set 1": {   
        
        "name": "Example Rule Set 2", 
        "language": ["javascript", "typescript"],
        "rules": [
            //
        ]
    },
}

This is different from v1.4, which uses a list of dictionaries to store the list of rule sets in "dryerLint.ruleSets", and the list of rules in "rules". For instance

"dryerLint.ruleSets": [
    {   // First rule set
        "name": "Example Rule Set 1",
        "language": "c++",
        "rules": [
            {
                "name": "No apples or oranges. Only bananas",
                "pattern": "(apple|orange)",
                "message": "Don't use apples or oranges. Only bananas!",
            },
        ]
    }, 
    {   // Second rule set.
        "name": "Example Rule Set 2", 
        "language": ["javascript", "typescript"],
        "rules": [
            //
        ]
    },
    // ...
]

To keep existing v1.4 rules while allowing you to start updating to the v2.0 format, change "dryerLint.ruleSets" to `"dryerLint.ruleSets-legacy" for the v1.4 list of rule sets:

"dryerLint.ruleSets-legacy": [
    {   // First rule set
        "name": "Example Rule Set 1",
        "language": "c++",
        "rules": [
            {
                "name": "No apples or oranges. Only bananas",
                "pattern": "(apple|orange)",
                "message": "Don't use apples or oranges. Only bananas!",
            },
        ]
    }, 
    {   // Second rule set.
        "name": "Example Rule Set 2", 
        "language": ["javascript", "typescript"],
        "rules": [
            //
        ]
    },
    // ...
]

Define new rule sets using the v2.0 format in the "dryerLint.ruleSets" setting.

The advantage of the new format is that VSCode will merge settings defined as dictionaries, but not lists, so the new format allows you to define rule sets in user settings and workspace settings.

Related Projects

  • Dryer Lint was forked from relint extension by Ryan Blonna. The relint project has been dormant since 2021 aside from updates merged from Dryer Lint.

  • ast-grep is command line tool for custom linting, which also has a VS Code Extension. The setup of ast-grep is somewhat more involved, whereas Dryer Lint only requires installing the VS Code extension, but ast-grep.

  • Semgrep: AI-based static analysis.

  • comby

  • Structural Search for JetBrains IntelliJ IDEA

Development

This section describes how to set up Dryer Lint for development.

Install Node.js and the Node Package Manager:

  1. Download and install Node.js (LTS version recommended).
  2. The Node Package Manager (npm) comes bundled with Node.js.

After installing NPM, clone this repository and open it in VS Code. Then, to install the Node.js dependencies listed in package.json, run the following command within the root directory of the repo.

npm install

Once you have all of the dependencies, you should be able to build this extension using

npm run compile

in the root of this repository.

To see the console output of Dryer Lint, open the VS Code “Output” panel and select “Dryer Lint” from the dropdown.

Test Extension in another Workspace

To run this extension in a workspace—without building and installing a VS Code extension package globally—follow these steps:

  1. Open the workspace where you want to test Dryer Lint.
  2. Create .vscode/extension as a directory relative to the root of your workspace (if it does not already exist).
  3. Clone Dryer Lint into .vscode/extension. The resulting path should be .vscode/extension/dryer-lint.
  4. Change your working directory to .vscode/extension/dryer-lint and run npm install (as described in the previous section) to install all of Dryer Lint's dependencies.
  5. Run npm run compile to compile the project.
  6. Open the Extensions panel and select “Dryer Lint” from the “Recommended” subpanel. Click “Install Workspace Extension.”
  7. Run Developer: Restart Extension Host in the VS Code Command window (CTRL+SHIFT+P, by default on Windows).

To update the extension after changing the code, repeat steps 4 and 6 (npm run compile and run Developer: Restart Extension Host).

Packaging the Extension

Dryer Lint is packaged and published used the VS Code Extension Manager tool, vsce. To install vsce, run,

npm install -g @vscode/vsce

Then, within the root of this project, create a package with

vsce package

and publish a new major, minor, or patch version with

vsce publish [major/minor/path]

Development notes

When change the "contributes"/"configuration" in package.json, you need to reload the VS Code window for IntelliCode to update its autocompletion in the settings.json file.

To print trace and debug logging statements, you need to change the log from its default value ("Info"). To change the log level, select "Developer: Set Log Level..." from the command palette.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2025 Microsoft