Skip to content

Commit

Permalink
Merge pull request #1385 from flycheck/add-cargo-clippy
Browse files Browse the repository at this point in the history
Add cargo clippy
  • Loading branch information
fmdkdd committed Feb 11, 2018
2 parents 0648dd5 + 2f29e2f commit f61a9dc
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Expand Up @@ -16,6 +16,7 @@
- Tcl with ``nagelfar`` [GH-1365]
- CWL with ``schema-salad-tool`` [GH-1361]
- MarkdownLint CLI with ``markdownlint`` [GH-1366]
- Rust with ``rust-clippy`` [GH-1385]

- New features:

Expand Down
8 changes: 7 additions & 1 deletion doc/languages.rst
Expand Up @@ -1028,21 +1028,27 @@ to view the docstring of the syntax checker. Likewise, you may use
.. supported-language:: Rust

Flycheck checks Rust_ with `rust-cargo` in Cargo projects, or `rust`
otherwise.
otherwise. For Cargo projects, you can also use the clippy_ linter with
`rust-clippy`.

.. _Rust: https://www.rust-lang.org/
.. _clippy: https://github.com/rust-lang-nursery/rust-clippy

.. syntax-checker:: rust-cargo
rust
rust-clippy

Check syntax and types with the Rust_ compiler. In a Cargo_ project the
compiler is invoked through ``cargo check`` to take Cargo dependencies
into account.

`rust-clippy` has no configurable options.

.. note::

`rust-cargo` requires Rust 1.17 or newer.
`rust` requires Rust 1.7 or newer.
`rust-clippy` requires the nightly version of Rust.

.. _Cargo: http://doc.crates.io/index.html

Expand Down
87 changes: 70 additions & 17 deletions flycheck.el
Expand Up @@ -238,6 +238,7 @@ attention to case differences."
ruby-jruby
rust-cargo
rust
rust-clippy
scala
scala-scalastyle
scheme-chicken
Expand Down Expand Up @@ -4711,7 +4712,7 @@ the syntax checker definition, if the variable is nil."
(flycheck-checker-default-executable checker))))

