Skip to content
This repository has been archived by the owner on Apr 18, 2022. It is now read-only.

Commit

Permalink
Enhance CC Mode's fontification, etc., of unterminated strings.
Browse files Browse the repository at this point in the history
String delimiters, including escaped new lines, of correctly terminated
strings are left in font-lock-string-face.  All others get
font-lock-warning-face.  The latter get syntax-table text properties on the
opening string delim and the "terminating EOL".

Correct two miscellaneous bugs: the handling of text properties on Java Mode's
generic delimiters; the handling of c-just-done-before-change.

* lisp/progmodes/cc-defs.el (c-point): New position 'eoll "end of logical line".
(c-characterp): New macro.

* lisp/progmodes/cc-fonts.el (c-font-lock-invalid-string): Removed.
(c-basic-matchers-before): Use a simple matcher in place of the form around
c-font-lock-invalid-string.

* lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Add
c-before-change-check-unbalanced-strings to the value for all modes except AWK
Mode.  Also add c-before-change-check-<>-operators to Java Mode, correcting an
error in that mode's handling of generic delimiters.
(c-before-font-lock-functions): Add c-after-change-re-mark-unbalanced-strings
to the value for all modes except AWK Mode.
(c-single-quotes-quote-strings, c-string-delims): New lang variables for
future enhancements.
(c-string-innards-re-alist): New lang variable.

* lisp/progmodes/cc-mode.el (c-just-done-before-change): Do not set this
variable when a change is the alteration of text properties.
(c-basic-common-init): Set parse-sexp-lookup-properties (and the XEmacs
equivalent) also for Pike Mode.
(c-neutralize-CPP-line): No longer neutralize unbalanced quotes here.
(c-unescaped-nls-in-string-p, c-multiline-string-start-is-being-detached)
(c-pps-to-string-delim, c-before-change-check-unbalanced-strings)
(c-after-change-re-mark-unbalanced-strings): New functions.
(c-after-change): Fix a bug with the handling of c-just-done-before-change.
  • Loading branch information
Alan Mackenzie committed May 20, 2018
1 parent e2f68c1 commit bb591f1
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 47 deletions.
18 changes: 18 additions & 0 deletions lisp/progmodes/cc-defs.el
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ one of the following symbols:
`bol' -- beginning of line
`eol' -- end of line
`eoll' -- end of logical line (i.e. without escaped NL)
`bod' -- beginning of defun
`eod' -- end of defun
`boi' -- beginning of indentation
Expand Down Expand Up @@ -254,6 +255,16 @@ to it is returned. This function does not modify the point or the mark."
(end-of-line)
(point))))

((eq position 'eoll)
`(save-excursion
,@(if point `((goto-char ,point)))
(while (progn
(end-of-line)
(prog1 (eq (logand 1 (skip-chars-backward "\\\\")) 1)))
(beginning-of-line 2))
(end-of-line)
(point)))

((eq position 'boi)
`(save-excursion
,@(if point `((goto-char ,point)))
Expand Down Expand Up @@ -453,6 +464,13 @@ to it is returned. This function does not modify the point or the mark."
`(int-to-char ,integer)
integer))

(defmacro c-characterp (arg)
;; Return t when ARG is a character (XEmacs) or integer (Emacs), otherwise
;; return nil.
(if (integerp ?c)
`(integerp ,arg)
`(characterp ,arg)))

(defmacro c-last-command-char ()
;; The last character just typed. Note that `last-command-event' exists in
;; both Emacs and XEmacs, but with confusingly different meanings.
Expand Down
35 changes: 2 additions & 33 deletions lisp/progmodes/cc-fonts.el
Original file line number Diff line number Diff line change
Expand Up @@ -682,33 +682,6 @@ stuff. Used on level 1 and higher."
''c-nonbreakable-space-face)))
))

