GithubHelp home page GithubHelp logo

iamcco / diagnostic-languageserver Goto Github PK

View Code? Open in Web Editor NEW
407.0 3.0 27.0 116 KB

diagnostic language server integrate with linters

License: MIT License

JavaScript 0.15% TypeScript 99.72% Shell 0.13%
coc linter diagnostic lsp neovim vim

diagnostic-languageserver's Introduction

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

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

References

Buy Me A Coffee ☕️

btc

image

diagnostic-languageserver's People

Contributors

bryanforbes avatar c0r73x avatar dependabot[bot] avatar eliasnorrby avatar esetnik avatar fsouza avatar gregorias avatar iamcco avatar mikew avatar miuirussia avatar n9v9 avatar przepompownia avatar revenue-hack avatar sanga avatar sileht avatar thomasjm avatar tyen-brex avatar zurp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

diagnostic-languageserver's Issues

parseJson: how to correct use %filepath in the path to errorsRoot

Let's see an output of phpstan on some old project:

 $ phpstan analyze --level max --error-format=json php/PHPCD.php         
{                                                                                                                                                                             
  "totals": {                                                                                                                                                                 
    "errors": 0,                                                                                                                                                              
    "file_errors": 41                                                                                                                                                         
  },                                                                                                                                                                          
  "files": {                                                                                                                                                                  
    "/home/user/phpcd.vim/php/PHPCD.php": {                                                                                                                              
      "errors": 41,                                                                                                                                                           
      "messages": [                                                                                                                                                           
        {                                                                                                                                                                     
          "message": "Method PHPCD\\PHPCD::setServer() has no return typehint specified.",                                                                                    
          "line": 100,                                                                                                                                                        
          "ignorable": true                                                                                                                                                   
        }
      ]
    }
  }
}

In the shell the filtering this output by | jq '.files["/home/user/phpcd.vim/php/PHPCD.php"].messages' works.

I tried to make something similar in coc config, e.g. use "errorsRoot": "files[\"%filepath\"].messages" but it does not work. Please update examples with the correct usage if using %filepath in erorsRoot is possible.

I successfully made working equivalent fo phpcs but it can take stdin (phpstan seems to cannot it) and so there is no need to use the filename in the path.

Display diagnostics only for the current file

Hey there, first of all thanks for this nice extension.
I am using it mainly for Go with golangci-lint. This linter does checks on directories and it reports all linting errors correctly. However when I have two files say A and B which both contain linting errors and I open A then I also get the errors from B displayed inside A's window:

image

Is it possible to only display the errors for file A and when I switch to file B to then display the errors for file B?
When I use the sourceName property implemented in #26, I can see from which file the linting message comes, but all messages are still displayed.

Do you accept pull requests? If so then I would try to come up with a PR that filters the returned ILinterResult[] based on the textDocument.uri path only if the aforementioned sourceName property is given, or something like that.

Thanks!

Custom formatter with viml script

Hi, I see all the examples of linters and formatters using external program,
Say I have a vim native function that is used to format my document, can I use it somehow?
Thanks.

stdin-filename support

Hey,
Thanks for the great project!
Been using coc-eslint for a while, but diagnostic-languageserver + eslint_d is unbeatable.
Prettier is one of the plugins I'm using in my eslint config. It relies on filenames to decide what rules / parser it should apply. To be able to support that with diagnostic-languageserver we need to add --stdin-filename to args.
I made a quick patch for it so that it works for me here: https://github.com/neculaesei/diagnostic-languageserver/blob/master/src/common/util.ts#L40
The problem is that with my approach these arguments are added to all linters / fixers, not just eslint, and also the default is hardcoded to "untitled.js". Maybe there could be a way to template textDocument.uri and have it in the args as {filename} in coc-settings.json.
What are your thoughts on this?
I'd be happy to provide a pull request for this.

Ignore exit code option

Some linters, such as gitlint and rstcheck, will give an exit code other than zero even when linting was successful.
To work around this, I usually have to set the command to sh so I can run true after the command, or set up a wrapper script to suppress error codes.

Having something like an ignoreExitCode option would work better though.

Lint messages are shown for adjacent files

I'm using "ktlint" for Kotlin and I see lint messages shown not only for opened file, but for adjacent ones.
I'm using coc extension.

