Skip to content

Commit

Permalink
rust-cargo checks tests, examples and benches targets
Browse files Browse the repository at this point in the history
Previously, `rust-cargo` was unable to check integration tests and other
optional Cargo targets.  For a description of the conventional Cargo layout,
see:

http://doc.crates.io/manifest.html#the-project-layout

This commits enhances `rust-cargo` to check all files under the conventional
layout, by using `flycheck-rust-crate-type` as the target type, and
`flycheck-rust-binary-name` as the target name.

In addition, it adds :enabled and :verify properties to `rust-cargo` to ensure
these variables are correctly set, and to inform the user in case they are not.

Integration tests are added to check the support for the full conventional
layout.
  • Loading branch information
fmdkdd committed Feb 14, 2017
1 parent 3943b4c commit d348ded
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
Expand Up @@ -24,6 +24,10 @@
``g`` reloads the buffer.
- Make sure the erlang compiler is only run on compilable files.
- ``flycheck-tslint`` does not crash any more on deprecation notices [GH-1174]
- ``rust-cargo`` now checks integration tests, examples and benchmarks
[GH-1206]
- ``rust-cargo`` does not use ``flycheck-rust-library-path`` anymore, as
dependencies are taken care of by Cargo [GH-1206]

30 (Oct 12, 2016)
=================
Expand Down
16 changes: 11 additions & 5 deletions doc/languages.rst
Expand Up @@ -964,15 +964,21 @@ to view the docstring of the syntax checker. Likewise, you may use

.. defcustom:: flycheck-rust-crate-type

The type of the crate to check, as string for the ``--crate-type``
option.
For `rust-cargo`, the target type as a string, one of ``lib``, ``bin``,
``example``, ``test`` or ``bench``.

For `rust`, the type of the crate to check, as a string for the
``--crate-type`` option.

.. defcustom:: flycheck-rust-binary-name

The name of the binary to pass to ``cargo rustc --bin``, as a string.
The name of the binary to pass to ``cargo rustc --TARGET-TYPE``, as a
string.

For `rust-cargo`, always required unless `flycheck-rust-crate-type` is
``lib``, in which case it is ignored.

Only required when `flycheck-rust-crate-type` is ``bin`` and the crate
has multiple targets.
Ignored by `rust`.

.. defcustom:: flycheck-rust-library-path

Expand Down
90 changes: 68 additions & 22 deletions flycheck.el
Expand Up @@ -700,7 +700,7 @@ This variable is a normal hook. See Info node `(elisp)Hooks'."
"Functions to run if the Flycheck status changed.

This hook is run whenever the status of Flycheck changes. Each
hook function takes the status symbol as sinlge argument, as
hook function takes the status symbol as single argument, as
given to `flycheck-report-status', which see.

