npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

diagnostic-languageserver

v1.15.0

Published

diagnostic language server

Downloads

642

Readme

diagnostic-languageserver

General purpose Language Server that integrate with linter to support diagnostic features

Main features

  • diagnostic with linters
  • document format

screenshot with neovim and coc image

Install

yarn global add diagnostic-languageserver

make sure your yarn's global bin path is include in PATH

for example export PATH="$(yarn global bin):$PATH"

Config & Document

languageserver config:

{
  "languageserver": {
    "dls": {
      "command": "diagnostic-languageserver",
      "args": ["--stdio", "--log-level", "2"],
      "filetypes": [ "sh", "email" ], // filetypes that you want to enable this lsp
      "initializationOptions": {
        "linters": {
          ...
        },
        "filetypes": {
          ...
        },
        "formatters": {
          ...
        },
        "formatFiletypes": {
          ...
        }
      }
    }
  }
}

linters field:

{
  "linterName": {                                    // linter name, for example: vint
    "command": "shellcheck",                         // linter command
    "rootPatterns": [],                              // root patterns, default empty array
    "isStdout": true,                                // use stdout output, default true
    "isStderr": false,                               // use stderr output, default false
    "debounce": 100,                                 // debounce time
    "onSaveOnly": false,                             // linter is triggered only when file is saved
    "args": [ "--format=gcc", "-"],                  // args
    "offsetLine": 0,                                 // offsetline
    "offsetColumn": 0,                               // offsetColumn
    "sourceName": "shellcheck",                      // source name
    "ignore": [".git", "dist/"]                      // ignore pattern same as `.gitignore`
                                                     // don't forget to add `rootPatterns` when using `ignore`
                                                     // it need workspace to filter

    // Using regular expressions:
    "formatLines": 1,                                // how much lines for formatPattern[0] to match
    "formatPattern": [
      "^([^:]+):(\\d+):(\\d+):\\s+([^:]+):\\s+(.*)$",  // line match pattern (javascript regex)
      {
        "sourceName": 1,                             // diagnostic file use match group 1. Will default to the file being linted.
        "sourceNameFilter": true,                    // Display diagnostics only for the current file.
                                                     // Only works when sourceName is defined and when it contains either an absolute
                                                     // or relative path to the file being linted. Defaults to false.
        "line": 2,                                   // diagnostic line use match group 2
        "column": 3,                                 // diagnostic column use match group 3
        "endLine": 2,                                // diagnostic end line use match group 2. Will default to group from `line`
        "endColumn": 3,                              // diagnostic end column use match group 3. Will default to group from `column`
        "message": [5],                              // message to display use match group 5
        "security": 4                                // security to use match group 4, ignore if linter do not support security
      }
    ],

    // Using JSON:
    "parseJson": {
      "errorsRoot": "[0].messages",                  // dot separated path. Will default to whatever JSON is output
                                                     // for more information see examples at https://lodash.com/docs/#get
                                                     // %filepath will be replaced with full path to the file (like in `args`)

      // All of these support lodash.get syntax.
      "sourceName": "file",                          // propert that contains the `file`. Will default to the file being linted.
      "sourceNameFilter": true,                      // Display diagnostics only for the current file.
                                                     // Only works when sourceName is defined and when it contains either an absolute
                                                     // or relative path to the file being linted. Defaults to false.
      "line": "line",                                // property that contains the `line`
      "column": "column",                            // property that contains the `column`
      "endLine": "endLine",                          // property that contains the `endLine`. Will default to `line`
      "endColumn": "endColumn",                      // property that contains the `endColumn`. Will default to `column`
      "security": "severity",                        // property that contains the `security`
      "message": "${message} [${code}]",             // message to display
    },

    "securities": {                                  // security keys, ignore if linter do not support security
      "error": "error",                              // [key: string]?: "error" | "warning" | "info" | "hint"
      "warning": "warning",
      "note": "info"
    },
    "requiredFiles": [                               // only run linter if any of these files exist. option
      ".shellcheckrc",
      "shellcheckrc"
    ]
  }
}

filetypes field:

{
  "sh": "linterName",                          // filetype: linterName or linterName[]
  "*": "linterName"                            // `*` is for all filetypes
}

