go-font-lock-test.el (8412B)
1 ;;; go-font-lock-test.el 2 3 ;; Copyright 2019 The go-mode Authors. All rights reserved. Use of 4 ;; this source code is governed by a BSD-style license that can be 5 ;; found in the LICENSE file. 6 7 (require 'ert) 8 (require 'go-mode) 9 (require 'cl-lib) 10 11 (ert-deftest go--fontify-signature () 12 (go--should-fontify "KfuncK FfooF() { }") 13 (go--should-fontify "KfuncK FfooF(TaT) { }") 14 (go--should-fontify "KfuncK FfooF(TaT, TbT) { }") 15 (go--should-fontify "KfuncK FfooF(TaT) TaT { }") 16 (go--should-fontify "KfuncK FfooF(VaV TbT) (VaV TbT) { }") 17 (go--should-fontify "KfuncK FfooF(VaV, VbV TcT) (VaV TbT, VcV TdT) { }") 18 19 (go--should-fontify "KfuncK (TbT) FfooF(VaV, VbV TcT) TdT { }") 20 (go--should-fontify "KfuncK (VaV TbT) FfooF(VaV TbT) (TdT) { }") 21 22 (go--should-fontify "VfooV := KfuncK(VaV TbT) TcT { }") 23 24 (go--should-fontify "KfuncK(...TintT) { }") 25 (go--should-fontify "KfuncK(VaV ...TintT) { }") 26 (go--should-fontify "KfuncK(VaV ...KinterfaceK{}) { }") 27 28 (go--should-fontify "KfuncK(KinterfaceK { FfooF() }, TstringT) KinterfaceK{}") 29 30 (go--should-fontify "KfuncK(VaV TbT, VcV KfuncK(VdV *TeT) TdT) TfT") 31 (go--should-fontify "KfuncK(VaV KfuncK() TbT, VcV TdT)") 32 33 (go--should-fontify " 34 KfuncK FfooF( 35 VaV TcatT, VbV KinterfaceK { FbarkF() }, 36 VcV TbananaT, 37 ) ( 38 VwhyV TdothisT, 39 VjustV TstopT, 40 ) { }") 41 42 (go--should-fontify " 43 D// DQ 44 QD// DQ( 45 QKfuncK (VfV TintT) {} 46 ")) 47 48 (ert-deftest go--fontify-struct () 49 (go--should-fontify "KstructK { i TintT }") 50 (go--should-fontify "KstructK { a, b TintT }") 51 52 (go--should-fontify " 53 KstructK { 54 a TboolT 55 c KstructK { f *Tfoo.ZebraT } 56 }")) 57 58 (ert-deftest go--fontify-interface () 59 (go--should-fontify " 60 KinterfaceK { 61 FfooF(VaV, VbV TcT) *TstringT 62 }") 63 64 (go--should-fontify " 65 KinterfaceK { 66 FfooF(KinterfaceK { FaF() TintT }) (VcV TdT) 67 }") 68 69 (go--should-fontify " 70 KmapK[TstringT]KinterfaceK{}{ 71 S`foo`S: foo.FbarF(baz), 72 }")) 73 74 75 (ert-deftest go--fontify-type-switch () 76 (go--should-fontify " 77 KswitchK foo.(KtypeK) { 78 KcaseK TstringT, *Tfoo.ZebraT, [2]TbyteT: 79 KcaseK CnilC: 80 KcaseK TfooT, TbarT, D// DQhi 81 Q 82 D// DQthere 83 Q TbazT, TquxT: 84 KdefaultK: 85 }") 86 87 (go--should-fontify " 88 KswitchK foo.(KtypeK) { 89 KcaseK KinterfaceK { FfooF(TintT, TstringT) }, KstructK { i, j TintT }, TstringT: 90 }") 91 92 (go--should-fontify " 93 KswitchK 123 { 94 KcaseK string: 95 }")) 96 97 (ert-deftest go--fontify-composite-literal () 98 (go--should-fontify "TfooT{") 99 (go--should-fontify "[]TfooT{") 100 (go--should-fontify "Tfoo.ZarT{") 101 (go--should-fontify "[]Tfoo.ZarT{") 102 103 (go--should-fontify "TfooT{CbarC:baz, CquxC: 123}") 104 105 (go--should-fontify "TfooT{ 106 CbarC: baz, 107 }") 108 109 (go--should-fontify "[]TfooT{{ 110 CbarC: baz, 111 }, { 112 CbarC: baz, 113 }}") 114 115 (go--should-fontify "TsomeMapT{ 116 foo.Zar: baz, 117 a + b: 3, 118 a-b: 4, 119 }")) 120 121 (ert-deftest go--fontify-slices-arrays-maps () 122 (go--should-fontify "[]TfooT") 123 (go--should-fontify "[]Tfoo.ZarT") 124 (go--should-fontify "[]*Tfoo.ZarT") 125 126 (go--should-fontify "[123]TfooT") 127 (go--should-fontify "[...]TfooT") 128 (go--should-fontify "[foo.Zar]TfooT") 129 (go--should-fontify "D/*DQhi*/Q[1]*TfooT") 130 131 (go--should-fontify "KmapK[*Tfoo.ZarT]*Tbar.ZarT") 132 (go--should-fontify "[]KmapK[TfooT]TbarT") 133 (go--should-fontify "KmapK[[1][2][three]*Tfoo.ZarT][four][]*Tbar.ZarT") 134 (go--should-fontify "KmapK[TstringT]KmapK[TstringT]Tfloat64T") 135 (go--should-fontify "KmapK[[2][c]*TintT]TboolT")) 136 137 (ert-deftest go--fontify-negation () 138 ;; Fontify unary "!". 139 (go--should-fontify "N!Nfoo") 140 141 ;; Alternate fontification with multiple "!". 142 (go--should-fontify "N!N!foo") 143 (go--should-fontify "N!N!N!Nfoo") 144 145 ;; Don't fontify "!=" operator. 146 (go--should-fontify "foo != bar")) 147 148 149 (ert-deftest go--fontify-type-decl () 150 (go--should-fontify "KtypeK TfooT TbarT") 151 (go--should-fontify "KtypeK TfooT Tbar.ZarT") 152 (go--should-fontify "KtypeK TfooT KstructK { }") 153 (go--should-fontify "KtypeK TfooT = Tbar.ZarT") 154 (go--should-fontify "KtypeK TfooT = KmapK[TstringT]TstringT") 155 156 (go--should-fontify " 157 KtypeK ( 158 TfooT TbarT 159 TfooT KstructK {} 160 TfooT = *Tbar.ZarT 161 )")) 162 163 (ert-deftest go--fontify-var-decl () 164 (go--should-fontify "KvarK VfooV = bar") 165 (go--should-fontify "KvarK VfooV, VbarV = bar, baz") 166 (go--should-fontify "KvarK VfooV TbarT D// DQcoolQ") 167 (go--should-fontify "KvarK VfooV TbarT = baz") 168 (go--should-fontify "KvarK VfooV KstructK { i TintT } = baz") 169 (go--should-fontify "KvarK VfooV []*Tfoo.ZarT D// DQcoolQ") 170 171 (go--should-fontify " 172 KvarK ( 173 VfooV TbarT 174 VfooV KfuncK(ViV TintT) 175 VfooV = bar 176 VfooV TbarT = baz 177 VfooV, VbarV = baz, qux 178 VfooV, VbarV TbazT = qux, zorb 179 )")) 180 181 (ert-deftest go--fontify-const-decl () 182 (go--should-fontify "KconstK CfooC, CbarC = 123, 456 D// D") 183 (go--should-fontify "KconstK CfooC, CbarC TbazT = 123, 456") 184 (go--should-fontify " 185 KconstK ( 186 CaC = 1 187 CaC TintT = 1 188 CaC, CbC TintT = 1, 2 189 )")) 190 191 (ert-deftest go--fontify-labels () 192 (go--should-fontify " 193 CfooC: 194 KforK { 195 KcontinueK CfooC 196 KbreakK CfooC 197 KgotoK CfooC 198 } 199 ")) 200 201 (ert-deftest go--fontify-assign () 202 (go--should-fontify "VfooV := bar") 203 (go--should-fontify "foo = bar D// DQ:=Q") 204 (go--should-fontify "VfooV, VbarV := baz, qux") 205 (go--should-fontify "foo, bar = baz, qux") 206 (go--should-fontify "KfuncK FfooF(ViV TintT) { VbarV := baz }")) 207 208 (ert-deftest go--fontify-index-multiply () 209 (go--should-fontify "foo[1]*10 + 1") 210 (go--should-fontify "foo[1]*foo[2] + 1")) 211 212 (ert-deftest go--fontify-go-dot-mod () 213 (go--should-fontify " 214 KmoduleK foo 215 216 KgoK 1.13 217 218 KrequireK ( 219 Nexample.com/require/go/bananaN Sv12.34.56SV-1234-456abcV D// DQindirect 220 Q Nnoslash.devN Sv1.2.3S 221 ) 222 223 KreplaceK ( 224 Nfoo.example.com/barN Sv1.2.3S => Nfoo.example.com/barN Sv1.2.3S 225 Nexample.com/foo/barN => Nexample.com/baz/barN Sv0.0.0SV-20201112005413-933910cbaea0V 226 ) 227 " 'go-dot-mod-mode)) 228 229 (defun go--should-match-face (want-face) 230 (let ((got-face (get-text-property (point) 'face))) 231 (if (not (eq got-face want-face)) 232 (progn 233 (message "char '%s' (%s): wanted %s, got %s" (char-to-string (char-after)) (point) want-face got-face) 234 nil) 235 t))) 236 237 (defun go--should-fontify (contents &optional mode) 238 "Verify fontification. 239 240 CONTENTS is a template that uses single capital letters to 241 represent expected font lock face names. For example: 242 243 BmakeB([]TintT, 0) 244 245 expects \"make\" to be a (B)uiltin and \"int\" to be a (T)type." 246 (with-temp-buffer 247 (setq mode (or mode 'go-mode)) 248 (funcall mode) 249 (insert contents) 250 (goto-char (point-min)) 251 252 ;; First pass through buffer looks for the face tags. We delete 253 ;; the tags and record the expected face ranges in `faces'. 254 (let ((case-fold-search nil) faces start start-pos) 255 (while (re-search-forward "[TBKCFSNVDQ]" nil t) 256 (let ((found-char (char-before))) 257 (backward-delete-char 1) 258 (if start 259 (progn 260 (should (= found-char start)) 261 (let ((face (cl-case found-char 262 (?T 'font-lock-type-face) 263 (?B 'font-lock-builtin-face) 264 (?K 'font-lock-keyword-face) 265 (?C 'font-lock-constant-face) 266 (?F 'font-lock-function-name-face) 267 (?S (if (eq mode 'go-mode) 'font-lock-string-face 'go-dot-mod-module-semver)) 268 (?N (if (eq mode 'go-mode) 'font-lock-negation-char-face 'go-dot-mod-module-name)) 269 (?V (if (eq mode 'go-mode) 'font-lock-variable-name-face 'go-dot-mod-module-version)) 270 (?D 'font-lock-comment-delimiter-face) 271 (?Q 'font-lock-comment-face)))) 272 (setq faces (append faces `((,face ,start-pos ,(point)))))) 273 (setq start nil)) 274 (setq start found-char) 275 (setq start-pos (point))))) 276 277 ;; Fontify buffer now that we have removed the tags. 278 (font-lock-fontify-buffer) 279 (goto-char (point-min)) 280 281 ;; Go through buffer one character at a time making sure the 282 ;; character's face is correct. 283 (let ((face (pop faces))) 284 (while (not (eobp)) 285 (while (and face (>= (point) (nth 2 face))) 286 (setq face (pop faces))) 287 (if (and face (>= (point) (nth 1 face))) 288 (should (go--should-match-face (nth 0 face))) 289 (should (go--should-match-face nil))) 290 (forward-char))))))