From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs 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 Message-ID: <20190608203639.GA28722@ACM> References: <20190608131724.GA4643@ACM> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="3273"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Mutt/1.10.1 (2018-07-13) To: 36136@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Jun 08 22:37:11 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1hZi5P-0000iK-94 for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Jun 2019 22:37:11 +0200 Original-Received: from localhost ([::1]:60408 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hZi5N-0001HU-Li for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Jun 2019 16:37:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:53063) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hZi5I-0001HL-1H for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 16:37:05 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hZi5G-0001fj-Hn for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 16:37:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:40235) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hZi5G-0001fb-Df for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 16:37:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1hZi5G-00039H-9v for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 16:37:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Alan Mackenzie Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 08 Jun 2019 20:37:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 36136 X-GNU-PR-Package: emacs Original-Received: via spool by 36136-submit@debbugs.gnu.org id=B36136.156002620612084 (code B ref 36136); Sat, 08 Jun 2019 20:37:02 +0000 Original-Received: (at 36136) by debbugs.gnu.org; 8 Jun 2019 20:36:46 +0000 Original-Received: from localhost ([127.0.0.1]:53779 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1hZi50-00038q-0L for submit@debbugs.gnu.org; Sat, 08 Jun 2019 16:36:46 -0400 Original-Received: from colin.muc.de ([193.149.48.1]:35422 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1hZi4x-00038h-Te for 36136@debbugs.gnu.org; Sat, 08 Jun 2019 16:36:45 -0400 Original-Received: (qmail 81245 invoked by uid 3782); 8 Jun 2019 20:36:40 -0000 Original-Received: from acm.muc.de (p2E5D5C7B.dip0.t-ipconnect.de [46.93.92.123]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sat, 08 Jun 2019 22:36:40 +0200 Original-Received: (qmail 17829 invoked by uid 1000); 8 Jun 2019 20:36:39 -0000 Content-Disposition: inline In-Reply-To: <20190608131724.GA4643@ACM> X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:160246 Archived-At: 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).