emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/go-mode c020e2c 456/495: Fontify type names in more places


From: ELPA Syncer
Subject: [nongnu] elpa/go-mode c020e2c 456/495: Fontify type names in more places.
Date: Sat, 7 Aug 2021 09:06:08 -0400 (EDT)

branch: elpa/go-mode
commit c020e2cba0f9684cc060cbbdc492d9a470420bf4
Author: Muir Manders <muir@mnd.rs>
Commit: Peter Sanford <psanford@sanford.io>

    Fontify type names in more places.
    
    We now fontify type names in var decls, const decls, and struct
    definitions:
    
    var foo, bar *string*
    
    const baz *float64* = 123.4
    
    type blah struct { foo *string* }
    
    We achieve this with a dumb check that essentially just looks for
    "<go-ident>[[:space:]]+<go-type-name>", but with some extra logic to
    ignore keywords. This takes advantage of the fact that when you have
    two identifiers separated by whitespace, the second is always(?) a
    type name.
    
    Fixes #256, fixes #51
    
    Closes: #307 [via git-merge-pr]
---
 go-mode.el                |  43 +++++++++++++++++++-
 test/go-font-lock-test.el | 100 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/go-mode.el b/go-mode.el
index e16556c..3cad755 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -410,9 +410,20 @@ For mode=set, all covered lines will have this weight."
   ;; we cannot use 'symbols in regexp-opt because GNU Emacs <24
   ;; doesn't understand that
   (append
-   `((go--match-func
+   `(
+     ;; Fontify types in function signatures.
+     (go--match-func
+      ;; The signature logic is "anchored" to a "func" keyword, so
+      ;; `go--match-func' must match all signature types in a single
+      ;; invocation since it can't remember if it is inside a "func"
+      ;; across invocations. So, it must have an explicit limit on the
+      ;; number of sub-expressions.
       ,@(mapcar (lambda (x) `(,x font-lock-type-face))
                 (number-sequence 1 go--font-lock-func-param-num-groups)))
+
+     ;; Fontify types in e.g. "var foo string".
+     (go--match-ident-type-pair 1 font-lock-type-face)
+
      (,(concat "\\_<" (regexp-opt go-mode-keywords t) "\\_>") . 
font-lock-keyword-face)
      (,(concat "\\(\\_<" (regexp-opt go-builtins t) "\\_>\\)[[:space:]]*(") 1 
font-lock-builtin-face)
      (,(concat "\\_<" (regexp-opt go-constants t) "\\_>") . 
font-lock-constant-face)
@@ -1257,6 +1268,36 @@ of last search.  Return t if search succeeded."
           (set-match-data (go--make-match-data regions))
           t)))))
 
