diff --git a/README.md b/README.md index 3a7e9ab..b7c5bc3 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,28 @@ SonarLintâ„¢ is a free IDE extension that lets you fix coding issues before they exist! -Like a spell checker,it highlights Bugs and Security Vulnerabilities as you write code, with clear remediation guidance so you can fix them before the code is even committed. +Like a spell checker,it highlights Bugs and Security Vulnerabilities as you write code, with clear remediation guidance so you can fix them before the code is even committed. -In Emacs supports analysis of JavaScript, TypeScript, Python, Java, HTML, PHP, Go, and XML out of the box! +In Emacs supports analysis of JavaScript, TypeScript, Python, Java, HTML, PHP, C/C++, +Go, and XML out of the box! :warning: This is not an official [SonarSource](https://www.sonarsource.com/) extension ![Flycheck gif](https://gitlab.com/sasanidas/lsp-sonarlint/-/raw/master/examples/sonarlint-example.gif "Flycheck gif") + +## How it works + +lsp-sonarlint relies on the [official vscode extension](https://github.com/SonarSource/sonarlint-vscode/), which is downloaded and unzipped. + +The official VSCode extension typically contains : +- A language server (written in java) +- A Java runtime +- Analysers for 10+ languages +- A VSCode front-end + +lsp-sonarlint is emacs's equivalent of the VSCode front-end, but only +implements the base feature set, i.e linting and rules viewing. + ## Requirements - emacs >= 25 @@ -20,15 +35,15 @@ In Emacs supports analysis of JavaScript, TypeScript, Python, Java, HTML, PHP, G - [ht](https://github.com/Wilfred/ht.el) - [dash](https://github.com/magnars/dash.el) -The language server needs a Java Runtime (JRE) 8 or 11. If one is already installed on your computer, SonarLint should automatically find and use it. - To analyze JavaScript and TypeScript, SonarLint will also need Node.js. +To analyse C/C++ projects, SonarLint's CFamily analyzer will need both a working compiler and a +compile_commands.json which is typically generated by [cmake](https://github.com/rizsotto/Bear) or [bear](https://github.com/rizsotto/Bear). ## Installation ## Source -Download and include the main file lsp-sonarlint.el and the folders languages and server. +Download and include the main file lsp-sonarlint.el. ### Melpa You can then run the following commands to install lsp-sonarlint: @@ -40,51 +55,27 @@ M-x package-install RET lsp-sonarlint RET (to install and compile `lsp-sonarli ## Usage The language server relies on java plugins to properly analyze the selected language source code. -The basic workflow to activate a plugin for a language is: - - - Enable language specific extension, alongside lsp-sonarlint: -``` lisp -(require 'lsp-sonarlint) -(require 'lsp-sonarlint-LANGUAGENAME) -``` - -- It is important to enable the desired languages **before** execute the lsp client: +By default all are enabled, but you can specify the ones you want. ``` lisp -(setq lsp-sonarlint-LANGUAGENAME-enabled t) -``` - -- If the extension is not installed in the path **lsp-sonarlint-LANGUAGENAME-analyzer-path**, it will ask if you want to download it from -the URL defined in **lsp-sonarlint-LANGUAGENAME-download-url**. - -- If everything went well, you can now activate the *lsp* emacs command. - - -#### Complete config example -In this example, we have a multiple language project, with Javascript Typescript, HTML and PHP: - -``` lisp -(require 'lsp-sonarlint) - -(require 'lsp-sonarlint-php) -(setq lsp-sonarlint-php-enabled t) - -(require 'lsp-sonarlint-html) -(setq lsp-sonarlint-html-enabled t) - -(require 'lsp-sonarlint-javascript) -(setq lsp-sonarlint-javascript-enabled t) - -(require 'lsp-sonarlint-typescript) -(setq lsp-sonarlint-typescript-enabled t) -``` - -Now we can activate the lsp extension. - -The extension will check every plugin path and ask if it is not find to download it, -the default path is defined in **lsp-sonarlint-LANGUAGENAME-analyzer-path**. +(use-package lsp-sonarlint + :custom + ;; Allow sonarlint to download and unzip the official VSCode extension + ;; If nil, you'll have to do that yourself. See also `lsp-sonarlint-download' + ;; `lsp-sonarlint-download-url' and `lsp-sonarlint-download-dir' + (lsp-sonarlint-auto-download t) + + ;; Choose which analyzers you want enabled. By default all are enabled + ;; See command `lsp-sonarlint-available-analyzers' for the full list. + (lsp-sonarlint-enabled-analyzers '("java" "cfamily" "python" "text"))) +``` +> [!WARNING] +> On windows, lsp-sonarlint may encounter [this issue](https://github.com/emacs-lsp/lsp-mode/issues/3022) while unzipping the VSCode extension. If you do, try the following : +```elisp +(setq lsp-unzip-script lsp-ext-pwsh-script) +``` ## Static Analysis Rules @@ -98,31 +89,48 @@ Out of the box, SonarLint automatically checks your code against the following r - [PHP rules](https://rules.sonarsource.com/php) - [XML rules](https://rules.sonarsource.com/xml) - [Go rules](https://rules.sonarsource.com/go) +- [C rules](https://rules.sonarsource.com/c) +- [C++ rules](https://rules.sonarsource.com/cpp) - [Bidi (bidirectional unicode characters)](https://rules.sonarsource.com/text/) + [Secrets](https://rules.sonarsource.com/secrets/) ## Supported settings -* `lsp-sonarlint-server-path` - Path of the sonarlint jar executable file. +* `lsp-sonarlint-auto-download` - Set to t to enable auto-downloading of VSCode's extension on startup. +* `lsp-sonarlint-download-url` - Specify another URL for the VSCode extension. +* `lsp-sonarlint-download-dir` - Specify where VSCode's extension will be downloaded and unzipped. +* `lsp-sonarlint-use-system-jre` - If t, use the system Java runtime instead of the bundled one. +* `lsp-sonarlint-enabled-analyzers` - List of analyzers to enable. Defaults to 'all for all analyzers. * `lsp-sonarlint-modes-enabled` - List of major modes where the lsp server will activate. * `lsp-sonarlint-disable-telemetry` - Disable telemetry option (disabled by default). * `lsp-sonarlint-test-file-pattern` - Regex to find test file, most rules are not evaluated on test files. * `lsp-sonarlint-show-analyzer-logs` - Show analyzer logs. * `lsp-sonarlint-verbose-logs` - Make SonarLint logs verbose. -* `lsp-sonarlint-server-download-url` - SonarLint server download URL. -* `lsp-sonarlint-plugin-autodownload` - Not ask for confirmation and download analyzers if they are missing. +* `lsp-sonarlint-cfamily-compilation-commands-path` - Path to compile_commands.json for C/C++ analysis. + +### Available commands +* `lsp-sonarlint-download` - Download the VSCode extension and unzip it. Called automatically +if `lsp-sonarlint-auto-download`is set to t +* `lsp-sonarlint-available-analyzers` - List all available analyzers provided by the downloaded VSCode extension. -### Plugins supported settings -This settigns are common for all the language plugins. +### Plugins additional info + +For most analyzers, lsp-sonarlint provides variables describing additional +info. -* `lsp-sonarlint-LANGUAGE-enabled` - Enable LANGUAGE lsp-sonarlint plugin (disable by default) -* `lsp-sonarlint-LANGUAGE-download-url` - URL to download the LANGUAGE sonarlint plugin -* `lsp-sonarlint-LANGUAGE-analyzer-path` - Location where the plugin/anlyzer is located. * `lsp-sonarlint-LANGUAGE-doc-url` - Sonarsource official plugin documentation * `lsp-sonarlint-LANGUAGE-repository-url` - Plugin source code +### Plugins not tested yet +Currently, sonarlint's vscode extension also provides omnisharp and Infrastructure As Code (IAC) +analyzers. They have not been tested yet, you may expect some additional configuration +to make them work. +You'll at least need to add the major-modes to `lsp-sonarlint-modes-enabled'. + +Feel free to try them out and provide feedback. + ## Data and telemetry -This extension collects anonymous usage data and sends it to SonarSource. +This extension collects anonymous usage data and sends it to SonarSource. Collection of telemetry is controlled via the setting: `lsp-sonarlint-disable-telemetry`, it is disable by default. diff --git a/fixtures/compile_commands.json b/fixtures/compile_commands.json new file mode 100644 index 0000000..7ec41e7 --- /dev/null +++ b/fixtures/compile_commands.json @@ -0,0 +1,8 @@ +[ +{ + "directory": ".", + "command": "/usr/bin/c++ sample.cpp", + "file": "sample.cpp", + "output": "dummy" +} +] diff --git a/fixtures/sample.cpp b/fixtures/sample.cpp new file mode 100644 index 0000000..19b1c99 --- /dev/null +++ b/fixtures/sample.cpp @@ -0,0 +1,4 @@ +int g(int& val) +{ + return val; +} diff --git a/languages/go/lsp-sonarlint-go.el b/languages/go/lsp-sonarlint-go.el deleted file mode 100644 index 096de0b..0000000 --- a/languages/go/lsp-sonarlint-go.el +++ /dev/null @@ -1,60 +0,0 @@ -;;; lsp-sonarlint-go.el --- lsp-sonarlint Go module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint Go plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-go nil - "lsp-sonarlint Go analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-go . "1.12.0")) - -(defcustom lsp-sonarlint-go-enabled nil - "Enable lsp-sonarlint-go plugin." - :group 'lsp-sonarlint-go - :type 'boolean) - -(defcustom lsp-sonarlint-go-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/slang/sonar-go-plugin/1.12.0.4259/sonar-go-plugin-1.12.0.4259.jar" - "Go plugin download URL." - :group 'lsp-sonarlint-go - :type 'string) - -(defcustom lsp-sonarlint-go-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-go.jar") - "Lsp-sonarlint Go analyzer location." - :group 'lsp-sonarlint-go - :type 'file) - -(defvar lsp-sonarlint-go-doc-url "https://www.sonarsource.com/go/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-go-repository-url "https://github.com/SonarSource/slang/" - "Official sonarlint code extension repository.") - - -(provide 'lsp-sonarlint-go) -;;; lsp-sonarlint-go.el ends here diff --git a/languages/html/lsp-sonarlint-html.el b/languages/html/lsp-sonarlint-html.el deleted file mode 100644 index 7ba187b..0000000 --- a/languages/html/lsp-sonarlint-html.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; lsp-sonarlint-html.el --- lsp-sonarlint html module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint HTML plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-html nil - "lsp-sonarlint html analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-html . "3.7.1")) - -(defcustom lsp-sonarlint-html-enabled nil - "Enable lsp-sonarlint-html plugin." - :group 'lsp-sonarlint-html - :type 'boolean) - -(defcustom lsp-sonarlint-html-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/html/sonar-html-plugin/3.7.1.3306/sonar-html-plugin-3.7.1.3306.jar" - "HTML plugin download URL." - :group 'lsp-sonarlint-html - :type 'string) - -(defcustom lsp-sonarlint-html-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-html.jar") - "Lsp-sonarlint HTML analyzer location." - :group 'lsp-sonarlint-html - :type 'file) - -(defvar lsp-sonarlint-html-doc-url "https://www.sonarsource.com/html/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-html-repository-url "https://github.com/SonarSource/sonar-html" - "Official sonarlint code extension repository.") - - - - - -(provide 'lsp-sonarlint-html) -;;; lsp-sonarlint-html.el ends here diff --git a/languages/java/lsp-sonarlint-java.el b/languages/java/lsp-sonarlint-java.el deleted file mode 100644 index 04bc4bc..0000000 --- a/languages/java/lsp-sonarlint-java.el +++ /dev/null @@ -1,60 +0,0 @@ -;;; lsp-sonarlint-java.el --- lsp-sonarlint java module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint Java plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-java nil - "lsp-sonarlint java analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-java . "7.18.0")) - -(defcustom lsp-sonarlint-java-enabled nil - "Enable lsp-sonarlint-java plugin." - :group 'lsp-sonarlint-java - :type 'boolean) - -(defcustom lsp-sonarlint-java-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/java/sonar-java-plugin/7.18.0.31443/sonar-java-plugin-7.18.0.31443.jar" - "Java plugin download URL." - :group 'lsp-sonarlint-java - :type 'string) - -(defcustom lsp-sonarlint-java-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-java.jar") - "Lsp-sonarlint java analyzer location." - :group 'lsp-sonarlint-java - :type 'file) - -(defvar lsp-sonarlint-java-doc-url "https://www.sonarsource.com/java/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-java-repository-url "https://github.com/SonarSource/sonar-java" - "Official sonarlint code extension repository.") - - -(provide 'lsp-sonarlint-java) -;;; lsp-sonarlint-java.el ends here diff --git a/languages/javascript/lsp-sonarlint-javascript.el b/languages/javascript/lsp-sonarlint-javascript.el deleted file mode 100644 index 82e86c2..0000000 --- a/languages/javascript/lsp-sonarlint-javascript.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; lsp-sonarlint-javascript.el --- lsp-sonarlint javascript module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint Javascript plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-javascript nil - "lsp-sonarlint javascript analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-javascript . "10.1.0")) - -(defcustom lsp-sonarlint-javascript-enabled nil - "Enable lsp-sonarlint-javascript plugin." - :group 'lsp-sonarlint-javascript - :type 'boolean) - -(defcustom lsp-sonarlint-javascript-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/javascript/sonar-javascript-plugin/10.1.0.21143/sonar-javascript-plugin-10.1.0.21143.jar" - "Javascript plugin download URL." - :group 'lsp-sonarlint-javascript - :type 'string) - -(defcustom lsp-sonarlint-javascript-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-javascript.jar") - "Lsp-sonarlint javascript analyzer location." - :group 'lsp-sonarlint-javascript - :type 'file) - -(defvar lsp-sonarlint-javascript-doc-url "https://www.sonarsource.com/js/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-javascript-repository-url "https://github.com/SonarSource/SonarJS" - "Official sonarlint code extension repository.") - - - - - -(provide 'lsp-sonarlint-javascript) -;;; lsp-sonarlint-javascript.el ends here diff --git a/languages/php/lsp-sonarlint-php.el b/languages/php/lsp-sonarlint-php.el deleted file mode 100644 index f0d551a..0000000 --- a/languages/php/lsp-sonarlint-php.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; lsp-sonarlint-php.el --- lsp-sonarlint php module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint PHP plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-php nil - "lsp-sonarlint php analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-php . "3.28.0")) - -(defcustom lsp-sonarlint-php-enabled nil - "Enable lsp-sonarlint-php plugin." - :group 'lsp-sonarlint-php - :type 'boolean) - -(defcustom lsp-sonarlint-php-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/php/sonar-php-plugin/3.28.0.9490/sonar-php-plugin-3.28.0.9490.jar" - "Php plugin download URL." - :group 'lsp-sonarlint-php - :type 'string) - -(defcustom lsp-sonarlint-php-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-php.jar") - "Lsp-sonarlint php analyzer location." - :group 'lsp-sonarlint-php - :type 'file) - -(defvar lsp-sonarlint-php-doc-url "https://www.sonarsource.com/php/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-php-repository-url "https://github.com/SonarSource/sonar-php" - "Official sonarlint code extension repository.") - - - - - -(provide 'lsp-sonarlint-php) -;;; lsp-sonarlint-php.el ends here diff --git a/languages/python/lsp-sonarlint-python.el b/languages/python/lsp-sonarlint-python.el deleted file mode 100644 index b22f29d..0000000 --- a/languages/python/lsp-sonarlint-python.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; lsp-sonarlint-python.el --- lsp-sonarlint python module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint python plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-python nil - "lsp-sonarlint python analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-python . "4.2.0")) - -(defcustom lsp-sonarlint-python-enabled nil - "Enable lsp-sonarlint-python plugin." - :group 'lsp-sonarlint-python - :type 'boolean) - -(defcustom lsp-sonarlint-python-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/python/sonar-python-plugin/4.2.0.11487/sonar-python-plugin-4.2.0.11487.jar" - "Python plugin download URL." - :group 'lsp-sonarlint-python - :type 'string) - -(defcustom lsp-sonarlint-python-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-python.jar") - "Lsp-sonarlint python analyzer location." - :group 'lsp-sonarlint-python - :type 'file) - -(defvar lsp-sonarlint-python-doc-url "https://www.sonarsource.com/python/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-python-repository-url "https://github.com/SonarSource/sonar-python" - "Official sonarlint code extension repository.") - - - - - -(provide 'lsp-sonarlint-python) -;;; lsp-sonarlint-python.el ends here diff --git a/languages/text/lsp-sonarlint-text.el b/languages/text/lsp-sonarlint-text.el deleted file mode 100644 index 5909800..0000000 --- a/languages/text/lsp-sonarlint-text.el +++ /dev/null @@ -1,63 +0,0 @@ -;;; lsp-sonarlint-text.el --- lsp-sonarlint text module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint text plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-text nil - "lsp-sonarlint text analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-text . "2.0.1")) - -(defcustom lsp-sonarlint-text-enabled nil - "Enable lsp-sonarlint-text plugin." - :group 'lsp-sonarlint-text - :type 'boolean) - -(defcustom lsp-sonarlint-text-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/text/sonar-text-plugin/2.0.1.611/sonar-text-plugin-2.0.1.611.jar" - "Text plugin download URL." - :group 'lsp-sonarlint-text - :type 'string) - -(defcustom lsp-sonarlint-text-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-text.jar") - "Lsp-sonarlint text analyzer location." - :group 'lsp-sonarlint-text - :type 'file) - -(defvar lsp-sonarlint-text-doc-url "https://www.sonarsource.com/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-text-repository-url "https://github.com/SonarSource/sonar-text" - "Official sonarlint code extension repository.") - - - - - -(provide 'lsp-sonarlint-text) -;;; lsp-sonarlint-text.el ends here diff --git a/languages/typescript/lsp-sonarlint-typescript.el b/languages/typescript/lsp-sonarlint-typescript.el deleted file mode 100644 index 027da68..0000000 --- a/languages/typescript/lsp-sonarlint-typescript.el +++ /dev/null @@ -1,59 +0,0 @@ -;;; lsp-sonarlint-typescript.el --- lsp-sonarlint typescript module -*- lexical-binding: t; -*- - -;; Copyright (C) 2021 Gueorgui Tcherednitchenko -;; Author: Gueorgui Tcherednitchenko -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the sonarlint typescript plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-typescript nil - "lsp-sonarlint typescript analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-typescript . "10.1.0")) - -(defcustom lsp-sonarlint-typescript-enabled nil - "Enable lsp-sonarlint-typescript plugin." - :group 'lsp-sonarlint-typescript - :type 'boolean) - -(defcustom lsp-sonarlint-typescript-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/javascript/sonar-javascript-plugin/10.1.0.21143/sonar-javascript-plugin-10.1.0.21143.jar" - "Typescript plugin download URL." - :group 'lsp-sonarlint-typescript - :type 'string) - -(defcustom lsp-sonarlint-typescript-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-javascript.jar") ;; Note: it is the same as for javascript, and that is intentional - "Lsp-sonarlint typescript analyzer location." - :group 'lsp-sonarlint-typescript - :type 'file) - -(defvar lsp-sonarlint-typescript-doc-url "https://www.sonarsource.com/ts/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-typescript-repository-url "https://github.com/SonarSource/SonarJS" - "Official sonarlint code extension repository.") - -(provide 'lsp-sonarlint-typescript) -;;; lsp-sonarlint-typescript.el ends here diff --git a/languages/xml/lsp-sonarlint-xml.el b/languages/xml/lsp-sonarlint-xml.el deleted file mode 100644 index 6181ba1..0000000 --- a/languages/xml/lsp-sonarlint-xml.el +++ /dev/null @@ -1,60 +0,0 @@ -;;; lsp-sonarlint-xml.el --- lsp-sonarlint xml module -*- lexical-binding: t; -*- - -;; Copyright (C) 2020 Fermin Munoz -;; URL: https://gitlab.com/sasanidas/lsp-sonarlint -;; Keywords: languages - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: -;; Specific configuration for the SonarLint XML plugin. - -;; This is NOT and official SonarLint extension. - - -;;; Code: - -(defgroup lsp-sonarlint-xml nil - "lsp-sonarlint xml analyzer group" - :group 'lsp-sonarlint - :version '(lsp-sonarlint-xml . "2.7.0")) - -(defcustom lsp-sonarlint-xml-enabled nil - "Enable lsp-sonarlint-xml plugin." - :group 'lsp-sonarlint-xml - :type 'boolean) - -(defcustom lsp-sonarlint-xml-download-url - "https://repo.maven.apache.org/maven2/org/sonarsource/xml/sonar-xml-plugin/2.7.0.3820/sonar-xml-plugin-2.7.0.3820.jar" - "Xml plugin download URL." - :group 'lsp-sonarlint-xml - :type 'string) - -(defcustom lsp-sonarlint-xml-analyzer-path -(concat - (file-name-directory load-file-name) - "sonar-xml.jar") - "Lsp-sonarlint xml analyzer location." - :group 'lsp-sonarlint-xml - :type 'file) - -(defvar lsp-sonarlint-xml-doc-url "https://www.sonarsource.com/xml/" - "Documentation sonarsource URL.") - -(defvar lsp-sonarlint-xml-repository-url "https://github.com/SonarSource/sonar-xml" - "Official sonarlint code extension repository.") - - -(provide 'lsp-sonarlint-xml) -;;; lsp-sonarlint-xml.el ends here diff --git a/lsp-sonarlint.el b/lsp-sonarlint.el index 44e730d..24e978b 100644 --- a/lsp-sonarlint.el +++ b/lsp-sonarlint.el @@ -44,13 +44,22 @@ :link '(url-link "https://github.com/emacs-lsp/lsp-sonarlint") :package-version '(lsp-mode . "6.4")) -(defcustom lsp-sonarlint-server-path - (concat - (file-name-directory load-file-name) - "server/sonarlint-language-server.jar") - "SonarLint Language Server jar file location." +(defcustom lsp-sonarlint-download-url + (format "https://github.com/SonarSource/sonarlint-vscode/releases/download/4.6.0%%2B76435/sonarlint-vscode%s-4.6.0.vsix" + (pcase system-type + ('gnu/linux "-linux-x64") + ('darwin "-darwin-arm64") + ('windows-nt "-win32-x64"))) + "Official SonarLint VSCode extension (vsix). +It contains the necessary language server and analyzers." + :type 'string) + +(defcustom lsp-sonarlint-download-dir + (concat (file-name-directory load-file-name) "sonarlint-vscode") + "Location where VSCode's sonarlint extension should be found. +If absent, it will be downloaded from github and unzipped there." :group 'lsp-sonarlint - :type 'file) + :type 'directory) (defcustom lsp-sonarlint-modes-enabled '(php-mode go-mode @@ -62,6 +71,12 @@ typescript-mode typescript-tsx-mode python-mode + c-mode + c++-mode + c-or-c++-mode + c-ts-mode + c++-ts-mode + c-or-c++-ts-mode java-mode xml-mode nxml-mode) @@ -99,57 +114,158 @@ e.g. `-Xmx1024m`." :group 'lsp-sonarlint :type 'string) -(defcustom lsp-sonarlint-server-download-url - "https://repox.jfrog.io/repox/sonarsource/org/sonarsource/sonarlint/ls/sonarlint-language-server/2.19.0.72769/sonarlint-language-server-2.19.0.72769.jar" - "SonarLint Language Server jar file download URL." +(defcustom lsp-sonarlint-cfamily-compile-commands-path + "${workspaceFolder}/compile_commands.json" + "Location of the compile_commands.json file. +It is needed in C/C++ to provide your compilation options." :group 'lsp-sonarlint - :type 'string) + :type 'file) + +(defconst lsp-sonarlint-go-doc-url "https://www.sonarsource.com/go/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-go-repository-url "https://github.com/SonarSource/slang/" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-html-doc-url "https://www.sonarsource.com/html/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-html-repository-url "https://github.com/SonarSource/sonar-html" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-java-doc-url "https://www.sonarsource.com/java/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-java-repository-url "https://github.com/SonarSource/sonar-java" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-c-doc-url "https://www.sonarsource.com/c" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-c++-doc-url "https://www.sonarsource.com/cpp" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-javascript-doc-url "https://www.sonarsource.com/js/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-javascript-repository-url "https://github.com/SonarSource/SonarJS" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-php-doc-url "https://www.sonarsource.com/php/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-php-repository-url "https://github.com/SonarSource/sonar-php" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-python-doc-url "https://www.sonarsource.com/python/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-python-repository-url "https://github.com/SonarSource/sonar-python" + "Official sonarlint code extension repository.") -(defcustom lsp-sonarlint-plugin-autodownload nil - "Whether to go ahead and download missing plugins not asking for a confirmation. -Useful for batch testing." +(defconst lsp-sonarlint-text-doc-url "https://www.sonarsource.com/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-text-repository-url "https://github.com/SonarSource/sonar-text" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-typescript-doc-url "https://www.sonarsource.com/ts/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-typescript-repository-url "https://github.com/SonarSource/SonarJS" + "Official sonarlint code extension repository.") + +(defconst lsp-sonarlint-xml-doc-url "https://www.sonarsource.com/xml/" + "Documentation sonarsource URL.") + +(defconst lsp-sonarlint-xml-repository-url "https://github.com/SonarSource/sonar-xml" + "Official sonarlint code extension repository.") + +(defun lsp-sonarlint-download() + "Download the VSCode extension and unzips it. + +Follows the customizable variables : `lsp-sonarlint-download-url' and +`lsp-sonarlint-download-dir'" + (interactive) + (let* ((dest-dir (file-name-directory lsp-sonarlint-download-dir)) + (vsix-path (concat dest-dir "sonarlint.zip"))) + (unless (file-exists-p lsp-sonarlint-download-dir) + (unless (file-exists-p vsix-path) + (url-copy-file lsp-sonarlint-download-url vsix-path)) + (lsp-unzip vsix-path lsp-sonarlint-download-dir) + (if (file-exists-p lsp-sonarlint-download-dir) + (progn + (delete-file vsix-path) + (message "Sonarlint : successfully downloaded to %s" lsp-sonarlint-download-dir)) + + ;; For unzip issues on windows, see https://github.com/emacs-lsp/lsp-mode/issues/3022 + (warn "Could not unzip the VSCode extension, Either :\n\ +- Set `lsp-unzip-script' properly : on windows set it to `lsp-ext-pwsh-script'\n\ +- Download manually `lsp-sonarlint-download-url', unzip it, move it to `lsp-sonarlint-download-dir'"))))) + +(defcustom lsp-sonarlint-auto-download + nil + "If non nil, the analyzers will be downloaded at startup if needed. +See also `lsp-sonarlint-download-dir' and `lsp-sonarlint-download-url'." + :group 'lsp-sonarlint + :set (lambda (sym auto-download) ; Trigger download when set to non-nil + (set sym auto-download) + (when auto-download + (lsp-sonarlint-download))) :group 'lsp-sonarlint :type 'boolean) -(let ((languages-directory-path (concat (file-name-directory load-file-name) "languages"))) - (if (file-directory-p languages-directory-path) - (add-to-list 'load-path languages-directory-path) - (error "There was an error with the `load-file-name` function"))) - -(defun lsp-sonarlint--remove-duplicate-plugins (jars) - "Return copy of JARS with duplicates removed. -The duplicates may occur if the same plugin implements different languages, -for example sonar-javascript.jar covers both JavaScript and TypeScript. -If a duplicate occurs, SonarLint will throw an exception." - (cl-remove-duplicates jars :test #'equal :key (lambda (jar-path) (file-name-base jar-path)))) - -(defun lsp-sonarlint--plugin-list () - "Check for the enabled extensions and return a path list. -If the analyzer path is not a file, and -lsp-sonarlint-plugin-autodownload is not nil it offers to -download the analyzer, and does that." - (let* ((lsp-sonarlint--enabled-plugins - (-filter (lambda (member) - (when (eval - (intern (concat (format "%s" (car member) ) "-enabled"))) - t)) - (custom-group-members 'lsp-sonarlint t)))) - - (lsp-sonarlint--remove-duplicate-plugins - (-map (lambda (enabled-member) - (let* ((enabled-member--download-url - (eval (intern (concat (format "%s" (car enabled-member) ) "-download-url")))) - (enabled-member--analyzer-path - (eval (intern (concat (format "%s" (car enabled-member) ) "-analyzer-path"))))) - (unless (file-exists-p - enabled-member--analyzer-path) - (when (or lsp-sonarlint-plugin-autodownload - (yes-or-no-p - (format "%s language plugin not found, do you want to download it? " - (car enabled-member)))) - (url-copy-file enabled-member--download-url enabled-member--analyzer-path))) - enabled-member--analyzer-path)) - lsp-sonarlint--enabled-plugins)))) +(defcustom lsp-sonarlint-use-system-jre + nil + "Use the system java runtime instead of the one bundled in VSCode's extension." + :group 'lsp-sonarlint + :type 'boolean) + +(defcustom lsp-sonarlint-enabled-analyzers + 'all + "Specify which analyzers you want to enable. +- Use the \\='all symbol to enable all analyzers. +- Use a list of analyzer names if you only need a subset. In this case, +use `lsp-sonarlint-available-analyzers' to list available analyzers." + :group 'lsp-sonarlint + :type '(choice (const :tag "All analyzers" all) + (const :tag "No analyzer" nil) + (repeat :tag "A subset (see `lsp-sonarlint-available-analyzers')" string))) + +(defun lsp-sonarlint--extract-analyzer-name(analyzer-path) + "Extracts the analyzer name from ANALYZER-PATH" + (replace-regexp-in-string "sonar\\(lint\\)?" "" (file-name-base analyzer-path))) + +(defun lsp-sonarlint-available-analyzers() + "Return a list of the available analyzers." + (interactive) + (let* ((root-dir lsp-sonarlint-download-dir) + (plugin-dir (concat root-dir "/extension/analyzers")) + (plugin-paths (directory-files plugin-dir t ".jar")) + (plugin-names (mapcar #'lsp-sonarlint--extract-analyzer-name plugin-paths))) + (message "Analyzers found in %s : %s" plugin-dir plugin-names) + plugin-names)) + +(defun lsp-sonarlint--check-enabled-analyzer(analyzer) + "Return t if ANALYZER is enabled. +See `lsp-sonarlint-available-analyzers' and `lsp-sonarlint-enabled-analyzers'" + (let* ((analyzer-name (lsp-sonarlint--extract-analyzer-name analyzer))) + (pcase lsp-sonarlint-enabled-analyzers + ('all t) + (_ (seq-contains-p lsp-sonarlint-enabled-analyzers analyzer-name))))) + +(defun lsp-sonarlint-server-start-fun() + "Start lsp-sonarlint in stdio mode." + (let* ((root-dir lsp-sonarlint-download-dir) + (bundled-java-path (car (directory-files-recursively root-dir "java\\(.exe\\)?$"))) + (java-path (if lsp-sonarlint-use-system-jre "java" bundled-java-path)) + (jar-path (concat root-dir "/extension/server/sonarlint-ls.jar")) + (analyzer-dir (concat root-dir "/extension/analyzers")) + (analyzer-paths (directory-files analyzer-dir t ".jar")) + (enabled-analyzers (seq-filter #'lsp-sonarlint--check-enabled-analyzer analyzer-paths))) + (unless java-path + (warn "lsp-sonarlint : java is required and was not found on your system" :error)) + (-concat (list java-path "-jar" jar-path "-stdio" "-analyzers") enabled-analyzers))) (defun lsp-sonarlint--code-action-open-rule (_workspace params) "Create a buffer with rendered rule from PARAMS text in it. @@ -157,81 +273,113 @@ Extracts the title ahd htmlDescription, and renders the HTML in a temporary buffer." (with-temp-buffer (let* ((rule-title (format "

%s


" (ht-get params "name"))) - (rule-body (ht-get params "htmlDescription"))) + (rule-tab (aref (ht-get params "htmlDescriptionTabs") 0)) + (tab-section (ht-get rule-tab "ruleDescriptionTabNonContextual")) + (rule-body (ht-get tab-section "htmlContent"))) (insert rule-title) (insert "\n") (insert rule-body)) (shr-render-buffer (current-buffer)))) - -(defun lsp-sonarlint-server-start-fun (port) - "Start lsp-sonarlint in TCP mode listening to port PORT." - (-concat - `("java" "-jar" ,(eval lsp-sonarlint-server-path) ,(format "-port=%d" port)) - (mapcar (lambda (plugin-path) (format "-analyzers=%s" plugin-path)) - (lsp-sonarlint--plugin-list)))) - - -(defconst lsp-sonarlint--action-handlers '()) +(defun lsp-sonarlint--analyze-folder(dirname) + "Return t if DIRNAME should be analyzed. +i.e folders starting with '.' will be ignored" + (not (string= (substring (file-name-base dirname) 0 1) "."))) + +(defun lsp-sonarlint--list-files-in-folder (workspace _params) + "Respond to a listFilesInFolder request. +List all files of interest in WORKSPACE's directory. +See `lsp-sonarlint-analyze-folder' to see which files are ignored." + (let* ((root-dir (lsp--workspace-root workspace)) + (files (directory-files-recursively root-dir ".*" nil 'lsp-sonarlint--analyze-folder))) + (lsp-ht + ("foundFiles" + (apply 'vector + (mapcar (lambda(file) + (lsp-ht + ("fileName" (file-name-nondirectory file)) + ("filePath" file))) + files)))))) + +(defvar lsp-sonarlint--action-handlers '()) (lsp-register-custom-settings '(("sonarlint.disableTelemetry" lsp-sonarlint-disable-telemetry) ("sonarlint.testFilePattern" lsp-sonarlint-test-file-pattern) + ("sonarlint.pathToCompileCommands" lsp-sonarlint-cfamily-compile-commands-path) ("sonarlint.output.showAnalyzerLogs" lsp-sonarlint-show-analyzer-logs) ("sonarlint.output.verboseLogs" lsp-sonarlint-verbose-logs) ("sonarlint.ls.vmargs" lsp-sonarlint-vmargs))) -(defun lsp-sonarlint--request-handlers () +(defvar lsp-sonarlint--request-handlers + (lsp-ht + ;; Check whether the file should be analyzed or not + ;; This is typically to check if an open file is in an active workspace or not + ;; Let's assume here that the file should be analyzed + ("sonarlint/shouldAnalyseFile" (lambda (&rest _) + (lsp-ht + ("shouldBeAnalysed" t)))) + ;; Sonarlint sends those before to ask if you want to display a notification + ;; On what your environement is missing. e.g If you have an old version of nodejs. + ("sonarlint/canShowMissingRequirementsNotification" (lambda (&rest _) t)) + ;; For some reason, sonarlint requests the list of files in the folder + ;; VSCode's extension seems to send everything, even the .git folder. + ;; Here we give anything stored inside of the root directory, except + ;; hidden folders (in the unix sense, those which start with '.') + ("sonarlint/listFilesInFolder" #'lsp-sonarlint--list-files-in-folder) + ;; Sonarlint VSCode extension has a setting to specify a glob pattern + ;; of files to be excluded from analysis. + ;; We do not support this option at the moment, do not filter anything. + ("sonarlint/filterOutExcludedFiles" (lambda (_ params) params)) + ;; Check if the file is ignored by Source Control Manager (a.k.e. VCS, version control system). + ;; I think this is related to .gitignore and similar files. + ;; Probably safe to assume as a first step that you don't care, and want your diagnostics. + ;; TODO: implement a proper check here. + ("sonarlint/isIgnoredByScm" #'ignore) + ;; Probably only relevant to the java analyzer. + ;; Some additional java configuration for the project. + ;; TODO: implement + ("sonarlint/getJavaConfig" #'ignore)) + "SonarLint-specific request handlers. See REQUEST-HANDLERS in lsp--client in lsp-mode." - (let ((ht (make-hash-table :test 'equal))) - ;; Check whether the file is just being previewed or is actually open in an editor - ;; to save some wasted work. - ;; I guess it is safe to assume, when lsp-mode sends a file over to the server, - ;; it is because it is open in editor. - (puthash "sonarlint/isOpenInEditor" (lambda (_workspace _params) t) ht) - ;; Check if the file is ignored by Source Control Manager (a.k.e. VCS, version control system). - ;; I think this is related to .gitignore and similar files. - ;; Probably safe to assume as a first step that you don't care, and want your diagnostics. - ;; TODO: implement a proper check here. - (puthash "sonarlint/isIgnoredByScm" (lambda (_workspace _params) nil) ht) - ;; Get the VCS branch name. Let it be nil for now - ;; TODO: implement a proper response - (puthash "sonarlint/getBranchNameForFolder" (lambda (_workspace _params) nil) ht) - ;; Probably only relevant to the java analyzer. - ;; Some additional java configuration for the project. - ;; TODO: implement - (puthash "sonarlint/getJavaConfig" (lambda (_workspace _params) nil) ht) - ht)) - -(defun lsp-sonarlint--notification-handlers () + ) + +(defvar lsp-sonarlint--notification-handlers + (lsp-ht + ;; Security Hotspots are a special kind of issue that have particular + ;; interface on SonarCloud, SonarQube, and in SonarLint. See + ;; https://docs.sonarcloud.io/digging-deeper/security-hotspots/ I presume + ;; the PARAMS contain a list of issues of this category, similar to the + ;; normal issues. + ;; TODO: display them, perhaps optionally, as they could be noisy sometimes, + ;; especially without the possibility to "review" them once and forever. + ("sonarlint/publishSecurityHotspots" #'ignore) + ;; Sonarlint sends this to suggest the connected mode, and sends along + ;; your previous sonar projects. Connected mode is not currently implemented here. + ("sonarlint/suggestConnection" #'ignore) + ;; Not sure what this is for. Testing of SonarLint itself? + ("sonarlint/readyForTests" #'ignore) + ;; Sent by cfamily for analysis of C/C++ files. Sonar requires your + ;; build commands specified in a compile_commands.json + ("sonarlint/needCompilationDatabase" (lambda(&rest _) + (warn "Sonar could not find your compile_commands.json, please check `lsp-sonarlint-cfamily-compile-commands-path'"))) + ;; This is probably just to raise awareness of the new kind of issues: + ;; secrets. That'd be too booring to implement. Hopefully, the user is + ;; paying attention and will notice anyway. + ("sonarlint/showNotificationForFirstSecretsIssue" #'ignore) + ("sonarlint/showRuleDescription" #'lsp-sonarlint--code-action-open-rule)) + "SonarLint-specific notification handlers. -See NOTIFICATION-HANDLERS in lsp--client in lsp-mode." - (let ((ht (make-hash-table :test 'equal))) - ;; Security Hotspots are a special kind of issue that have particular - ;; interface on SonarCloud, SonarQube, and in SonarLint. See - ;; https://docs.sonarcloud.io/digging-deeper/security-hotspots/ I presume - ;; the PARAMS contain a list of issues of this category, similar to the - ;; normal issues. - ;; TODO: display them, perhaps optionally, as they could be noisy sometimes, - ;; especially without the possibility to "review" them once and forever. - (puthash "sonarlint/publishSecurityHotspots" (lambda (_workspace _params) nil) ht) - ;; Not sure what this is for. Testing of SonarLint itself? - (puthash "sonarlint/readyForTests" (lambda (_workspace _params) nil) ht) - ;; This is probably just to raise awareness of the new kind of issues: - ;; secrets. That'd be too booring to implement. Hopefully, the user is - ;; paying attention and will notice anyway. - (puthash "sonarlint/showNotificationForFirstSecretsIssue" (lambda (_workspace _params) nil) ht) - (puthash "sonarlint/showRuleDescription" #'lsp-sonarlint--code-action-open-rule ht) - ht)) +See NOTIFICATION-HANDLERS in lsp--client in lsp-mode.") (lsp-register-client (make-lsp-client - :new-connection (lsp-tcp-server-command 'lsp-sonarlint-server-start-fun) + :new-connection (lsp-stdio-connection #'lsp-sonarlint-server-start-fun) :major-modes lsp-sonarlint-modes-enabled :priority -1 - :request-handlers (lsp-sonarlint--request-handlers) - :notification-handlers (lsp-sonarlint--notification-handlers) + :request-handlers lsp-sonarlint--request-handlers + :notification-handlers lsp-sonarlint--notification-handlers :multi-root t :add-on? t :server-id 'sonarlint diff --git a/server/LICENSE b/server/LICENSE deleted file mode 100644 index 7a4a3ea..0000000 --- a/server/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/server/sonarlint-language-server.jar b/server/sonarlint-language-server.jar deleted file mode 100644 index 7daf4cd..0000000 Binary files a/server/sonarlint-language-server.jar and /dev/null differ diff --git a/test/lsp-sonarlint-integration-test.el b/test/lsp-sonarlint-integration-test.el index 38a73a9..722350a 100644 --- a/test/lsp-sonarlint-integration-test.el +++ b/test/lsp-sonarlint-integration-test.el @@ -51,12 +51,14 @@ If that does not happen within TIMEOUT, throw an error." (while (lsp-sonarlint--any-alive-workspaces-p) (accept-process-output nil 0.1)))) -(defun lsp-sonarlint--exec-with-diags (file knob-symbol diag-consumer) - "Execute DIAG-CONSUMER in the buffer holding FILE with KNOB-SYMBOL enabled. +(defun lsp-sonarlint--exec-with-diags (file diag-consumer major-mode) + "Execute DIAG-CONSUMER in the buffer holding FILE. DIAG-CONSUMER is executed once LSP has some diagnostics for the file, in the LSP-enabled buffer. DIAG-CONSUMER must accept 1 argument - the list of diagnostics. -It can perform further interaction with LSP, e.g., execute code actions." +It can perform further interaction with LSP, e.g., execute code actions. +The MAJOR-MODE triggering the analysis matters, because the cfamily analyzer +only works for specific textDocument/didOpen:languageId." ;; It is important to start from a clean slate. ;; If lsp-mode runs any servers already, the test might fall into a race condition, ;; when a server was requested to stop, but did not quite shut down yet, @@ -67,19 +69,10 @@ It can perform further interaction with LSP, e.g., execute code actions." (lsp-keep-workspace-alive nil) (dir (file-name-directory file)) (lsp-enable-snippet nil) - ;; Disable all plugins to focus only on the issues from the knob-symbol - (lsp-sonarlint-go-enabled nil) - (lsp-sonarlint-html-enabled nil) - (lsp-sonarlint-java-enabled nil) - (lsp-sonarlint-javascript-enabled nil) - (lsp-sonarlint-typescript-enabled nil) - (lsp-sonarlint-php-enabled nil) - (lsp-sonarlint-text-enabled nil) - (lsp-sonarlint-typescript-enabled nil) - (lsp-sonarlint-xml-enabled nil) received-warnings) (let ((buf (find-file-noselect file)) (lsp-sonarlint-plugin-autodownload t) + (diagnostics-updated nil) (register-warning (lambda (&rest w) (when (equal (car w) 'lsp-mode) (push (cadr w) received-warnings))))) (unwind-protect @@ -87,18 +80,17 @@ It can perform further interaction with LSP, e.g., execute code actions." (advice-add 'display-warning :before register-warning) (lsp-workspace-folders-add dir) (with-current-buffer buf - (cl-letf (((symbol-value knob-symbol) t)) - (python-mode) ;; Any prog mode that triggers lsp-sonarlint triggers all its analyzers - (lsp)) + (funcall major-mode) + (lsp) (lsp-sonarlint--wait-for (lambda () (when-let ((stats (lsp-diagnostics-stats-for file))) (when (< 0 (seq-reduce '+ stats 0)) - (setq diagnostics-updated t)))) + (setq diagnostics-updated (gethash file (lsp-diagnostics t)))))) 'lsp-diagnostics-updated-hook 40) (should (null received-warnings)) - (funcall diag-consumer (gethash file (lsp-diagnostics t))))) + (funcall diag-consumer diagnostics-updated))) (kill-buffer buf) (lsp-workspace-folders-remove dir) (advice-remove 'display-warning register-warning) @@ -120,72 +112,73 @@ It can perform further interaction with LSP, e.g., execute code actions." "Get the full path of the sample file FNAME." (concat (lsp-sonarlint--fixtures-dir) fname)) -(defun lsp-sonarlint--get-all-issue-codes (sample-filename knob-symbol) - "Get all SonarLint issue-codes for given SAMPLE-FILENAME with KNOB-SYMBOL on. +(defun lsp-sonarlint--get-all-issue-codes (sample-filename &optional major-mode) + "Get all SonarLint issue-codes for given SAMPLE-FILENAME. This functions takes some time to wait for the LSP mode to init -and get the issues from the server." +and get the issues from the server. +MAJOR-MODE specifies the major mode enabled to trigger the analysis. +Some analyzers like cfamily require specific major-modes. +If nil, use python-mode by default." (lsp-sonarlint--exec-with-diags - (lsp-sonarlint--sample-file sample-filename) knob-symbol + (lsp-sonarlint--sample-file sample-filename) (lambda (diags) - (lsp-sonarlint--get-codes-of-issues diags)))) + (lsp-sonarlint--get-codes-of-issues diags)) + (if major-mode major-mode 'python-mode))) (ert-deftest lsp-sonarlint-python-reports-issues () "Check that LSP can get Python SonarLint issues for a Python file." - (require 'lsp-sonarlint-python) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.py" 'lsp-sonarlint-python-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.py") '("python:S1135" "python:S1716")))) (ert-deftest lsp-sonarlint-java-reports-issues () "Check that LSP can get Java SonarLint issues for a Java file." - (require 'lsp-sonarlint-java) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.java" 'lsp-sonarlint-java-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.java") '("java:S106" "java:S1135" "java:S1220")))) (ert-deftest lsp-sonarlint-html-reports-issues () "Check that LSP can get HTML SonarLint issues for an HTML file." - (require 'lsp-sonarlint-html) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.html" 'lsp-sonarlint-html-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.html") '("Web:S1135")))) ;; javascript-sample.js must have a distinct name from sample.ts, ;; otherwise the javascript/typescript plugin gets confused. (ert-deftest lsp-sonarlint-js-reports-issues () "Check that LSP can get JavaScript SonarLint issues for a JavaScript file." - (require 'lsp-sonarlint-javascript) - (should (equal (lsp-sonarlint--get-all-issue-codes "javascript-sample.js" 'lsp-sonarlint-javascript-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "javascript-sample.js") '("javascript:S1134" "javascript:S1135")))) (ert-deftest lsp-sonarlint-ts-reports-issues () "Check that LSP can get TypeScript SonarLint issues for a TypeScript file." - (require 'lsp-sonarlint-typescript) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.ts" 'lsp-sonarlint-typescript-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.ts") '("typescript:S1134" "typescript:S1135")))) (ert-deftest lsp-sonarlint-php-reports-issues () "Check that LSP can get PHP SonarLint issues for a PHP file." - (require 'lsp-sonarlint-php) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.php" 'lsp-sonarlint-php-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.php") '("php:S1135" "php:S1780")))) (ert-deftest lsp-sonarlint-xml-reports-issues () "Check that LSP can get XML SonarLint issues for a XML file." - (require 'lsp-sonarlint-xml) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.xml" 'lsp-sonarlint-xml-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.xml") '("xml:S1135")))) ;; "text" plugin detects secrets and bidirectional unicode characters (ert-deftest lsp-sonarlint-text-reports-issues () "Check that LSP can detect Secrets with SonarLint." - (require 'lsp-sonarlint-text) - (should (equal (lsp-sonarlint--get-all-issue-codes "secrets.java" 'lsp-sonarlint-text-enabled) - '("secrets:S6290" "secrets:S6290" "secrets:S6290")))) + (let ((lsp-sonarlint-enabled-analyzers '("text"))) + (should (equal (lsp-sonarlint--get-all-issue-codes "secrets.java") + '("secrets:S6290" "secrets:S6290" "secrets:S6290"))))) (ert-deftest lsp-sonarlint-go-reports-issues () "Check that LSP can get go SonarLint issues for a go file." - (require 'lsp-sonarlint-go) - (should (equal (lsp-sonarlint--get-all-issue-codes "sample.go" 'lsp-sonarlint-go-enabled) + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.go") '("go:S1135")))) +(ert-deftest lsp-sonarlint-c++-reports-issues () + "Check that LSP can get go SonarLint issues for a C++ file." + (should (equal (lsp-sonarlint--get-all-issue-codes "sample.cpp" 'c++-mode) + '("cpp:S995")))) + (defun lsp-sonarlint--find-descr-action-at-point () "Find the 'get rule description' code action for the issue at point." (seq-find (lambda (action) (string-match-p "description" (gethash "title" action))) @@ -214,10 +207,8 @@ and get the issues from the server." (ert-deftest lsp-sonarlint-display-rule-descr-test () "Check whether you can display rule description for a SonarLint issue." - (require 'lsp-sonarlint-python) (lsp-sonarlint--exec-with-diags (lsp-sonarlint--sample-file "sample.py") - 'lsp-sonarlint-python-enabled (lambda (diags) (lsp-sonarlint--go-to-first-diag diags) (let ((descr-action (lsp-sonarlint--find-descr-action-at-point))) @@ -229,10 +220,12 @@ and get the issues from the server." (unwind-protect (progn (advice-add 'shr-render-buffer :before #'check-opened-buffer) + (sit-for 1) (lsp-execute-code-action descr-action) (with-timeout (8 (error "Timeout waiting for rule description")) (while (not description-opened) (message "still waiting") (sit-for 0.1))) (should description-opened)) - (advice-remove 'shr-render-buffer #'check-opened-buffer)))))))) + (advice-remove 'shr-render-buffer #'check-opened-buffer)))))) + 'python-mode))