(defun c-font-lock-invalid-string ()
;; Assuming the point is after the opening character of a string,
;; fontify that char with `font-lock-warning-face' if the string
;; decidedly isn't terminated properly.
;;
;; This function does hidden buffer changes.
(let ((start (1- (point))))
(save-excursion
(and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start)
(if (if (eval-when-compile (integerp ?c))
;; Emacs
(integerp c-multiline-string-start-char)
;; XEmacs
(characterp c-multiline-string-start-char))
;; There's no multiline string start char before the
;; string, so newlines aren't allowed.
(not (eq (char-before start) c-multiline-string-start-char))
;; Multiline strings are allowed anywhere if
;; c-multiline-string-start-char is t.
(not c-multiline-string-start-char))
(if c-string-escaped-newlines
;; There's no \ before the newline.
(not (eq (char-before (point)) ?\\))
;; Escaped newlines aren't supported.
t)
(c-put-font-lock-face start (1+ start) 'font-lock-warning-face)))))

(defun c-font-lock-invalid-single-quotes (limit)
;; This function will be called from font-lock for a region bounded by POINT
;; and LIMIT, as though it were to identify a keyword for
Expand Down Expand Up @@ -749,16 +722,12 @@ casts and declarations are fontified. Used on level 2 and higher."
;; `c-recognize-<>-arglists' is set.

t `(;; Put a warning face on the opener of unclosed strings that
;; can't span lines. Later font
;; can't span lines and on the "terminating" newlines. Later font
;; lock packages have a `font-lock-syntactic-face-function' for
;; this, but it doesn't give the control we want since any
;; fontification done inside the function will be
;; unconditionally overridden.
,(c-make-font-lock-search-function
;; Match a char before the string starter to make
;; `c-skip-comments-and-strings' work correctly.
(concat ".\\(" c-string-limit-regexp "\\)")
'((c-font-lock-invalid-string)))
("\\s|" 0 font-lock-warning-face t nil)

;; Invalid single quotes.
c-font-lock-invalid-single-quotes
Expand Down
48 changes: 45 additions & 3 deletions lisp/progmodes/cc-langs.el
Original file line number Diff line number Diff line change
Expand Up @@ -472,21 +472,24 @@ so that all identifiers are recognized as words.")
(c-lang-defconst c-get-state-before-change-functions
;; For documentation see the following c-lang-defvar of the same name.
;; The value here may be a list of functions or a single function.
t nil
t 'c-before-change-check-unbalanced-strings
c++ '(c-extend-region-for-CPP
c-before-change-check-raw-strings
c-before-change-check-<>-operators
c-depropertize-CPP
c-invalidate-macro-cache
c-truncate-bs-cache
c-before-change-check-unbalanced-strings
c-parse-quotes-before-change)
(c objc) '(c-extend-region-for-CPP
c-depropertize-CPP
c-invalidate-macro-cache
c-truncate-bs-cache
c-before-change-check-unbalanced-strings
c-parse-quotes-before-change)
java 'c-parse-quotes-before-change
;; 'c-before-change-check-<>-operators
java '(c-parse-quotes-before-change
c-before-change-check-unbalanced-strings
c-before-change-check-<>-operators)
awk 'c-awk-record-region-clear-NL)
(c-lang-defvar c-get-state-before-change-functions
(let ((fs (c-lang-const c-get-state-before-change-functions)))
Expand Down Expand Up @@ -514,21 +517,25 @@ parameters \(point-min) and \(point-max).")
;; For documentation see the following c-lang-defvar of the same name.
;; The value here may be a list of functions or a single function.
t '(c-depropertize-new-text
c-after-change-re-mark-unbalanced-strings
c-change-expand-fl-region)
(c objc) '(c-depropertize-new-text
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-extend-font-lock-region-for-macros
c-neutralize-syntax-in-CPP
c-change-expand-fl-region)
c++ '(c-depropertize-new-text
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-extend-font-lock-region-for-macros
c-after-change-re-mark-raw-strings
c-neutralize-syntax-in-CPP
c-restore-<>-properties
c-change-expand-fl-region)
java '(c-depropertize-new-text
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-restore-<>-properties
c-change-expand-fl-region)
awk '(c-depropertize-new-text
Expand Down Expand Up @@ -611,6 +618,19 @@ EOL terminated statements."
(c c++ objc) t)
(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields))

(c-lang-defconst c-single-quotes-quote-strings
"Whether the language uses single quotes for multi-char strings."
t nil)
(c-lang-defvar c-single-quotes-quote-strings
(c-lang-const c-single-quotes-quote-strings))

(c-lang-defconst c-string-delims
"A list of characters which can delimit arbitrary length strings"
t (if (c-lang-const c-single-quotes-quote-strings)
'(?\" ?\')
'(?\")))
(c-lang-defvar c-string-delims (c-lang-const c-string-delims))

(c-lang-defconst c-has-quoted-numbers
"Whether the language has numbers quoted like 4'294'967'295."
t nil
Expand Down Expand Up @@ -856,6 +876,28 @@ literal are multiline."
(c-lang-defvar c-multiline-string-start-char
(c-lang-const c-multiline-string-start-char))

(c-lang-defconst c-string-innards-re-alist
;; An alist of regexps matching the innards of a string, the key being the
;; string's delimiter.
;;
;; The regexps' matches extend up to, but not including, the closing string
;; delimiter or an unescaped NL. An EOL is part of the string only if it is
;; escaped.
t (mapcar (lambda (delim)
(cons
delim
(concat "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r"
(string delim)
"]\\)*")))
(and
(or (null (c-lang-const c-multiline-string-start-char))
(c-characterp (c-lang-const c-multiline-string-start-char)))
(if (c-lang-const c-single-quotes-quote-strings)
'(?\" ?\')
'(?\")))))
(c-lang-defvar c-string-innards-re-alist
(c-lang-const c-string-innards-re-alist))

(c-lang-defconst c-opt-cpp-symbol
"The symbol which starts preprocessor constructs when in the margin."
t "#"
Expand Down
Loading

0 comments on commit bb591f1

Please sign in to comment.