Is it possible to define custom/local linters in vscode?

Viewed 1802

I have a simple home made linter that I use for work, it's invoked like this: python3 scripts/lint.py FILENAME

The output is completely standard linter-style output, like:

path/to/file.yang:5:19: Linter warning here
path/to/file.yang:6:83: Another warning here
...

I feel like it should be very easy to integrate this linter into vscode so I get automatic linting while writing code, just like how linter extensions work. However, Googling "vscode custom linter" yields absolutely nothing of value.

Is it possible to do this without going through the trouble of writing a custom extension?

1 Answers

It can be done but it involves a bit of settings editing.

Remove the default key binding for Ctrl+S and setup 2 new key bindings

keybindings.json

  {
    "key": "ctrl+s",
    "command": "-workbench.action.files.save"
  },
  {
    "key": "ctrl+s",
    "command": "multiCommand.lintingYang",
    "when": "editorLangId == yang"
  },
  {
    "key": "ctrl+s",
    "command": "workbench.action.files.save",
    "when": "editorLangId != yang"
  }

Use the extension multi-command by ryuta46 to create a command that saves the file and calls the custom linter: (add a little wait to be sure the file is saved)

.vscode/settings.json

  "multiCommand.commands": [
    {
      "command": "multiCommand.lintingYang",
      "interval": 500,
      "sequence": [
        "workbench.action.files.save",
        { "command": "workbench.action.tasks.runTask",
          "args": "Lint Yang"
        }
      ]
    }
  ]

The linter call is a task that has a custom problem matcher

.vscode/tasks.json

    {
      "label": "Lint Yang",
      "type": "shell",
      "command": "python3",
      "args": [ "${workspaceFolder}/scripts/lint.py", "${file}"],
      "options": { "cwd": "${fileDirname}" },
      "presentation": { "clear": true },
      "problemMatcher": {
        "owner": "yang",
        "fileLocation": ["relative", "${workspaceFolder}"],
        "pattern": [
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        ]
      }
    }

Edit

It should be enough to define a keybinding that will catch the exception case, otherwise it will use the default keybinding.

keybindings.json

  {
    "key": "ctrl+s",
    "command": "multiCommand.lintingYang",
    "when": "editorLangId == yang"
  }
Related