(defun flycheck-find-checker-executable (checker)
"Get the full path of the executbale of CHECKER.
"Get the full path of the executable of CHECKER.

Return the full absolute path to the executable of CHECKER, or
nil if the executable does not exist."
Expand Down Expand Up @@ -5786,7 +5787,7 @@ https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139"
;; Turn each span into a flycheck error
(dolist (span spans)
(let-alist span
;; Children lack any filename/line/column information, so we use
;; Children may not have filename/line/column information, so we use
;; those from the primary span
(when .is_primary
(setq primary-filename .file_name
Expand All @@ -5813,16 +5814,27 @@ https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs#L67-L139"
errors)))

;; Then we turn children messages into flycheck errors pointing to the
;; location of the primary span. According to the format, children
;; may contain spans, but they do not seem to use them in practice.
;; location of the primary span.
(dolist (child children)
(let-alist child
(push
(flycheck-error-new-at
primary-line
primary-column
;; Use the line/column from the first span if there is one, or
;; fallback to the line/column information from the primary span of
;; the diagnostic.
(or (cdr (assq 'line_start (car .spans)))
primary-line)
(or (cdr (assq 'column_start (car .spans)))
primary-column)
'info
.message
;; Messages from `cargo clippy' may suggest replacement code. In
;; these cases, the `message' field itself is an unhelpful `try' or
;; `change this to'. We add the `suggested_replacement' field in
;; these cases.
(-if-let (replacement
(cdr (assq 'suggested_replacement (car .spans))))
(format "%s: `%s`" .message replacement)
.message)
:id error-code
:checker checker
:buffer buffer
Expand Down Expand Up @@ -9375,6 +9387,24 @@ Relative paths are relative to the file being checked."
(flycheck-error-message err)))
errors))

(defun flycheck-rust-manifest-directory ()
"Return the nearest directory holding the Cargo manifest.

Return the nearest directory containing the `Cargo.toml' manifest
file, starting from the current buffer and using
`locate-dominating-file'. Return nil if there is no such file,
or if the current buffer has no file name."
(and buffer-file-name
(locate-dominating-file buffer-file-name "Cargo.toml")))

(defun flycheck-rust-cargo-has-command-p (command)
"Whether Cargo has COMMAND in its list of commands.

Execute `cargo --list' to find out whether COMMAND is present."
(let ((cargo (funcall flycheck-executable-find "cargo")))
(member command (mapcar #'string-trim-left
(ignore-errors (process-lines cargo "--list"))))))

(defun flycheck-rust-valid-crate-type-p (crate-type)
"Whether CRATE-TYPE is a valid target type for Cargo.

Expand Down Expand Up @@ -9406,19 +9436,12 @@ This syntax checker requires Rust 1.17 or newer. See URL
:error-explainer flycheck-rust-error-explainer
:modes rust-mode
:predicate flycheck-buffer-saved-p
:enabled
(lambda ()
(and buffer-file-name
(locate-dominating-file buffer-file-name "Cargo.toml")))
:working-directory
(lambda (_)
(and buffer-file-name
(locate-dominating-file buffer-file-name "Cargo.toml")))
:enabled flycheck-rust-manifest-directory
:working-directory (lambda (_) (flycheck-rust-manifest-directory))
:verify
(lambda (_)
(and buffer-file-name
(let* ((has-toml (locate-dominating-file
buffer-file-name "Cargo.toml"))
(let* ((has-toml (flycheck-rust-manifest-directory))
(valid-crate-type (flycheck-rust-valid-crate-type-p
flycheck-rust-crate-type))
(need-binary-name
Expand Down Expand Up @@ -9466,6 +9489,36 @@ This syntax checker needs Rust 1.7 or newer. See URL
:modes rust-mode
:predicate flycheck-buffer-saved-p)

(flycheck-define-checker rust-clippy
"A Rust syntax checker using clippy.

See URL `https://github.com/rust-lang-nursery/rust-clippy'."
:command ("cargo" "+nightly" "clippy" "--message-format=json")
:error-parser flycheck-parse-cargo-rustc
:error-filter flycheck-rust-error-filter
:error-explainer flycheck-rust-error-explainer
:modes rust-mode
:predicate flycheck-buffer-saved-p
:enabled (lambda ()
(and (flycheck-rust-cargo-has-command-p "clippy")
(flycheck-rust-manifest-directory)))
:working-directory (lambda (_) (flycheck-rust-manifest-directory))
:verify
(lambda (_)
(and buffer-file-name
(let ((has-toml (flycheck-rust-manifest-directory))
(has-clippy (flycheck-rust-cargo-has-command-p "clippy")))
(list
(flycheck-verification-result-new
:label "Clippy"
:message (if has-clippy "Found"
"Cannot find the `cargo clippy' command")
:face (if has-clippy 'success '(bold warning)))
(flycheck-verification-result-new
:label "Cargo.toml"
:message (if has-toml "Found" "Missing")
:face (if has-toml 'success '(bold warning))))))))

(defvar flycheck-sass-scss-cache-directory nil
"The cache directory for `sass' and `scss'.")

Expand Down
6 changes: 5 additions & 1 deletion test/specs/test-documentation.el
@@ -1,5 +1,6 @@
;;; test-documentation.el --- Flycheck Specs: Documentation -*- lexical-binding: t; -*-

;; Copyright (C) 2018 Flycheck contributors
;; Copyright (C) 2013-2016 Sebastian Wiesner and Flycheck contributors

;; Author: Sebastian Wiesner <swiesner@lunaryorn.com>
Expand Down Expand Up @@ -40,12 +41,15 @@
(let ((match (intern (match-string 1))))
(cl-pushnew match matches))
(-when-let (match (match-string 2))
(cl-pushnew (intern match) matches))
(-when-let (match (match-string 3))
(cl-pushnew (intern match) matches))))
matches))

(defconst flycheck/checker-re
(rx bol " .. syntax-checker:: " (group (1+ nonl)) "\n"
(? " " (group (1+ nonl)) eol)))
(? " " (group (1+ nonl)) "\n")
(? " " (group (1+ nonl))) eol))

(defconst flycheck/defcustom-re
(rx bol " .. defcustom:: " (group (1+ nonl)) "\n"
Expand Down

0 comments on commit f61a9dc

Please sign in to comment.