Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion swift-mode-font-lock.el
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ Example: #if, #endif, and #selector."
"Face for highlighting property accesses."
:group 'swift-mode:faces)

(defface swift-mode:negation-char-face
'((t . (:inherit font-lock-negation-char-face)))
"Face for highlighting the negation char."
:group 'swift-mode:faces)

(defun swift-mode:make-set (list)
"Return a hash where its keys are elements of the LIST.
Expand Down Expand Up @@ -660,7 +664,12 @@ Excludes true, false, and keywords begin with a number sign.")
;; Property accesses
(swift-mode:font-lock-match-property-access
.
'swift-mode:property-access-face))
'swift-mode:property-access-face)

;; Make negation chars easier to see
("\\(?:^\\|\\s-\\|\\s(\\|\\s>\\|[,:;]\\)\\(!+\\)[^=]"
1
'swift-mode:negation-char-face))
"Swift mode keywords for Font Lock.")


Expand Down
51 changes: 51 additions & 0 deletions test/swift-files/font-lock/font-lock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Negation characters.
//

//
// These "!" should be identified as negation chars.
//

if !foo {} // #("if !foo {}" 0 2 (face swift-mode:keyword-face) 3 4 (face swift-mode:negation-char-face))

if !!!!!foo {} // #("if !!!!!foo {}" 0 2 (face swift-mode:keyword-face) 3 8 (face swift-mode:negation-char-face))

if !!!!!(foo) {} // #("if !!!!!(foo) {}" 0 2 (face swift-mode:keyword-face) 3 8 (face swift-mode:negation-char-face))

if (!foo) {} // #("if (!foo) {}" 0 2 (face swift-mode:keyword-face) 4 5 (face swift-mode:negation-char-face))

let x = [!a,!b] // #("let x = [!a,!b]" 0 3 (face swift-mode:keyword-face) 9 10 (face swift-mode:negation-char-face) 12 13 (face swift-mode:negation-char-face))

let x = [a:!b] // #("let x = [a:!b]" 0 3 (face swift-mode:keyword-face) 11 12 (face swift-mode:negation-char-face))

//
// These "!" should NOT be identified as negation chars.
//

try! foo // #("try! foo" 0 3 (face swift-mode:keyword-face))

foo as! Foo // #("foo as! Foo" 4 6 (face swift-mode:keyword-face))

foo != bar // "foo != bar"

foo !== bar // "foo !== bar"

a.b.c! // #("a.b.c!" 4 5 (face swift-mode:property-access-face))

a.b.c_! // #("a.b.c_!" 4 5 (face swift-mode:property-access-face))

a.b.aあ! // #("a.b.a\343\201\202!" 4 8 (face swift-mode:property-access-face))

init! {} // #("init! {}" 0 4 (face swift-mode:keyword-face))

let foo: Foo! = bar // #("let foo: Foo! = bar" 0 3 (face swift-mode:keyword-face))

let x = foo()! // #("let x = foo()!" 0 3 (face swift-mode:keyword-face) 8 11 (face swift-mode:function-call-face))

let x = foo[0]! // #("let x = foo[0]!" 0 3 (face swift-mode:keyword-face))

// Identifiers can be quoted.
a.b.`c`! // #("a.b.`c`!" 4 7 (face font-lock-string-face))

// Custom operators.
foo +!+!+!+!+ bbb // "foo +!+!+!+!+ bbb"
102 changes: 102 additions & 0 deletions test/swift-mode-test-font-lock.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
;;; swift-mode-test-font-lock.el --- Test for swift-mode: font-lock -*- lexical-binding: t -*-

;; Copyright (C) 2020 Daniel Martín

;; Authors: Daniel Martín (http://github.com/taku0)

;; This file is not part of GNU Emacs.

;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Test for swift-mode: font-lock.
;; Execute swift-mode:run-test:font-lock interactively or in batch mode.

;;; Code:

(require 'swift-mode)
(require 'swift-mode-font-lock)

(defun swift-mode:run-test:font-lock
(&optional error-buffer error-counts progress-reporter)
"Run font-lock test for `swift-mode'.

ERROR-BUFFER is the buffer to output errors.
ERROR-COUNTS is a association list holding counts of errors. Updated
destructively.
PROGRESS-REPORTER is the progress-reporter."
(interactive)
(if (not swift-mode:test:running)
(swift-mode:run-test '(swift-mode:run-test:font-lock))
(let ((current-line 0))
(setq default-directory
(concat (file-name-as-directory swift-mode:test:basedir)
(file-name-as-directory "swift-files")
"font-lock"))

(dolist (swift-file (file-expand-wildcards "*.swift"))
(redisplay)
(with-temp-buffer
(switch-to-buffer (current-buffer))
(insert-file-contents-literally swift-file)
(swift-mode)
(font-lock-fontify-buffer)
(setq current-line 0)
(while (not (eobp))
(when (not noninteractive)
(progress-reporter-update progress-reporter))
(setq current-line (1+ current-line))
(cond
((= (line-beginning-position) (line-end-position))
;; Empty line
nil)
((looking-at-p "//.*")
;; Ignore comments
nil)
(t
(let*
((status (swift-mode:test-current-line-font-lock
swift-file current-line error-buffer))
(count-assoc (assq status error-counts)))
(setcdr count-assoc (1+ (cdr count-assoc))))))
(forward-line)))))))

(defun swift-mode:test-current-line-font-lock
(swift-file current-line error-buffer)
"Compute the font-lock properties applied by swift-mode on current line.

SWIFT-FILE is the filename of the current test case.
CURRENT-LINE is the current line number.
ERROR-BUFFER is the buffer to output errors."
(let ((status 'ok))
(when (looking-at "\\(.*\\)[ /t]+//[ /t]+\\(.*\\)")
(let ((actual-props (format "%S" (buffer-substring (match-beginning 1) (match-end 1))))
(expected-props (buffer-substring-no-properties (match-beginning 2)
(match-end 2))))
(when (not (string-equal expected-props actual-props))
(setq status 'error)
(swift-mode:show-error
error-buffer swift-file current-line
"error"
(concat
"font-lock: expected "
(prin1-to-string expected-props)
" but "
(prin1-to-string actual-props))))))
status))

(provide 'swift-mode-test-font-lock)

;;; swift-mode-test-font-lock.el ends here
4 changes: 3 additions & 1 deletion test/swift-mode-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
(require 'swift-mode-test-indent)
(require 'swift-mode-test-beginning-of-defun)
(require 'swift-mode-test-imenu)
(require 'swift-mode-test-font-lock)

(defvar swift-mode:test:basedir
(file-name-directory (or load-file-name buffer-file-name)))
Expand All @@ -48,7 +49,8 @@ Return the error-buffer"
(defvar swift-mode:tests
'(swift-mode:run-test:indent
swift-mode:run-test:beginning-of-defun
swift-mode:run-test:imenu))
swift-mode:run-test:imenu
swift-mode:run-test:font-lock))

(defun swift-mode:run-test (&optional tests)
"Run TESTS for `swift-mode'."
Expand Down