This variable is a abnormal hook. See Info
Expand Down Expand Up @@ -2468,7 +2468,7 @@ buffer-local value of `flycheck-disabled-checkers'."

Set `flycheck-current-syntax-check' accordingly."
;; Allocate the current syntax check *before* starting it. This allows for
;; synchronous checks, which call the status callback immediately in there
;; synchronous checks, which call the status callback immediately in their
;; start function.
(let* ((check (flycheck-syntax-check-new
:buffer (current-buffer)
Expand Down Expand Up @@ -8766,28 +8766,35 @@ if it is not modified, i.e. after it has been saved."
(flycheck-def-option-var flycheck-rust-crate-type "lib" (rust-cargo rust)
"The type of the Rust Crate to check.

The value of this variable is a string denoting the crate type,
for the `--crate-type' flag."
For `rust-cargo', the value should be a string denoting the
target type passed to Cargo. See
`flycheck-rust-valid-crate-type-p' for the list of allowed
values.

For `rust', the value should be a string denoting the crate type
for the `--crate-type' flag of rustc."
:type 'string
:safe #'stringp
:package-version '(flycheck . "0.20"))
(make-variable-buffer-local 'flycheck-rust-crate-type)

(flycheck-def-option-var flycheck-rust-binary-name nil rust-cargo
"The name of the binary to pass to `cargo rustc --bin'.
"The name of the binary to pass to `cargo rustc --CRATE-TYPE'.

The value of this variable is a string denoting the name of the
binary to build: Either the name of the crate, or the name of one
of the files under `src/bin'.
target to check: usually the name of the crate, or the name of
one of the files under `src/bin', `tests', `examples' or
`benches'.

This variable is used only when `flycheck-rust-crate-type' is
`bin', and is only useful for crates with multiple targets."
This always requires a non-nil value, unless
`flycheck-rust-crate-type' is `lib', in which case it is
ignored."
:type 'string
:safe #'stringp
:package-version '(flycheck . "28"))
(make-variable-buffer-local 'flycheck-rust-binary-name)

(flycheck-def-option-var flycheck-rust-library-path nil (rust-cargo rust)
(flycheck-def-option-var flycheck-rust-library-path nil rust
"A list of library directories for Rust.

The value of this variable is a list of strings, where each
Expand All @@ -8812,32 +8819,71 @@ Relative paths are relative to the file being checked."
(flycheck-error-message err)))
errors))

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

A valid Cargo target type is one of `lib', `bin', `example',
`test' or `bench'."
(member crate-type '("lib" "bin" "example" "test" "bench")))

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

This syntax checker requires Rust 1.15 or newer. See URL
`https://www.rust-lang.org'."
:command ("cargo" "rustc"
(eval (cond
((string= flycheck-rust-crate-type "lib") "--lib")
(flycheck-rust-binary-name
(list "--bin" flycheck-rust-binary-name))))
(eval (concat "--" flycheck-rust-crate-type))
;; All crate targets except "lib" need a binary name
(eval (unless (string= flycheck-rust-crate-type "lib")
flycheck-rust-binary-name))
"--message-format=json"
(eval flycheck-cargo-rustc-args)
"--" "-Z" "no-trans"
(option-flag "--test" flycheck-rust-check-tests)
(option-list "-L" flycheck-rust-library-path concat)
;; Passing the "--test" flag when the target is a test binary or
;; bench is unnecessary and triggers an error.
(eval (when flycheck-rust-check-tests
(unless (member flycheck-rust-crate-type '("test" "bench"))
"--test")))
(eval flycheck-rust-args))
:error-parser flycheck-parse-cargo-rustc
:error-filter flycheck-rust-error-filter
:error-explainer flycheck-rust-error-explainer
:modes rust-mode
:predicate (lambda ()
;; Since we build the entire project with cargo rustc we require
;; that the buffer is saved. And of course, we also need a Cargo
;; file :)
(and (flycheck-buffer-saved-p)
(locate-dominating-file (buffer-file-name) "Cargo.toml"))))
:predicate flycheck-buffer-saved-p
:enabled (lambda ()
(and (locate-dominating-file (buffer-file-name) "Cargo.toml")
(flycheck-rust-valid-crate-type-p flycheck-rust-crate-type)
(or (string= flycheck-rust-crate-type "lib")
flycheck-rust-binary-name)))
:verify (lambda (_)
(let* ((toml (locate-dominating-file
(buffer-file-name) "Cargo.toml"))
(crate-type flycheck-rust-crate-type)
(valid-crate-type
(flycheck-rust-valid-crate-type-p crate-type))
(bin-name flycheck-rust-binary-name)
(lib (string= crate-type "lib")))
(list
(flycheck-verification-result-new
:label "Cargo.toml"
:message (if toml "Found" "Missing")
:face (if toml 'success '(bold warning)))
(flycheck-verification-result-new
:label "Crate type"
:message (if valid-crate-type crate-type
(format "%s (invalid, should be one of 'lib', 'bin', 'test', 'example' or 'bench')"
crate-type))
:face (if valid-crate-type 'success '(bold error)))
(flycheck-verification-result-new
:label "Binary name"
:message (cond
(lib "Not required")
((not bin-name) "Unset")
(t (format "%S" flycheck-rust-binary-name)))
:face (cond
(lib 'success)
((not bin-name) '(bold error))
(t 'success)))))))

(flycheck-define-checker rust
"A Rust syntax checker using Rust compiler.
Expand Down
65 changes: 64 additions & 1 deletion test/flycheck-test.el
Expand Up @@ -3867,7 +3867,8 @@ Why not:
:checker ruby-jruby))))

(flycheck-ert-def-checker-test rust-cargo rust warning
(let ((flycheck-rust-crate-type "bin"))
(let ((flycheck-rust-crate-type "bin")
(flycheck-rust-binary-name "flycheck-test"))
(flycheck-ert-should-syntax-check
"language/rust/flycheck-test/src/warnings.rs" 'rust-mode
'(3 1 warning "function is never used: `main`, #[warn(dead_code)] on by default"
Expand All @@ -3881,6 +3882,68 @@ Why not:
(flycheck-ert-should-syntax-check
"language/rust/lib-main/src/main.rs" 'rust-mode)))

(flycheck-ert-def-checker-test rust-cargo rust conventional-layout
(let ((flycheck-rust-crate-type "lib"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/src/lib.rs" 'rust-mode
'(3 1 warning "function is never used: `foo_lib`, #[warn(dead_code)] on by default"
:checker rust-cargo)
'(6 17 warning "unused variable: `foo_lib_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "lib"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/src/a.rs" 'rust-mode
'(1 1 warning "function is never used: `foo_a`, #[warn(dead_code)] on by default"
:checker rust-cargo)
'(4 17 warning "unused variable: `foo_a_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "bin")
(flycheck-rust-binary-name "cargo-targets"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/src/main.rs" 'rust-mode
'(1 17 warning "unused variable: `foo_main`, #[warn(unused_variables)] on by default"
:checker rust-cargo)
'(4 17 warning "unused variable: `foo_main_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "bin")
(flycheck-rust-binary-name "a"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/src/bin/a.rs" 'rust-mode
'(1 17 warning "unused variable: `foo_bin_a`, #[warn(unused_variables)] on by default"
:checker rust-cargo)
'(4 17 warning "unused variable: `foo_bin_a_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "bench")
(flycheck-rust-binary-name "a"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/benches/a.rs" 'rust-mode
'(1 17 warning "unused variable: `foo_bench_a`, #[warn(unused_variables)] on by default"
:checker rust-cargo)
'(4 17 warning "unused variable: `foo_bench_a_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "test")
(flycheck-rust-binary-name "a"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/tests/a.rs" 'rust-mode
'(2 16 warning "unused variable: `foo_test_a_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo)
'(4 1 warning "function is never used: `foo_test_a`, #[warn(dead_code)] on by default"
:checker rust-cargo)))

(let ((flycheck-rust-crate-type "example")
(flycheck-rust-binary-name "a"))
(flycheck-ert-should-syntax-check
"language/rust/cargo-targets/examples/a.rs" 'rust-mode
'(1 17 warning "unused variable: `foo_ex_a`, #[warn(unused_variables)] on by default"
:checker rust-cargo)
'(4 17 warning "unused variable: `foo_ex_a_test`, #[warn(unused_variables)] on by default"
:checker rust-cargo))))

