From: Alan Mackenzie <acm@muc.de>
To: 36136@debbugs.gnu.org
Subject: bug#36136: [PATCH]: Re: bug#36136: syntax-ppss fails to invalidate its cache on changes to syntax-table text properties
Date: Sat, 8 Jun 2019 20:36:39 +0000 [thread overview]
Message-ID: <20190608203639.GA28722@ACM> (raw)
In-Reply-To: <20190608131724.GA4643@ACM>
Hello, Emacs.
On Sat, Jun 08, 2019 at 13:17:24 +0000, Alan Mackenzie wrote:
> The syntax-ppss cache is not invalidated when syntax-table text
> properties are set or cleared. This is because the invalidation
> function, syntax-ppss-flush-cache is invoked only as a before-change
> function, but typical (?all) syntax-table property changes happen when
> before-change-functions is inactive.
> This is a bug.
> In my debugging of a CC Mode scenario, a buffer change causes a
> syntax-table text property change at an earlier part of the buffer. This
> is to do with the change making previously non-matching C++ raw string
> identifiers match up. Font lock follows the syntax-ppss state, which
> spuriously records that the end part of the buffer is still in a string.
> Hence the non-string part of the buffer is still fontified with
> font-lock-string-face.
> Suggested fix: the functions set_properties, add_properties,
> remove_properties in textprop.c should check for changes to,
> specifically, syntax-table properties. When these changes are detected,
> a hook called something like syntax-table-props-change-alert-hook should
> be called (with some appropriate position parameters, tbd).
> syntax-ppss-flush-cache will be added to this hook.
Here is a first draught of a fix to this bug.
It creates a new abnormal hook,
syntax-table-props-change-alert-functions, whose member functions are
called each time a syntax-table text property is changed.
syntax-ppss-flush-cache is inserted into this new hook at loading time
for syntax.el, thus invalidating the syntax-ppss cache each time a
syntax-table text property is changed.
There is a consequential amendment to the doc string of
inhibit-modification-hooks.
This fixes the original problem.
Comments?
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index 9c6d5b5829..673d598de6 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -43,6 +43,10 @@
(eval-when-compile (require 'cl-lib))
+;; Ensure that the cache gets invalidated when `syntax-table' text
+;; properties get set, even when `inhibit-modification-hooks' is non-nil.
+(add-hook 'syntax-table-props-change-alert-functions #'syntax-ppss-flush-cache)
+
;;; Applying syntax-table properties where needed.
(defvar syntax-propertize-function nil
diff --git a/src/insdel.c b/src/insdel.c
index 85fffd8fd1..5e978d1b29 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -2360,9 +2360,11 @@ syms_of_insdel (void)
Vcombine_after_change_calls = Qnil;
DEFVAR_BOOL ("inhibit-modification-hooks", inhibit_modification_hooks,
- doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
+ doc: /* Non-nil means don't run most of the hooks that respond to buffer changes.
This affects `before-change-functions' and `after-change-functions',
-as well as hooks attached to text properties and overlays.
+as well as most hooks attached to text properties and overlays.
+However the hook `syntax-table-props-change-alert-functions' gets run
+regardless of the setting of this variable.
Setting this variable non-nil also inhibits file locks and checks
whether files are locked by another Emacs session, as well as
handling of the active region per `select-active-regions'. */);
diff --git a/src/textprop.c b/src/textprop.c
index ae42c44185..050bb7b435 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -334,7 +334,10 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), XCAR (value),
object);
- }
+ if (EQ (sym, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (interval->position));
+ }
/* For each new property that has no value at all in the old plist,
make an undo record binding it to nil, so it will be removed. */
@@ -346,6 +349,9 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), Qnil,
object);
+ if (EQ (sym, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (interval->position));
}
}
@@ -400,7 +406,10 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
{
record_property_change (i->position, LENGTH (i),
sym1, Fcar (this_cdr), object);
- }
+ if (EQ (sym1, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (i->position));
+ }
/* I's property has a different value -- change it */
if (set_type == TEXT_PROPERTY_REPLACE)
@@ -436,6 +445,9 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
{
record_property_change (i->position, LENGTH (i),
sym1, Qnil, object);
+ if (EQ (sym1, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (i->position));
}
set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist)));
changed = true;
@@ -470,9 +482,14 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
while (CONSP (current_plist) && EQ (sym, XCAR (current_plist)))
{
if (BUFFERP (object))
- record_property_change (i->position, LENGTH (i),
- sym, XCAR (XCDR (current_plist)),
- object);
+ {
+ record_property_change (i->position, LENGTH (i),
+ sym, XCAR (XCDR (current_plist)),
+ object);
+ if (EQ (sym, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (i->position));
+ }
current_plist = XCDR (XCDR (current_plist));
changed = true;
@@ -486,8 +503,13 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
if (CONSP (this) && EQ (sym, XCAR (this)))
{
if (BUFFERP (object))
- record_property_change (i->position, LENGTH (i),
- sym, XCAR (XCDR (this)), object);
+ {
+ record_property_change (i->position, LENGTH (i),
+ sym, XCAR (XCDR (this)), object);
+ if (EQ (sym, Qsyntax_table))
+ CALLN (Frun_hook_with_args, Qsyntax_table_props_change_alert_functions,
+ make_fixnum (i->position));
+ }
Fsetcdr (XCDR (tail2), XCDR (XCDR (this)));
changed = true;
@@ -2319,6 +2341,20 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
Vtext_property_default_nonsticky
= list2 (Fcons (Qsyntax_table, Qt), Fcons (Qdisplay, Qt));
+ DEFVAR_LISP ("syntax-table-props-change-alert-functions",
+ Vsyntax_table_props_change_alert_functions,
+ doc: /* List of functions to call each time a `syntax-table' text property
+gets added, removed, or changed.
+
+Each function is passed a single parameter, the buffer position of the
+start of the property change. The current buffer is the one the
+change has been made in. These functions get called even when
+`inhibit-modification-hooks' is non-nil.
+
+Note that these functions may NOT themselves make any buffer changes,
+including text property changes. */);
+ Vsyntax_table_props_change_alert_functions = Qnil;
+
interval_insert_behind_hooks = Qnil;
interval_insert_in_front_hooks = Qnil;
staticpro (&interval_insert_behind_hooks);
@@ -2337,6 +2373,7 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
DEFSYM (Qrear_nonsticky, "rear-nonsticky");
DEFSYM (Qmouse_face, "mouse-face");
DEFSYM (Qminibuffer_prompt, "minibuffer-prompt");
+ DEFSYM (Qsyntax_table_props_change_alert_functions, "syntax-table-props-change-alert-functions");
/* Properties that text might use to specify certain actions. */
--
Alan Mackenzie (Nuremberg, Germany).
next prev parent reply other threads:[~2019-06-08 20:36 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-08 13:17 bug#36136: syntax-ppss fails to invalidate its cache on changes to syntax-table text properties Alan Mackenzie
2019-06-08 20:36 ` Alan Mackenzie [this message]
2019-06-09 5:56 ` bug#36136: [PATCH]: " Eli Zaretskii
2019-06-09 14:52 ` Alan Mackenzie
2019-06-09 18:39 ` Alan Mackenzie
2019-06-12 8:37 ` Stefan Monnier
2019-06-12 10:15 ` Alan Mackenzie
2019-06-12 10:54 ` Stefan Monnier
2019-06-13 12:21 ` Alan Mackenzie
2019-06-13 21:31 ` Stefan Monnier
[not found] ` <handler.36136.B.155999987226722.ack@debbugs.gnu.org>
2019-08-24 19:35 ` bug#36136: Acknowledgement (syntax-ppss fails to invalidate its cache on changes to syntax-table text properties) Alan Mackenzie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190608203639.GA28722@ACM \
--to=acm@muc.de \
--cc=36136@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).