{
    "languageserver": {
        "kotlin": {
	    "command": "kotlin-language-server",
	        "filetypes": ["kotlin"]
        },

        "dls": {
            "command": "diagnostic-languageserver",
            "args": ["--stdio"],
            "filetypes": [ "kotlin" ],
            "initializationOptions": {
                "linters": {
                    "ktlint": {
                        "command": "ktlint",
                        "sourceName": "ktlint",
                        "formatLines": 1,
                        "formatPattern": [ 
                            "^[^:]+:(\\d+):(\\d+):\\s+(.*)$",
                            { 
                                "line": 1,
                                "column": 2,
                                "message" : [0]
                            }
                        ]
                    }
                },
                "formatters": {
                    "ktlint" : {
                        "command": "ktlint",
                        "args" : [ "--format"]
                    }
                },
                "filetypes": {
                    "kotlin": "ktlint"
                },
                "formatFileTypes" : {
                    "kotlin": "ktlint"
                }
            }
        }
    }
}

illogical sourceName

Describe the bug
sourceName shows partial filepath.

It is caused by the workaround in:
#30
iamcco/coc-diagnostic#49

Expected behavior
sourceName should contain the name of the linter not the filename.

Screenshots
image

Desktop (please complete the following information):

  • OS: Arch Linux (Linux 5.8.10-arch1-1)

parseJson: support linters that only report a line

I'm having trouble integrating slim-lint because it will only report the line an error occured, but no column:

{
  "metadata": {
    "slim_lint_version": "0.20.0",
    "ruby_engine": "ruby",
    "ruby_patchlevel": "146",
    "ruby_platform": "x86_64-darwin19"
  },
  "files": [
    {
      "path": "....html.slim",
      "offenses": [
        {
          "severity": "warning",
          "message": "Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.",
          "location": {
            "line": 9
          }
        },
        {
          "severity": "warning",
          "message": "Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.",
          "location": {
            "line": 12
          }
        },
        {
          "severity": "warning",
          "message": "Style/UnlessElse: Do not use `unless` with `else`. Rewrite these with the positive case first.",
          "location": {
            "line": 20
          }
        }
      ]
    }
  ],
  "summary": {
    "offense_count": 3,
    "target_file_count": 1,
    "inspected_file_count": 1
  }
}
    "slimlint": {
      "command": "slim-lint",
      "sourceName": "slim-lint",
      "args": ["-r", "json", "%file"],
      "parseJson": {
        "errorsRoot": "files.[0].offenses",
        "line": "location.line",
        "security": "severity",
        "message": "${code}: ${message}"
      }
    }

The errors seem to be attached to the second last column in the buffer instead of being visible over the whole line.

Questions about code design

Guys, sorry to disturb you, but i'd like to share some of my thoughts and feedback about that project. Sorry again for not very structured feedback, but hope it might be userful:

  • Logger stores all logged messages during session if it's disabled, that means, memory consuming grows up in time, that might be inconvenient for large projects. I understand your intention, but performance-wise it looks like uncontrollable memory leak.
  • Project will be much easier to support without rxjs, vscode lsp already implements pub/sub, and it's quite sub-optimal to build stream to pass whole document on every change. It seems possible to get rid of this abstraction and make the codebase better both in terms of redundant cyclomatic complexity and code readability for new contributors.
  • It would be great to have options to configure on which event lint is triggered (onSave, onChange, etc).
  • May be I misread this code, but second return never will be executed.

I can make a PR simplifies the codebase and refactors architecture, if you'll fine with it. What do you think?

Adding support for `endColumn` / `endLine` to diagnostics

What do you think about adding support for endLine and endColumn to diagnostics? I noticed that shellcheck -f json and eslint --format json will return that info.

There's a couple of ways to implement it:

Idea 1: Use the fact that the output is json

JSON is easy to parse (especially since this is already javascript), but there would need to be a few additions, we'd need to

  • tell diagnostic-languageserver to parse json
  • tell diagnostic-languageserver where the list of errors starts (for cases when the list of errors is not on the root)
  • tell diagnostic-languageserver what keys are what

So for eslint, it would look something like:

{
  "eslint": {
    "command": "./node_modules/.bin/eslint",
    "rootPatterns": ["package.json"],
    "debounce": 100,
    "args": [ "--stdin", "--format", "json" ],
    "sourceName": "eslint",

    "parseJson": true,
    // Dot separated path. If empty, simply use the root.
    "errorsRoot": "messages",

    "line": "line",
    "column": "column",

    // If left out, just use line / column
    "endLine": "endLine",
    "endColumn": "endColumn",

    // Will be parsed from the error object.
    "message": "$message [$ruleId]",
    "security": "severity",

    "securities": {
      "2": "error",
      "1": "warning"
    }
  }
}