(flycheck-ert-def-checker-test rust rust syntax-error
(let ((flycheck-disabled-checkers '(rust-cargo)))
(flycheck-ert-should-syntax-check
Expand Down
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions test/resources/language/rust/cargo-targets/Cargo.toml
@@ -0,0 +1,3 @@
[package]
name = "cargo-targets"
version = "0.1.0"
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/benches/a.rs
@@ -0,0 +1,4 @@
fn main() { let foo_bench_a = 0; }

#[test]
fn test() { let foo_bench_a_test = 0; }
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/examples/a.rs
@@ -0,0 +1,4 @@
fn main() { let foo_ex_a = 0; }

#[test]
fn test() { let foo_ex_a_test = 0; }
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/src/a.rs
@@ -0,0 +1,4 @@
fn foo_a() {}

#[test]
fn test() { let foo_a_test = 0; }
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/src/bin/a.rs
@@ -0,0 +1,4 @@
fn main() { let foo_bin_a = 0; }

#[test]
fn test() { let foo_bin_a_test = 0; }
6 changes: 6 additions & 0 deletions test/resources/language/rust/cargo-targets/src/lib.rs
@@ -0,0 +1,6 @@
mod a;

fn foo_lib() {}

#[test]
fn test() { let foo_lib_test = 0; }
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/src/main.rs
@@ -0,0 +1,4 @@
fn main() { let foo_main = 0; }

#[test]
fn test() { let foo_main_test = 0; }
4 changes: 4 additions & 0 deletions test/resources/language/rust/cargo-targets/tests/a.rs
@@ -0,0 +1,4 @@
#[test]
fn foo() { let foo_test_a_test = 0; }

fn foo_test_a() {}

0 comments on commit d348ded

Please sign in to comment.