diff options
| author | Wilfred Hughes <me@wilfred.me.uk> | 2015-12-30 11:24:35 +0000 |
|---|---|---|
| committer | Wilfred Hughes <me@wilfred.me.uk> | 2016-01-05 23:57:01 +0000 |
| commit | dd6d417c1404efcf2364a61fd7e855ec134a991f (patch) | |
| tree | b03e0b6d9fb33d7287c3867c6c77990e095705ca | |
| parent | 061e6d8a3a9104570144f1eacb729e3211cb03cd (diff) | |
| download | rust-mode-dd6d417c1404efcf2364a61fd7e855ec134a991f.tar.gz | |
Fix type annotations incorrectly highlighted as modules.
Previously, we were always treating :: as a module, but Rust
allows type annotations using :: e.g.
parse::<i32>();
This also changes module highlighting so that only the module name is
highlighted, excluding the ::. This makes rust-mode consistent with
other Emacs modes, such as c++-mode and ruby-mode.
| -rw-r--r-- | rust-mode-tests.el | 21 | ||||
| -rw-r--r-- | rust-mode.el | 20 |
2 files changed, 39 insertions, 2 deletions
diff --git a/rust-mode-tests.el b/rust-mode-tests.el index e7a0429..e41245f 100644 --- a/rust-mode-tests.el +++ b/rust-mode-tests.el @@ -1403,6 +1403,27 @@ this_is_not_a_string();)" "\"/*! doc */\"" '("\"/*! doc */\"" font-lock-string-face))) +(ert-deftest font-lock-module () + (rust-test-font-lock + "foo::bar" + '("foo" font-lock-type-face))) + +(ert-deftest font-lock-submodule () + (rust-test-font-lock + "foo::bar::baz" + '("foo" font-lock-type-face + "bar" font-lock-type-face))) + +(ert-deftest font-lock-type-annotation () + "Ensure type annotations are not confused with modules." + (rust-test-font-lock + "parse::<i32>();" + ;; Only the i32 should have been highlighted. + '("i32" font-lock-type-face)) + (rust-test-font-lock + "foo:: <i32>" + ;; Only the i32 should have been highlighted. + '("i32" font-lock-type-face))) (ert-deftest indent-method-chains-no-align () (let ((rust-indent-method-chain nil)) (test-indent diff --git a/rust-mode.el b/rust-mode.el index 8049273..4697c70 100644 --- a/rust-mode.el +++ b/rust-mode.el @@ -14,6 +14,7 @@ ;;; Code: (eval-when-compile (require 'rx) + (require 'cl) (require 'compile) (require 'url-vars)) @@ -525,6 +526,21 @@ function or trait. When nil, where will be aligned with fn or trait." (concat "\\_<" (regexp-opt words t) "\\_>")) (defconst rust-re-special-types (regexp-opt-symbols rust-special-types)) + +(defun rust-module-font-lock-matcher (limit) + "Matches module names \"foo::\" but does not match type annotations \"foo::<\"." + (block nil + (while t + (let* ((symbol-then-colons (rx-to-string `(seq (group (regexp ,rust-re-ident)) "::"))) + (match (re-search-forward symbol-then-colons limit t))) + (cond + ;; If we didn't find a match, there are no more occurrences + ;; of foo::, so return. + ((null match) (return nil)) + ;; If this isn't a type annotation foo::<, we've found a + ;; match, so a return it! + ((not (looking-at (rx (0+ space) "<"))) (return match))))))) + (defvar rust-mode-font-lock-keywords (append `( @@ -548,8 +564,8 @@ function or trait. When nil, where will be aligned with fn or trait." ;; Field names like `foo:`, highlight excluding the : (,(concat (rust-re-grab rust-re-ident) ":[^:]") 1 font-lock-variable-name-face) - ;; Module names like `foo::`, highlight including the :: - (,(rust-re-grab (concat rust-re-ident "::")) 1 font-lock-type-face) + ;; Module names like `foo::`, highlight excluding the :: + (rust-module-font-lock-matcher 1 font-lock-type-face) ;; Lifetimes like `'foo` (,(concat "'" (rust-re-grab rust-re-ident) "[^']") 1 font-lock-variable-name-face) |