formatters field:

  "dartfmt": {                                 // formatter name
    "command": "dartfmt",                      // format command
    "args": [ "--fix" ],                       // args
    "rootPatterns": [],                        // root patterns, default empty array
    "isStdout": true,                          // use stdout output, default true
    "isStderr": false,                         // use stderr output, default false
    "doesWriteToFile": false,                  // use if formatter doesn't support stdio. should be paired with `%file`
    "requiredFiles": [                         // only run formatter if any of these files exist. optional
      ".run_dartfmt",
    ],
    "ignoreExitCode": false,                   // ignore exit code. default false: exit code > 0 will not change the file.
                                               // some formatter may exit with code > 0 so you need set it to true or number[]
                                               // exit code array that you want to ignore.
    "ignore": [".git", "dist/"]                // ignore pattern same as `.gitignore`
                                               // don't forget to add `rootPatterns` when using `ignore`
                                               // it need workspace to filter
  }

formatFiletypes field:

{
  "dart": "dartfmt",                          // filetype: formatterName or formatterName[]
  "*": "linterName"                           // `*` is for all filetypes
}

Args additional syntax

args: ["%text", "%filename", "%relativepath", "%file", "%filepath", "%dirname", "%tempfile"]

  • %filename will replace with basename of file
  • %text will replace with file content
  • %file will replace with full path to the file and not use stdio
  • %filepath will replace with full path to the file
  • %relativepath will replace with relative path of file
  • %dirname will replace with dirname of file
  • %tempfile will replace with the full path to a temporary file written with the contents of the document and not use stdio; this file will automatically be deleted when the command completes

How to config a new linter

shellcheck for example:

file test.sh:

#!/usr/bin/env bash

echo `ls -al`

then:

shellcheck --format=gcc test.sh

output:

t.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]
t.sh:3:6: note: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]
t.sh:3:6: note: Use $(...) notation instead of legacy backticked `...`. [SC2006]

write pattern to match the line for line column message security:

const line = "t.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]"
const formatPattern = "^[^:]+:(\\d+):(\\d+):\\s+([^:]+):\\s+(.*)$"
const match = line.match(new RegExp(formatPattern))
console.log(match)

output:

{
  0: "t.sh:3:6: warning: Quote this to prevent word splitting. [SC2046]"
  1: "3"
  2: "6"
  3: "warning"
  4: "Quote this to prevent word splitting. [SC2046]"
}

so you got:

  • line: match[1]
  • column: match[2]
  • message: match[4]
  • security: match[3]

and your formatPattern field will be:

"formatPattern": [
  "^[^:]+:(\\d+):(\\d+):\\s+([^:]+):\\s+(.*)$",    // line match pattern (javascript regex)
  {
    "line": 1,                                     // diagnostic line use match group 1
    "column": 2,                                   // diagnostic column use match group 2
    "message": [4],                                // message to display use match group 4
    "security": 3                                  // security to use match group 3, ignore if linter do not support security
  }
]

Notes if the linter's message for per issue more then one line, you have to set the formatLines to fill your pattern, and you can view the languagetool pattern for example which formatLines = 2

Example with coc.nvim

Each LSP client should support initializationOptions option, all you need for diagnostic-languageserver is put the config in initializationOptions option.

  1. shellcheck for shell
  2. languagetool for grammer check
  3. more Linters config example.

coc-settings.json:

you can use this extension https://github.com/iamcco/coc-diagnostic

{
  "languageserver": {
    "dls": {
      "command": "diagnostic-languageserver",
      "args": ["--stdio"],
      "filetypes": [ "sh", "email", "dart" ],
      "initializationOptions": {
        "linters": {
          "shellcheck": {
            "command": "shellcheck",
            "debounce": 100,
            "args": [ "--format=gcc", "-"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "shellcheck",
            "formatLines": 1,
            "formatPattern": [
              "^[^:]+:(\\d+):(\\d+):\\s+([^:]+):\\s+(.*)$",
              {
                "line": 1,
                "column": 2,
                "message": 4,
                "security": 3
              }
            ],
            "securities": {
              "error": "error",
              "warning": "warning",
              "note": "info"
            }
          },
          "languagetool": {
            "command": "languagetool",
            "debounce": 200,
            "args": ["-"],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "languagetool",
            "formatLines": 2,
            "formatPattern": [
              "^\\d+?\\.\\)\\s+Line\\s+(\\d+),\\s+column\\s+(\\d+),\\s+([^\\n]+)\nMessage:\\s+(.*)$",
              {
                "line": 1,
                "column": 2,
                "message": [4, 3]
              }
            ],
          }
        },
        "formatters": {
          "dartfmt": {
            "command": "dartfmt",
            "args": [ "--fix" ],
          }
        },
        "filetypes": {
          "sh": "shellcheck",
          "email": "languagetool"
        },
        "formatFiletypes": {
          "dart": "dartfmt"
        }
      }
    }
  }
}

TODO

  • [x] local node_modules linter support like eslint or textlint
  • [x] diagnostic severity
  • [x] root pattern
  • [x] document format

References

Buy Me A Coffee ☕️

btc

image