+(defun go--match-ident-type-pair (end)
+  "Search for identifier + type-name pairs.
+
+For example, this looks for the \"foo bar\" in \"var foo bar\",
+yielding match-data for \"bar\" since that is a type name to be
+fontified. This approach matches type names in var and const
+decls, and in struct definitions. Return non-nil if search
+succeeds."
+  (let (type-names found-match)
+    ;; Find the starting ident, e.g. "foo" in "var foo bar".
+    (while (and
+            (not found-match)
+            (re-search-forward (concat "\\_<" go-identifier-regexp "\\_>") end 
t))
+      (cond
+       ;; Skip keywords, such as the "var" in "var foo bar".
+       ((member (match-string 0) go-mode-keywords))
+
+       ;; If our identifier is followed by a space.
+       ((> (skip-syntax-forward " ") 0)
+        (when (and
+               ;; And it looks like a type name.
+               (looking-at go-type-name-regexp)
+               ;; And it isn't a keyword.
+               (not (member (match-string 1) go-mode-keywords)))
+          (setq found-match t)))))
+
+    ;; Return whether we found an ident/type pair. match-data will be
+    ;; that of the final looking-at call.
+    found-match))
+
 (defun go--match-func-type-names (end)
   (cond
    ;; Function declaration (e.g. "func foo(")
diff --git a/test/go-font-lock-test.el b/test/go-font-lock-test.el
new file mode 100644
index 0000000..96f33ed
--- /dev/null
+++ b/test/go-font-lock-test.el
@@ -0,0 +1,100 @@
+;;; go-indentation-test.el
+
+;; Copyright 2019 The go-mode Authors. All rights reserved. Use of
+;; this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+
+(require 'ert)
+(require 'go-mode)
+(require 'cl-lib)
+
+(ert-deftest go--fontify-signature ()
+  (should-fontify "KfuncK FfooF() { }")
+  (should-fontify "KfuncK FfooF(TaT) { }")
+  (should-fontify "KfuncK FfooF(TaT, TbT) { }")
+  (should-fontify "KfuncK FfooF(TaT) TaT { }")
+  (should-fontify "KfuncK FfooF(a TbT) (a TbT) { }")
+  (should-fontify "KfuncK FfooF(a, b TcT) (a TbT, c TdT) { }")
+
+  (should-fontify "KfuncK (TbT) FfooF(a, b TcT) TdT { }")
+  (should-fontify "KfuncK (a TbT) FfooF(a TbT) (TdT) { }")
+
+  (should-fontify "foo := KfuncK(a TbT) TcT { }"))
+
+(ert-deftest go--fontify-decls ()
+  (should-fontify "KvarK foo TintT")
+  (should-fontify "KvarK foo *[3]TintT")
+  (should-fontify "KvarK foo Tfmt.StringerT")
+  (should-fontify "KvarK foo, bar Tfmt.StringerT")
+
+  (should-fontify "
+KvarK (
+  a TbT
+  a, b TbT
+  a KfuncK(b TcT)
+)")
+
+  (should-fontify "
+KconstK (
+  a = 1
+  a TintT = 1
+)"))
+
+(ert-deftest go--fontify-struct ()
+  (should-fontify "KstructK { i TintT }")
+  (should-fontify "KstructK { a, b TintT }")
+
+  (should-fontify "
+KstructK {
+  a TboolT
+  c KstructK { f *Tfmt.StringerT }
+}"))
+
+(defun should-fontify (contents)
+  "Verify fontification.
+
+CONTENTS is a template that uses single capital letters to
+represent expected font lock face names. For example:
+
+BmakeB([]TintT, 0)
+
+expects \"make\" to be a (B)uiltin and \"int\" to be a (T)type."
+  (with-temp-buffer
+    (go-mode)
+    (insert contents)
+    (goto-char (point-min))
+
+    ;; First pass through buffer looks for the face tags. We delete
+    ;; the tags and record the expected face ranges in `faces'.
+    (let ((case-fold-search nil) faces start start-pos)
+      (while (re-search-forward "[TBKCF]" nil t)
+        (let ((found-char (char-before)))
+          (backward-delete-char 1)
+          (if start
+              (progn
+                (should (= found-char start))
+                (let ((face (cl-case found-char
+                              (?T 'font-lock-type-face)
+                              (?B 'font-lock-builtin-face)
+                              (?K 'font-lock-keyword-face)
+                              (?C 'font-lock-constant-face)
+                              (?F 'font-lock-function-name-face))))
+                  (setq faces (append faces `((,face ,start-pos ,(point))))))
+                (setq start nil))
+            (setq start found-char)
+            (setq start-pos (point)))))
+
+      ;; Fontify buffer now that we have removed the tags.
+      (font-lock-fontify-buffer)
+      (goto-char (point-min))
+
+      ;; Go through buffer one character at a time making sure the
+      ;; character's face is correct.
+      (let ((face (pop faces)))
+        (while (not (eobp))
+          (while (and face (>= (point) (nth 2 face)))
+            (setq face (pop faces)))
+          (if (and face (>= (point) (nth 1 face)))
+              (should (eq (nth 0 face) (get-text-property (point) 'face)))
+            (should (eq nil (get-text-property (point) 'face))))
+          (forward-char))))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]