For reference, here's what eslint --format json looks like:

[
  {
    "filePath": "/foo/bar/file.ts",
    "messages": [
      {
        "ruleId": "@typescript-eslint/interface-name-prefix",
        "severity": 2,
        "message": "Interface name must not be prefixed with \"I\".",
        "line": 15,
        "column": 11,
        "nodeType": "Identifier",
        "messageId": "noPrefix",
        "endLine": 15,
        "endColumn": 15
      },
      {
        "ruleId": "@typescript-eslint/no-empty-interface",
        "severity": 2,
        "message": "An empty interface is equivalent to `{}`.",
        "line": 15,
        "column": 11,
        "nodeType": "Identifier",
        "messageId": "noEmpty",
        "endLine": 15,
        "endColumn": 15
      }
    ],
    "errorCount": 2,
    "warningCount": 0,
    "fixableErrorCount": 0,
    "fixableWarningCount": 0,
    "source": "big ol content"
  }
]

While JSON is indeed easier to work with, the eslint output, for instance, includes the whole content of the file it's linting. That seems like it could cause unneeded slowdown in diagnostic-languageserver.

Idea 2: Continue to use regexs

Regexs are already supported, so we could lean on that. And checking for multiple matches of an expression may already be supported, I haven't tried. I imagine it would need to operate on the whole of stdout+stderr, and not line-by-line, since there's no guarantee that the one line would include all needed info. But for instance, this regex parses shellcheck -f json:

/"line":([^,]+),"endLine":([^,]+),"column":([^,]+),"endColumn":([^,]+),"level":"([^"]+)","code":([^,]+),"message":"([^"]+)"/g
[{"file":"/foo/install.sh","line":24,"endLine":24,"column":6,"endColumn":14,"level":"warning","code":2046,"message":"Quote this to prevent word splitting."},{"file":"/foo/install.sh","line":24,"endLine":24,"column":6,"endColumn":14,"level":"style","code":2005,"message":"Useless echo? Instead of 'echo $(cmd)', just use 'cmd'."},{"file":"/foo/install.sh","line":24,"endLine":24,"column":6,"endColumn":14,"level":"style","code":2006,"message":"Use $(...) notation instead of legacy backticked `...`."}]

How to configure cspell

Hello,
Nice language server!

Describe the bug
I cannot seem to configure the linter for cspell.

Here is my configuration for the LSP plugin for Sublime Text:

{
    "clients": {
        "diagnostic-ls": {
            "enabled": true,
            "command": [
                "diagnostic-languageserver",
                "--stdio",
                "--log-level", "2"
            ],
            "selector": "source.python",
            "initializationOptions": {
                "linters": {
                    "cspell": {
                        "command": "cspell",
                        "debounce": 100,
                        "args": [
                            "%filepath"
                        ],
                        "sourceName": "cspell",
                        "formatLines": 1,
                        "formatPattern": [
                            // the error message looks like this:
                            // /home/predrag/.config/sublime-text/Packages/Sone/index.py:1:1 - Unknown word (funer)
                            ".*?:(\\d+):(\\d+)\\s*-\\s*(.*)",
                            {
                                "line": 1,
                                "column": 2,
                                "message": 3,
                            }
                        ]
                    },
                },
                "formatters": {},
                "filetypes": {
                    "python": "cspell",
                    // "py": "cspell",
                }
            },
        }
    }
}

To Reproduce
Steps to reproduce the behavior:

  1. I have a index.py with the following content:
fudsaner = 21 

  1. When I open the document, the language sever starts,
    but I see no errors reported for the word "fudsaner".

Expected behavior
I would expect that the language server reports the diagnostics.

Desktop (please complete the following information):

  • OS: Ubuntu 20.04
  • diagnostic-languageserver v1.8.1

Log:

:: --> diagnostic-ls initialize(1): {'rootUri': 'file:///home/predrag/.config/sublime-text/Packages/Sone', 'processId': 48422, 'workspaceFolders': [{'uri': 'file:///home/predrag/.config/sublime-text/Packages/Sone', 'name': 'Sone'}], 'clientInfo': {'version': '1.2.13', 'name': 'Sublime Text LSP'}, 'rootPath': '/home/predrag/.config/sublime-text/Packages/Sone', 'capabilities': {'textDocument': {'formatting': {'dynamicRegistration': True}, 'codeLens': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'documentHighlight': {'dynamicRegistration': True}, 'codeAction': {'resolveSupport': {'properties': ['edit']}, 'dynamicRegistration': True, 'dataSupport': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.organizeImports']}}}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}}, 'synchronization': {'willSaveWaitUntil': True, 'dynamicRegistration': True, 'willSave': True, 'didSave': True}, 'rename': {'dynamicRegistration': True, 'prepareSupport': True}, 'selectionRange': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'references': {'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True, 'versionSupport': True, 'dataSupport': True, 'tagSupport': {'valueSet': [1, 2]}, 'codeDescriptionSupport': True}, 'documentSymbol': {'dynamicRegistration': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'tagSupport': {'valueSet': [1]}, 'hierarchicalDocumentSymbolSupport': True}, 'completion': {'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'dynamicRegistration': True, 'completionItem': {'deprecatedSupport': True, 'snippetSupport': True, 'tagSupport': {'valueSet': [1]}, 'documentationFormat': ['markdown', 'plaintext']}}}, 'workspace': {'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'workspaceFolders': True, 'applyEdit': True, 'executeCommand': {}, 'symbol': {'dynamicRegistration': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'tagSupport': {'valueSet': [1]}}, 'configuration': True}, 'window': {'workDoneProgress': True, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}, 'showDocument': {'support': True}}, 'general': {'regularExpressions': {'engine': 'ECMAScript'}, 'markdown': {'parser': 'Python-Markdown', 'version': '3.2.2'}}}, 'initializationOptions': {'formatters': {}, 'filetypes': {'python': 'cspell'}, 'linters': {'cspell': {'sourceName': 'cspell', 'args': ['%filepath'], 'debounce': 100, 'formatLines': 1, 'command': 'cspell', 'formatPattern': ['.*?:(\\d+):(\\d+)\\s*-\\s*(.*)', {'message': 3, 'line': 1, 'column': 2}]}}}}
:: <<< diagnostic-ls 1: {'capabilities': {'documentFormattingProvider': True, 'textDocumentSync': {'change': {'syncKind': 2}, 'save': {}, 'didOpen': {}, 'didClose': {}}}}
::  -> diagnostic-ls initialized: {}
::  -> diagnostic-ls textDocument/didOpen: {'textDocument': {'uri': 'file:///home/predrag/.config/sublime-text/Packages/Sone/index.py', 'languageId': 'python', 'version': 0, 'text': 'fudsaner = 21 '}}
:: <-  diagnostic-ls textDocument/publishDiagnostics: {'uri': 'file:///home/predrag/.config/sublime-text/Packages/Sone/index.py', 'diagnostics': []}

I suspect that something is wrong with my linter configuration, but I am not sure what.

Support for filename in formatPattern?

Hey there, thank you very much for this cool project!

When using with certain linters, such as mypy, the output includes other files too (because a type checker can't really check a file in isolation). For example, efm supports that via the %f pattern in the lint-formats parameter. I was wondering if you'd accept a PR that introduces something like that to diagnostic-languageserver?

Thanks!

Applying multiple formatters in sequence

From the documentation I see that formatFiletypes can take an array of formatters for each file type, but from a very cursory reading of the code it seems like they are run async.

My use case is that I would like to run Prettier, and only then ESLint (kind of like prettier-eslint does, but without using it.

Is something like that possible?

My config for PHP_CodeSniffer

Perhaps it is useful to somebody...

{
  "languageserver": {
    "dls": {
      "command": "diagnostic-languageserver",
      "args": [ "--stdio" ],
      "filetypes": [ "php" ],
      "initializationOptions": {
        "linters": {
          "phpcs": {
            "command": "./vendor/bin/phpcs",
            "debounce": 100,
            "rootPatterns": [ "composer.json", "composer.lock", "vendor", ".git" ],
            "args": [ "--standard=PSR2", "--report=emacs", "-s", "-" ],
            "offsetLine": 0,
            "offsetColumn": 0,
            "sourceName": "phpcs",
            "formatLines": 1,
            "formatPattern": [
              "^.*:(\\d+):(\\d+):\\s+(.*)\\s+-\\s+(.*)$",
              {
                "line": 1,
                "column": 2,
                "message": 4,
                "security": 3
              }
            ],
            "securities": {
              "error": "error",
              "warning": "warning"
            }
          }
        },
        "filetypes": {
          "php": "phpcs"
        }
      }
    }
  }
}

Yarn install doesn't make `diagnostic-languageserver` available

After running the installation procedure in the README:

yarn global add diagnostic-languageserver

It still isn't possible to run diagnostic-languageserver from the commandline. Which is why trying to run e.g. shellcheck through diagnostic-languageserver fails with this message:

Server languageserver.dls failed to start: Launching server "languageserver.dls" using command diagnostic-languageserver failed.

To Reproduce

  1. Add CoC and diagnostic-languageserver plugins
  2. Save the following minimal config as coc-settings.json next to your vimrc file:
{
  // diagnostic-languageserver
  "diagnostic-languageserver.filetypes": {
    "sh": "shellcheck"
  }
}
  1. Run CocRestart

Expected behavior
I expected the diagnostic messages to be shown as in the readme.

Screenshots
https://imgur.com/S9nCEQG

Desktop (please complete the following information):

  • OS: Debian buster; uname --all: Linux tardis 4.19.0-12-amd64 #1 SMP Debian 4.19.152-1 (2020-10-18) x86_64 GNU/Linux

Log:

Does diagnostic-languageserver leave a logfile anywhere?

question: where to put configurations?

Hi, Sorry for the naive question. I'm trying to use neovim's built-in LSP, and this plugin is in the readme for diagnostic. I was hoping I can use this to enable linting via eslint.

I do see the configuration, but I'm not sure where to put them? Is there an example repo on how this is setup? Thanks!

Support different formatters' outputs.

Support any other output format from formatters?

Looking a way to get eslint working without writing do disk with doesWriteToFile I saw documentation that says:

This option has the same effect as --fix with one difference: the fixes are not saved to the file system. This makes it possible to fix code from stdin (when used with the --stdin flag).

Because the default formatter does not output the fixed code, you'll have to use another one (e.g. json) to get the fixes. Here's an example of this pattern

getSomeText | eslint --stdin --fix-dry-run --format=json

This flag can be useful for integrations (e.g. editor plugins) which need to autofix text from the command line without saving it to the filesystem.

Which output is a json with a field output I don't think it is a standard as I didn't find references about it, maybe I am wrong.

But would be good a way to configure these kind of formats.

Comparison to efm-langserver

Says in the readme that this project was inspired by efm-langserver but there's no comparison. How is this project better/different?

How to register stylua as lua formatter ?

Neoformat code about stylua is as follow:

function! neoformat#formatters#lua#stylua() abort
    return {
        \ 'exe': 'stylua',
        \ 'args': ['--search-parent-directories', '--stdin-filepath', '"%:p"', '--', '-'],
        \ 'stdin': 1,
        \ }
endfunction

How to trigger formatting and select the correct formatter

Describe the bug
I can't seem to get the formatting to work for TypeScript in the most recent Neovim, the linting seems to work fine.
I'm trying the configuration listed below. When I try to call :lua vim.lsp.buf.formatting() just nothing happens. I have disabled the typescript language server to make sure nothing interferes and when I inspect the attached clients, diagnostics-languageserver is there as expected. Do you have an idea how to use the formatter in Neovim? And assuming the formatting works, is there a way to make sure, nvim-lsp uses diagnostics-languageserver instead of tsserver for formatting?

Thank you!
Daniel

lspconfig.diagnosticls.setup{
  on_attach=custom_attach,
  filetypes = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'css', 'scss', 'markdown', 'pandoc' },
  init_options = {
    linters = {
      eslint = {
        command = 'eslint',
        rootPatterns = { '.git' },
        debounce = 100,
        args = { '--stdin', '--stdin-filename', '%filepath', '--format', 'json' },
        sourceName = 'eslint',
        parseJson = {
          errorsRoot = '[0].messages',
          line = 'line',
          column = 'column',
          endLine = 'endLine',
          endColumn = 'endColumn',
          message = '[eslint] ${message} [${ruleId}]',
          security = 'severity'
        },
        securities = {
          [2] = 'error',
          [1] = 'warning'
        }
      },
      markdownlint = {
        command = 'markdownlint',
        rootPatterns = { '.git' },
        isStderr = true,
        debounce = 100,
        args = { '--stdin' },
        offsetLine = 0,
        offsetColumn = 0,
        sourceName = 'markdownlint',
        securities = {
          undefined = 'hint'
        },
        formatLines = 1,
        formatPattern = {
          '^.*:(\\d+)\\s+(.*)$',
          {
            line = 1,
            column = -1,
            message = 2,
          }
        }
      }
    },
    filetypes = {
      javascript = 'eslint',
      javascriptreact = 'eslint',
      typescript = 'eslint',
      typescriptreact = 'eslint',
      markdown = 'markdownlint',
      pandoc = 'markdownlint'
    },
    formatters = {
      prettierEslint = {
        command = 'prettier-eslint',
        args = { '--stdin' },
        rootPatterns = { '.git' },
      },
      prettier = {
        command = 'prettier',
        args = { '--stdin-filepath', '%filename' }
      }
    },
    formatFiletypes = {
       css = 'prettier',
       javascript = 'prettierEslint',
       javascriptreact = 'prettierEslint',
       json = 'prettier',
       scss = 'prettier',
       typescript = 'prettierEslint',
       typescriptreact = 'prettierEslint'
    }
  }
}

Server doesn't support textDocument/hover

Hi,

thank you for your awesome work. I'm having the following issue: I want to work the diagnostic-language-server in combination with other language servers, for instance with the typescript-language-server. I have several hotkeys configured that trigger different functionalities, one of them is "hover" to get informations about functions/variables. If diagnosticls is activated for a file type, whenever I press the hover-hotkey, I get the correct functionality from tsserver but at the same time I get a server doesn't support textDocument/hover error in the command line:

Screenshot 2020-09-23 232039

Is there a way to handle or suppress this error? I am also using diagnostics-nvim so could I maybe add a method for the hover event that just toggles a popup with the diagnostics message?

Regards,
Daniel

Add an option for filename relative to workspace directory

Hi, first of all let me say that I like this plugin very much. It adds a lot of flexibility to coc.nvim.

While adding some linter and formatter myself, I found some of them can take the relative file path with respect to the workspace directory. Right now this language server supports "%text", "%filename", "%file", "%filepath". Is it support to add support for file's relative path when rootPattern is specified? Thanks.

vim.lsp.buf.formatting_sync() not working

Hi, I can run the command:

:lua vim.lsp.buf.formatting() which works, but :lua vim.lsp.buf.formatting_sync(nil, 1000) or any variation of that function is not working for me. I'm using eslint/prettier with typescript. Can you please confirm this is still working or if it's something my end?

How can I debug my config?

Hi
I'm trying to use dmypy (mypy in daemon mode) as a linter, but it's not working.
I'm can use mypy using the config in the wiki, and I can use dmypy in cli.
My question is how can I see what command is the diagnostic lsp actually running and what response is it receiving and what is going wrong? No error or message is being printed in coc's log file AFAIK.

This is the relevant part of coc-settings:

  "diagnostic-languageserver.debug": true,
  "diagnostic-languageserver.trace.server": "verbose",
  "diagnostic-languageserver.filetypes": {
    "python": ["flake8", "dmypy"]
  },
  "diagnostic-languageserver.linters": {
    "dmypy": {
       ...

And this is my versions:

## versions

vim version: NVIM v0.5.0-dev+1422-ga03ffe160
node version: v16.3.0
coc.nvim version: 0.0.80-171ff2bc99
coc.nvim directory: /home/sazary/.vim/plugged/coc.nvim
term: xterm-256color
platform: linux

Thank you very much

Wrong default configuration for vint?

Hi,
First of all thank you for this project, on which I rely for shell and vimscript linting.
I had trouble making diagnostic-languageserver work for vimscript though. I don't know if something changed recently, but the default entry:

	 "diagnostic-languageserver.linters":{
            "vint": {
                "command": "vint",
                "debounce": 100,
                "args": ["--enable-neovim", "-" ],
                "offsetLine": 0,
                "offsetColumn": 0,
                "sourceName": "vint",
                "formatLines": 1,
                "formatPattern": [
                    "[^:]+:(\\d+):(\\d+):\\s*(.*$)",
                    {
                        "line": 1,
                        "column": 2,
                        "message": 3
                    }
                ]
            }
	 }

does not seem to work. I had to change the "args" option to "args": ["%file"].
On macos high-sierra using vint 0.3.21 on Python 3.6.9 and vim 8.1.2072.
Thanks a lot!

Feature: Clear formatter error logs

Code formatters can fail when the code they're formatting is not valid. For example, "black" fails on invalid Python. It would be great if there were a feature that saved formatter errors for pretty display to the end user; it seems like these error messages are discarded at present (see #11)

I've implemented my own Vim formatter plugin a while ago that provides a version of this, but I'd like to migrate to your general language server for formatting if possible. The error logging feature is an extremely nice to have, so I'm opening this issue in case anyone has the time / inclination to implement something helpful (custom action show stderr on failed formatters, etc). I think formatter debugging capabilities is a fundamental part of a tool that provides code formatting.

Reference: https://github.com/pappasam/vim-filetype-formatter/blob/845aaa95dc00efa20a9aa2c8615a47bbd4bf50f7/doc/filetype_formatter.txt#L128

lslint

I am trying to get this to work for https://github.com/Makopo/lslint

Example output is

ERROR:: (  4, 20): Passing integer as argument 1 of `llOwnerSay' which is declared as `string msg'.
TOTAL:: Errors: 1  Warnings: 0

My coc-settings.json

{
  "coc.preferences.formatOnSaveFiletypes": ["tsx", "typescript"],
  "codeLens.enable": true,
  "prettier.requireConfig": true,
  "languageserver": {
    "dls": {
      "args": ["--stdio"],
      "command": "diagnostic-languageserver",
      "filetypes": ["lsl"],
      "initializationOptions": {
        "filetypes": { "lsl": "lslint" },
        "linters": {
          "lslint": {
            "command": "lslint",
            "debounce": 100,
            "formatPattern": [
              "^(.+):: \\( *(\\d+), *(\\d+)\\): (.+)$",
              { "column": 3, "line": 2, "message": [4], "security": 1 }
            ],
            "securities": { "ERROR": "error", "WARN": "warning" },
            "sourceName": "lslint"
          }
        }
      },
      "trace.server": "verbose"
    }
  }
}

Change severity/security

I want to show all output of a linter as warning (and not error)

    "write-good": {
      "command": "write-good",
      "debounce": 1000,
      "args": ["--text=%text"],
      "offsetLine": 0,
      "offsetColumn": 1,
      "sourceName": "write-good",
      "formatLines": 1,
      "severity" : "warning",
      "formatPattern": [
        "(.*)\\s+on\\s+line\\s+(\\d+)\\s+at\\s+column\\s+(\\d+)\\s*$",
        {
          "line": 2,
          "column": 3,
          "message": 1
        }
      ]
    },

Doesn't have the expected effect.

image

[E] is evidence for it being an error. Is the config wrong, or is this a bug?

Same if I try to hard-code it in formatPattern. Is it currently supported?

Btw. the wording "security" instead of "severity" is not quite what I would expect for this option. :)

Support %dirname

Describe the bug
Hello, could support for %dirname in args additional syntax be added? This would be useful to pass in the directory of the file, which is useful for linters such as golangci-lint

if (/%filename/.test(arg)) {
return arg.replace(/%filename/g, path.basename(fpath))
}

Could have

    if (/%dirname/.test(arg)) {
      return arg.replace(/%filename/g, path.dirname(fpath))
    }

[feature request]: `format selected range` with diagnostic-languageserver

Hi iamcoo,

thx a lot for 'diagnostic-languageserver'. I am trying to format visually selected python code with black or autopep8. Whenever I try to trigger the formatting with the mapping

vmap <leader>p  <Plug>(coc-format-selected)
nmap <leader>p  <Plug>(coc-format-selected)

I get the following error:

Notification error: formatSelected [ 'V' ] Error: formatRange provider not found for current buffer, your language server doesn't support it.

Formatting the whole file with the command

command! -nargs=0 Format :call CocAction('format')

works without a problem.

I did not find any related issues neither here on this site nor by using Google. Therefore I guess it must be a problem that might be only affecting me?

Here is the diagnostic-languageserver part of my coc-settings.json file that looks as unspectacular as my formatting mappings above:

{
  "languageserver": {
    "dls": {
      "command": "diagnostic-languageserver",
      "args": ["--stdio"],
      "filetypes": ["python"],
      "trace.server": "verbose",
      "initializationOptions": {
        "linters": {
          "pylint": {
            "sourceName": "pylint",
            "command": "pylint",
            "args": [
              "--output-format",
              "text",
              "--score",
              "no",
              "--msg-template",
              "'{line}:{column}:{category}:{msg} ({msg_id}:{symbol})'",
              "%file"
            ],
            "formatPattern": [
              "^(\\d+?):(\\d+?):([a-z]+?):(.*)$",
              {
                "line": 1,
                "column": 2,
                "security": 3,
                "message": 4
              }
            ],
            "rootPatterns": [".vim", ".git", "pyproject.toml", "setup.py"],
            "securities": {
              "informational": "hint",
              "refactor": "info",
              "convention": "info",
              "warning": "warning",
              "error": "error",
              "fatal": "error"
            },
            "offsetColumn": 1,
            "formatLines": 1
          }
        },
        "formatters": {
          "autopep8": {
            "command": "autopep8",
            "args": ["-"]
          },
          "black": {
            "command": "black",
            "args": ["--quiet", "-"]
          },
          "isort": {
            "command": "isort",
            "args": ["--quiet", "-"]
          }
        },
        "filetypes": {
          "python": "pylint"
        },
        "formatFiletypes": {
          "python": ["autopep8", "isort"]
        }
      }
    }
  }
}

Thank you very much for any help. If you need any more input just ask.

Where does the config go?

I want to use this LSP with a different LSP client than coc.nvim. So, where does this LSP's config file go? Would you mind documenting it in README for noncoc.nvim users? Thanks!

support for "suppress <lint rule>" textDocument/codeAction action

Hi there,

I was poking around with this to replace my coc.nvim eslint config, but I noticed that there is no support yet for code action to add stuff like eslint-disable-next-line:

// eslint-disable-next-line import/no-extraneous-dependencies
const glob = require('glob');

This type of code action can be a really handy time saver.

Skip missing binaries

Describe the bug

Skip formatters/linters that can't be found in $PATH.

To Reproduce

Consider this config (using coc-diagnostic):

{
  "diagnostic-languageserver.formatFiletypes": {
    "python": [
      "black",
      "isort"
    ]
  }
}

Typically in Python you have to activate a "virtualenv" to get access to project local tooling. But since tooling varies from project to project, it's not guaranteed that both black and isort are available. For example project A might just have black and project B only isort. But formatting only works if both are available.

Expected behavior

It would be nice if missing tools were skipped. So given the above config, if black is missing, it should still run isort.

Desktop (please complete the following information):

  • OS: macOS 11.5.1

Question: Can I use this to run LanguageTool in server mode?

Hi

I have a working setup using vim/coc.nvim/coc-diagnostic to run diagnostic-languageserver for LanguageTool. This runs LanguageTool in commandline mode which means it has to startup every time I want to check something.

Is it possible to have diagnostic-languageserver run LanguageTool in server mode (http or https)?

(I know LTeX does this in VSCode.)

Thanks

%filename and %filepath not interpolated in nvim

Describe the bug
It looks like the LSP is passing the actual string "%filepath" or "%filename" to the linter, instead of the interpolated value.

To Reproduce
My nvim LSP config:

require'lspconfig'.diagnosticls.setup{
  filetypes = { "typescript.tsx"},
  init_options = {
    linters = {
      eslint = {
        sourceName = 'eslint',
        rootPatterns = {".eslintrc.js"},
        command = 'eslint',
        args = {
          "--stdin",
          "--stdin-filename",
          "%filepath",
          "--format",
          "json",
        },
        parseJson = {
          errorsRoot = "[0].messages",
          line = "line",
          column = "column",
          endLine = "endLine",
          endColumn = "endColumn",
          message = "${message} [${ruleId}]",
          security = "severity",
        },
        securities = {[2] = "error", [1] = "warning"},
      },
    },
    filetypes = {
      ['typescript.tsx'] = 'eslint',
    },
  },
}

Looking at the LSP logs, I see this line:
[ DEBUG ] 2020-12-12T18:15:59-0500 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:471 ] "notification" "window/logMessage" { message = 'Linter command: eslint, args: ["--stdin","--stdin-filename","%filepath","--format","json"]', type = 4}

ESLint uses the filename to choose a parser based on the file extension. The error returned by the linter to the LSP is consistent with calling eslint --stdin --stdin-filename %filepath < myFile.tsx, or omitting --stdin-filename altogether. If I set args to {"--stdin", "--stdin-filename", "whatever.tsx", "--format", "json"} it correctly lints the file.

This happens with both %filepath and %filename.

Expected behavior
The LSP correctly interpolates the value of %filename or %filepath and passes it to the linter.

Desktop (please complete the following information):

  • OS: OS X 10.15.7

Option to exclude file and folders

Not really a bug, but there's no template for feature requests.

Right now, when the LSP is asked to provide diagnostics for the whole workspace, all folders seem to be considered. However, there might be folders such as .git or .venv that should not be touched by the server. Some option to exclude them would be great.

Choose default severity level

For linters that don't support severity level current severity level is defaulted to Error.
Can we configure default severity level?

languagetool support in nvim 0.5

using diagnostic-languageserver on nvim 0.5 with built-in lsp

I have configured it correctly to work with markdownlint, vim-vint & write-good. I am just unable to get it working with languagetool

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}}
                }
            },

No matter what I do it does not launch. i have changed the args to %file, %text, also commented it out. Could I receive some advice on how to config this differently?

Also, whats the best way to install languagetool? I have tried installing from the arch repo. If it is to use the standalone version, or from source, I dont know how to change the above in command section. would it be "java -jar /path/to/languagetool.jar"?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.