From: Alan Mackenzie <acm@muc.de>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: 30393@debbugs.gnu.org, Dmitry Gutov <dgutov@yandex.ru>,
Noam Postavsky <npostavs@users.sourceforge.net>
Subject: bug#30393: 24.4; cperl-mode: indentation failure
Date: Mon, 5 Mar 2018 08:42:55 +0000 [thread overview]
Message-ID: <20180305084255.GA4786@ACM> (raw)
In-Reply-To: <jwvsha6c4z1.fsf-monnier+emacsbugs@gnu.org>
Hello, Stefan.
Sorry this has taken so long. I've been preoccupied with things outside
of Emacs.
On Mon, Feb 12, 2018 at 15:45:40 -0500, Stefan Monnier wrote:
> > It has occurred to me over the last day or two that I have already
> > solved these problems (basically, with your first approach, hooking into
> > set-syntax-table and friends) in the comment-cache branch, and that the
> > approach taken could be used more or less unchanged in the current
> > master.
> If you can reuse existing code, even better.
The following patch ensures that (almost) any time the syntax table or a
syntax-table text property is changed in a way which affects literals,
the function syntax-ppss-flush-cache is called.
The known exceptions to the above are that setting any of the variables
parse-sexp-lookup-properties, syntax-propertize-function,
syntax-propertize-extend-region-functions, multibyte-syntax-as-symbol,
parse-sexp-ignore-comments, comment-end-can-be-escaped after mode
initialisation is not detected. The major mode code would need to flush
the caches explicitly on such a change. Also, changing the syntax-table
property of a symbol which is the value of a category text-property is
not detected.
In the following descriptions "literally the same" and "literally
different", when applied to syntax things, are shorthand for "will parse
literals (comments and strings) the same/differently".
Existing C functions have been modified as follows:
o - signal_after_change.
* - Regardless of the settings of the change hooks,
syntax-ppss-flush-cache will be called for an actual textual
change.
o - Fset_syntax_table.
* - If the new table is literally different from the old,
syntax-ppss-flush-cache will be called with an argument of -1.
o - Fmodify_syntax_entry.
* - If the new entry is literally different from the old one,
syntax-ppss-flush-cache will be called with an argument of -1.
o - init_syntax_once and syms_of_syntax.
* - Administrative amendments.
o - set_properties, add_properties, remove_properties. If a
syntax-table property set or removed, whether directly or via a
category property, potentially alters the parsing of literals,
syntax-ppss-flush-cache will be called.
diff --git a/src/chartab.c b/src/chartab.c
index 065ae4f9f2..e2b9e682cc 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -314,7 +314,6 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to,
return val;
}
-
/* Return the value for C in char-table TABLE. Shrink the range *FROM
and *TO to cover characters (containing C) that have the same value
as C. It is not assured that the values of (*FROM - 1) and (*TO +
@@ -386,6 +385,60 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
return val;
}
+/* Return the value for C in char-table TABLE. Shrink the range
+ *FROM and *TO to cover characters (containing C) that have the same
+ value as C. Should the value for C in TABLE be nil, consult the
+ parent table of TABLE, recursively if necessary. It is not
+ guaranteed that the values of (*FROM - 1) and (*TO + 1) are
+ different from that of C. */
+Lisp_Object
+char_table_ref_and_range_with_parents (Lisp_Object table, int c,
+ int *from, int *to)
+{
+ Lisp_Object val;
+ Lisp_Object parent, defalt;
+ struct Lisp_Char_Table *tbl;
+
+ if (*to < 0)
+ *to = MAX_CHAR;
+ if (ASCII_CHAR_P (c)
+ && *from <= c
+ && *to >= c)
+ {
+ tbl = XCHAR_TABLE (table);
+ parent = tbl->parent; /* Added in to try to fix segfault. 2018-02-18. */
+ defalt = tbl->defalt;
+ val = NILP (tbl->ascii)
+ ? defalt /*Qnil*/
+ : sub_char_table_ref_and_range (tbl->ascii, c, from, to, defalt, false);
+ while (NILP (val) && !NILP (parent))
+ {
+ tbl = XCHAR_TABLE (parent);
+ parent = tbl->parent;
+ defalt = tbl->defalt;
+ val = NILP (tbl->ascii)
+ ? defalt /*Qnil*/
+ : sub_char_table_ref_and_range (tbl->ascii, c, from, to, defalt, false);
+ }
+ return val;
+ }
+ else if (!ASCII_CHAR_P (c))
+ {
+ val = char_table_ref_and_range (table, c, from, to);
+ tbl = XCHAR_TABLE (table);
+ while (NILP (val))
+ {
+ parent = tbl->parent;
+ if (NILP (parent))
+ break;
+ val = char_table_ref_and_range (parent, c, from, to);
+ tbl = XCHAR_TABLE (parent);
+ }
+ return val;
+ }
+ else
+ return Qnil;
+}
static void
sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, bool is_uniprop)
diff --git a/src/insdel.c b/src/insdel.c
index 02e3f41bc9..4016ceb845 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -2170,6 +2170,12 @@ signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
ptrdiff_t count = SPECPDL_INDEX ();
struct rvoe_arg rvoe_arg;
+ /* Ensure we invalidate the syntax cache on an actual text change
+ regardless of the settings of inhibit-modification-hooks and
+ after-change-functions. */
+ if ((lenins != lendel)
+ && Ffboundp (Qsyntax_ppss_flush_cache)) /* For bootstrapping. */
+ call1 (Qsyntax_ppss_flush_cache, make_number (charpos));
if (inhibit_modification_hooks)
return;
diff --git a/src/lisp.h b/src/lisp.h
index a7f0a1d78f..e4f76f4561 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3851,6 +3851,8 @@ extern void r_alloc_inhibit_buffer_relocation (int);
extern Lisp_Object copy_char_table (Lisp_Object);
extern Lisp_Object char_table_ref_and_range (Lisp_Object, int,
int *, int *);
+extern Lisp_Object char_table_ref_and_range_with_parents (Lisp_Object, int,
+ int*, int*);
extern void char_table_set_range (Lisp_Object, int, int, Lisp_Object);
extern void map_char_table (void (*) (Lisp_Object, Lisp_Object,
Lisp_Object),
diff --git a/src/syntax.c b/src/syntax.c
index 52cec23cd7..d81a57cd22 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -178,8 +178,12 @@ static ptrdiff_t find_start_begv;
static EMACS_INT find_start_modiff;
+static void check_syntax_table (Lisp_Object);
static Lisp_Object skip_chars (bool, Lisp_Object, Lisp_Object, bool);
static Lisp_Object skip_syntaxes (bool, Lisp_Object, Lisp_Object);
+static bool syntax_table_value_range_is_interesting_for_literals (Lisp_Object,
+ int, int);
+static void break_off_syntax_tables_literal_relations (Lisp_Object);
static Lisp_Object scan_lists (EMACS_INT, EMACS_INT, EMACS_INT, bool);
static void scan_sexps_forward (struct lisp_parse_state *,
ptrdiff_t, ptrdiff_t, ptrdiff_t, EMACS_INT,
@@ -687,6 +691,112 @@ prev_char_comend_first (ptrdiff_t pos, ptrdiff_t pos_byte)
return val;
}
+/* Empty the syntax-ppss cache of every buffer whose syntax table is
+ currently set to TABLE. */
+static void
+empty_syntax_tables_buffers_syntax_caches (Lisp_Object table)
+{
+ Lisp_Object buf, buf_list;
+ struct buffer *current = current_buffer;
+ struct buffer *b;
+
+ buf_list = Fbuffer_list (Qnil);
+ while (!NILP (buf_list))
+ {
+ buf = XCAR (buf_list);
+ b = XBUFFER (buf);
+ if (EQ (BVAR (b, syntax_table), table))
+ {
+ set_buffer_internal_1 (b);
+ call1 (Qsyntax_ppss_flush_cache, make_number (-1));
+ }
+ buf_list = XCDR (buf_list);
+ }
+ set_buffer_internal_1 (current);
+}
+
+#define LITERAL_MASK ((1 << Sstring) \
+ | (1 << Sescape) \
+ | (1 << Scharquote) \
+ | (1 << Scomment) \
+ | (1 << Sendcomment) \
+ | (1 << Scomment_fence) \
+ | (1 << Sstring_fence))
+
+/* The following returns true if ELT (which will be a raw syntax
+ descriptor (see page "Syntax Table Internals" in the Elisp manual)
+ or nil) represents a syntax which is (potentially) relevant to
+ strings or comments. */
+static bool
+SYNTAB_LITERAL (Lisp_Object elt)
+{
+ int ielt;
+ if (!CONSP (elt))
+ return false;
+ ielt = XINT (XCAR (elt));
+ return (ielt & 0xF0000) /* a comment flag is set */
+ || ((1 << (ielt & 0xFF)) & LITERAL_MASK); /* One of Sstring, .... */
+}
+
+static
+bool syntax_table_value_is_interesting_for_literals (Lisp_Object val)
+{
+ if (!CONSP (val)
+ || !INTEGERP (XCAR (val)))
+ return false;
+ return SYNTAB_LITERAL (XCAR (val));
+}
+
+/* The text property PROP is having its value VAL at position POS in buffer BUF
+either set or cleared. If this value is relevant to the syntax of literals,
+reduce the BUF's "syntax cache position" to POS. */
+void
+check_syntax_cache_for_prop (ptrdiff_t pos, Lisp_Object prop,
+ Lisp_Object val, Lisp_Object buffer)
+{
+ struct buffer *b;
+ struct buffer *current = current_buffer;
+ Lisp_Object plist;
+
+ if (!BUFFERP (buffer))
+ return;
+ b = XBUFFER (buffer);
+ set_buffer_internal_1 (b);
+ if (pos >= syntax_propertize__done)
+ {
+ set_buffer_internal_1 (current);
+ return;
+ }
+
+ if (EQ (prop, Qcategory)
+ && SYMBOLP (val))
+ {
+ plist = Fsymbol_plist (val);
+ while (CONSP (plist))
+ {
+ prop = XCAR (plist);
+ plist = XCDR (plist);
+ if (!CONSP (plist))
+ {
+ set_buffer_internal_1 (current);
+ return;
+ }
+ val = XCAR (plist);
+ if (EQ (prop, Qsyntax_table))
+ break;
+ plist = XCDR (plist);
+ }
+ }
+ if (EQ (prop, Qsyntax_table)
+ && syntax_table_value_is_interesting_for_literals (val))
+ call1 (Qsyntax_ppss_flush_cache, make_number (pos));
+ set_buffer_internal_1 (current);
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+
+
/* Check whether charpos FROM is at the end of a comment.
FROM_BYTE is the bytepos corresponding to FROM.
Do not move back before STOP.
@@ -989,6 +1099,222 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
return from != comment_end;
}
\f
+/* If the two syntax entries OLD_SYN and NEW_SYN would parse strings
+ or comments differently return true, otherwise return nil. */
+static bool
+literally_different (Lisp_Object old_syn, Lisp_Object new_syn)
+{
+ bool old_literality = SYNTAB_LITERAL (old_syn),
+ new_literality = SYNTAB_LITERAL (new_syn);
+ return (old_literality != new_literality)
+ || (old_literality
+ && (!EQ (Fcar (old_syn), Fcar (new_syn))));
+}
+
+/* If there is a character position in the range [START, END] for
+ whose syntaxes in syntax tables OLD and NEW strings or comments
+ might be parsed differently, return the lowest character for which
+ this holds. Otherwise, return -1. */
+static int
+syntax_table_ranges_differ_literally_p (Lisp_Object old, Lisp_Object new,
+ int start, int end)
+{
+ int old_from, new_from, old_to, new_to;
+ Lisp_Object old_syn = Qnil, new_syn = Qnil; /* Initialise to avoid compiler warnings. */
+
+ new_from = old_from = start;
+ new_to = old_to = -1;
+
+ while ((old_from < end) && (new_from < end))
+ {
+ if (old_from == new_from)
+ {
+ old_syn = char_table_ref_and_range_with_parents (old, old_from,
+ &old_from, &old_to);
+ new_syn = char_table_ref_and_range_with_parents (new, new_from,
+ &new_from, &new_to);
+ if (literally_different (old_syn, new_syn))
+ return old_from;
+ old_from = old_to + 1;
+ new_from = new_to + 1;
+ old_to = -1;
+ new_to = -1;
+ }
+ else if (old_from < new_from)
+ {
+ old_syn = char_table_ref_and_range_with_parents (old, old_from,
+ &old_from, &old_to);
+ if (literally_different (old_syn, new_syn))
+ return old_from;
+ old_from = old_to + 1;
+ old_to = -1;
+ }
+ else
+ {
+ new_syn = char_table_ref_and_range_with_parents (new, new_from,
+ &new_from, &new_to);
+ if (literally_different (old_syn, new_syn))
+ return new_from;
+ new_from = new_to + 1;
+ new_to = -1;
+ }
+ }
+ return -1;
+}
+
+DEFUN ("least-literal-difference-between-syntax-tables",
+ Fleast_literal_difference_between_syntax_tables,
+ Sleast_literal_difference_between_syntax_tables,
+ 2, 2, 0,
+ doc: /* Lowest char whose different syntaxes in OLD and NEW parse literals differently.
+ OLD and NEW are syntax tables. */)
+ (Lisp_Object old, Lisp_Object new)
+{
+ int c;
+
+ check_syntax_table (old);
+ check_syntax_table (new);
+ c = syntax_table_ranges_differ_literally_p (old, new, 0, MAX_CHAR + 1);
+ if (c >= 0)
+ return make_number (c);
+ return Qnil;
+}
+
+/* The next two variables are alists, the key being a syntax table,
+ and the value being a non-empty list of syntax_tables. When a
+ syntax table B is known to parse strings and comments the same as
+ syntax table A, it will be a member of the value whose key is A in
+ `literally_the_same_sts' (and vice versa). Similarly, when two
+ syntax tables are known to parse strings and comments differently,
+ there will be entries in `literally_different_sts'. */
+static Lisp_Object literally_the_same_sts, literally_different_sts;
+
+DEFUN ("syntax-tables-literally-different-p",
+ Fsyntax_tables_literally_different_p,
+ Ssyntax_tables_literally_different_p,
+ 2, 2, 0,
+ doc: /* Will syntax tables OLD and NEW parse literals differently?
+Return t when OLD and NEW might parse comments and strings differently,
+otherwise nil. (Use `least-literal-difference-between-syntax-tables'
+to locate a character position where the tables differ.) */)
+ (Lisp_Object old, Lisp_Object new)
+{
+ Lisp_Object elt;
+
+ check_syntax_table (old);
+ check_syntax_table (new);
+ /* Check to see if there is a cached relationship between the tables. */
+ if (!NILP (Fmemq (new, /*XCHAR_TABLE (old)->extras[0])*/
+ Fassq (old, literally_the_same_sts))))
+ return Qnil;
+ if (!NILP (Fmemq (new, /*XCHAR_TABLE (old)->extras[1])*/
+ Fassq (old, literally_different_sts))))
+ return Qt;
+ /* The two tables have no known relationship, so we'll have
+ laboriously to compare them. */
+ if (syntax_table_ranges_differ_literally_p (old, new, 0, MAX_CHAR + 1) >= 0)
+ {
+ /* Mark the "literally different" relationship between the OLD and
+ NEW syntax tables. */
+ elt = Fassq (new, literally_different_sts);
+ if (NILP (elt))
+ literally_different_sts = Fcons (Fcons (new, Fcons (old, Qnil)),
+ literally_different_sts);
+ else
+ Fsetcdr (elt, Fcons (old, XCDR (elt)));
+ elt = Fassq (old, literally_different_sts);
+ if (NILP (elt))
+ literally_different_sts = Fcons (Fcons (old, Fcons (new, Qnil)),
+ literally_different_sts);
+ else
+ Fsetcdr (elt, Fcons (new, XCDR (elt)));
+ return Qt;
+ }
+ else
+ {
+ /* Mark the "not literally different" relationship between the OLD
+ and NEW syntax tables. */
+ elt = Fassq (new, literally_the_same_sts);
+ if (NILP (elt))
+ literally_the_same_sts = Fcons (Fcons (new, Fcons (old, Qnil)),
+ literally_the_same_sts);
+ else
+ Fsetcdr (elt, Fcons (old, XCDR (elt)));
+ elt = Fassq (old, literally_the_same_sts);
+ if (NILP (elt))
+ literally_the_same_sts = Fcons (Fcons (old, Fcons (new, Qnil)),
+ literally_the_same_sts);
+ else
+ Fsetcdr (elt, Fcons (new, XCDR (elt)));
+ return Qnil;
+ }
+}
+
+/* If any character in the range [START, END) has an entry in syntax
+ table TABLE which is relevant to literal parsing, return true,
+ else return false. */
+static bool
+syntax_table_value_range_is_interesting_for_literals (Lisp_Object table,
+ int start, int end)
+{
+ int from, to;
+ Lisp_Object syn;
+
+ from = start;
+ to = end;
+ while (from < to)
+ {
+ syn = char_table_ref_and_range_with_parents (table, from, &from, &to);
+ if (SYNTAB_LITERAL (syn))
+ return true;
+ from = to + 1;
+ to = end;
+ }
+ return false;
+}
+
+static void
+break_off_syntax_tables_literal_relations (Lisp_Object table)
+{
+ Lisp_Object remotes_elt;
+ Lisp_Object remotes, keep_remotes;
+ Lisp_Object rem, elt;
+
+ remotes_elt = Fassq (table, literally_the_same_sts);
+ remotes = Fcdr (remotes_elt);
+ keep_remotes = remotes;
+ while (!NILP (remotes))
+ {
+ rem = Fcar (remotes);
+ elt = Fassq (rem, literally_the_same_sts);
+ Fsetcdr (elt, Fdelq (table, Fcdr (elt)));
+ if (NILP (Fcdr (elt)))
+ literally_the_same_sts = Fdelq (elt, literally_the_same_sts);
+ remotes = Fcdr (remotes);
+ }
+ if (!NILP (keep_remotes))
+ literally_the_same_sts = Fdelq (remotes_elt, literally_the_same_sts);
+
+ remotes_elt = Fassq (table, literally_different_sts);
+ remotes = Fcdr (remotes_elt);
+ keep_remotes = remotes;
+ while (!NILP (remotes))
+ {
+ rem = Fcar (remotes);
+ elt = Fassq (rem, literally_different_sts);
+ Fsetcdr (elt, Fdelq (table, Fcdr (elt)));
+ if (NILP (Fcdr (elt)))
+ literally_different_sts = Fdelq (elt, literally_different_sts);
+ remotes = Fcdr (remotes);
+ }
+ if (!NILP (keep_remotes))
+ literally_different_sts = Fdelq (remotes_elt, literally_different_sts);
+}
+
+
+/*****************************************************************************
+ ****************************************************************************/
+
DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
doc: /* Return t if OBJECT is a syntax table.
Currently, any char-table counts as a syntax table. */)
@@ -1057,6 +1383,14 @@ One argument, a syntax table. */)
{
int idx;
check_syntax_table (table);
+ /* Optimise away the case when we're not changing the table. */
+ if (EQ (BVAR (current_buffer, syntax_table), table))
+ return table;
+ if (!NILP (Fsyntax_table_p (BVAR (current_buffer, syntax_table)))
+ && !NILP (Fsyntax_tables_literally_different_p
+ (BVAR (current_buffer, syntax_table), table))
+ && Ffboundp (Qsyntax_ppss_flush_cache)) /* for bootstrapping. */
+ call1 (Qsyntax_ppss_flush_cache, make_number (-1));
bset_syntax_table (current_buffer, table);
/* Indicate that this buffer now has a specified syntax table. */
idx = PER_BUFFER_VAR_IDX (syntax_table);
@@ -1274,6 +1608,16 @@ usage: (modify-syntax-entry CHAR NEWENTRY &optional SYNTAX-TABLE) */)
check_syntax_table (syntax_table);
newentry = Fstring_to_syntax (newentry);
+ if (SYNTAB_LITERAL (newentry)
+ || (CONSP (c)
+ ? syntax_table_value_range_is_interesting_for_literals
+ (syntax_table, XINT (XCAR(c)), XINT (XCDR (c)))
+ : (SYNTAB_LITERAL (Faref (syntax_table, c)))))
+ {
+ empty_syntax_tables_buffers_syntax_caches (syntax_table);
+ break_off_syntax_tables_literal_relations (syntax_table);
+ }
+
if (CONSP (c))
SET_RAW_SYNTAX_ENTRY_RANGE (syntax_table, c, newentry);
else
@@ -3637,6 +3981,10 @@ init_syntax_once (void)
/* This has to be done here, before we call Fmake_char_table. */
DEFSYM (Qsyntax_table, "syntax-table");
+ /* We do not yet have any knowledge of how syntax tables parse literals. */
+ literally_the_same_sts = Qnil;
+ literally_different_sts = Qnil;
+
/* Create objects which can be shared among syntax tables. */
Vsyntax_code_object = make_uninit_vector (Smax);
for (i = 0; i < Smax; i++)
@@ -3728,6 +4076,9 @@ syms_of_syntax (void)
staticpro (&gl_state.current_syntax_table);
staticpro (&gl_state.old_prop);
+ staticpro (&literally_the_same_sts);
+ staticpro (&literally_different_sts);
+
/* Defined in regex.c. */
staticpro (&re_match_object);
@@ -3752,6 +4103,8 @@ See the info node `(elisp)Syntax Properties' for a description of the
DEFSYM (Qinternal__syntax_propertize, "internal--syntax-propertize");
Fmake_variable_buffer_local (intern ("syntax-propertize--done"));
+ DEFSYM (Qsyntax_ppss_flush_cache, "syntax-ppss-flush-cache");
+
words_include_escapes = 0;
DEFVAR_BOOL ("words-include-escapes", words_include_escapes,
doc: /* Non-nil means `forward-word', etc., should treat escape chars part of words. */);
@@ -3790,6 +4143,8 @@ In both cases, LIMIT bounds the search. */);
DEFSYM (Qcomment_end_can_be_escaped, "comment-end-can-be-escaped");
Fmake_variable_buffer_local (Qcomment_end_can_be_escaped);
+ defsubr (&Sleast_literal_difference_between_syntax_tables);
+ defsubr (&Ssyntax_tables_literally_different_p);
defsubr (&Ssyntax_table_p);
defsubr (&Ssyntax_table);
defsubr (&Sstandard_syntax_table);
diff --git a/src/syntax.h b/src/syntax.h
index 2171cbbba4..1771ae4728 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -28,6 +28,10 @@ INLINE_HEADER_BEGIN
extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object);
extern void update_syntax_table_forward (ptrdiff_t, bool, Lisp_Object);
+extern void check_syntax_cache_for_prop (ptrdiff_t, Lisp_Object,
+ Lisp_Object, Lisp_Object);
+
+
/* The standard syntax table is stored where it will automatically
be used in all new buffers. */
diff --git a/src/textprop.c b/src/textprop.c
index 984f2e6640..cd56d8b12c 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "intervals.h"
+#include "syntax.h"
#include "buffer.h"
#include "window.h"
@@ -340,6 +341,12 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), XCAR (value),
object);
+ check_syntax_cache_for_prop
+ (interval->position, XCAR (sym), XCAR (value), object);
+ if (!EQ (property_value (properties, XCAR (sym)), Qunbound))
+ check_syntax_cache_for_prop
+ (interval->position, XCAR (sym),
+ property_value (properties, XCAR (sym)), object);
}
/* For each new property that has no value at all in the old plist,
@@ -352,6 +359,8 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), Qnil,
object);
+ check_syntax_cache_for_prop
+ (interval->position, XCAR (sym), XCAR (value), object);
}
}
@@ -406,6 +415,10 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
{
record_property_change (i->position, LENGTH (i),
sym1, Fcar (this_cdr), object);
+ check_syntax_cache_for_prop
+ (i->position, sym1, Fcar (this_cdr), object);
+ check_syntax_cache_for_prop
+ (i->position, sym1, val1, object);
}
/* I's property has a different value -- change it */
@@ -442,6 +455,8 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object,
{
record_property_change (i->position, LENGTH (i),
sym1, Qnil, object);
+ check_syntax_cache_for_prop
+ (i->position, sym1, val1, object);
}
set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist)));
changed = true;
@@ -475,11 +490,14 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object
/* First, remove the symbol if it's at the head of the list */
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);
-
+ if (BUFFERP (object))
+ {
+ record_property_change (i->position, LENGTH (i),
+ sym, XCAR (XCDR (current_plist)),
+ object);
+ check_syntax_cache_for_prop
+ (i->position, sym, XCAR (XCDR (current_plist)), object);
+ }
current_plist = XCDR (XCDR (current_plist));
changed = true;
}
@@ -492,8 +510,12 @@ 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);
+ check_syntax_cache_for_prop
+ (i->position, sym, XCAR (XCDR (this)), object);
+ }
Fsetcdr (XCDR (tail2), XCDR (XCDR (this)));
changed = true;
> Stefan
--
Alan Mackenzie (Nuremberg, Germany).
next prev parent reply other threads:[~2018-03-05 8:42 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-08 15:25 bug#30393: 24.4; cperl-mode: indentation failure paulusm
2018-02-09 1:44 ` Noam Postavsky
[not found] ` <mailman.8766.1518140709.27995.bug-gnu-emacs@gnu.org>
2018-02-09 17:50 ` Alan Mackenzie
2018-02-10 3:55 ` Noam Postavsky
2018-02-10 8:53 ` Dmitry Gutov
2018-02-10 11:26 ` Alan Mackenzie
2018-02-10 12:08 ` Eli Zaretskii
2018-02-11 12:49 ` Alan Mackenzie
2018-02-11 16:16 ` Eli Zaretskii
2018-02-14 21:00 ` Alan Mackenzie
2018-02-15 17:39 ` Eli Zaretskii
2018-02-16 11:52 ` Dmitry Gutov
2018-02-16 17:43 ` Alan Mackenzie
2018-02-17 2:16 ` Dmitry Gutov
2018-02-17 10:54 ` Alan Mackenzie
2018-02-10 14:58 ` Stefan Monnier
2018-02-11 10:36 ` Alan Mackenzie
2018-02-11 22:53 ` Stefan Monnier
2018-02-12 18:38 ` Alan Mackenzie
2018-02-12 20:45 ` Stefan Monnier
2018-03-05 8:42 ` Alan Mackenzie [this message]
2018-03-05 16:14 ` Eli Zaretskii
2018-03-06 18:09 ` Alan Mackenzie
2018-04-08 10:52 ` Alan Mackenzie
2018-04-09 18:41 ` Eli Zaretskii
2018-04-10 17:31 ` Alan Mackenzie
2018-04-16 19:21 ` bug#30393: 24.4; cperl-mode: indentation failure - Documentation enhancements Alan Mackenzie
2018-04-19 7:52 ` Eli Zaretskii
2020-08-22 16:07 ` Lars Ingebrigtsen
2020-11-03 13:45 ` bug#30393: [PATCH] Add a test to verify that the bug is gone (and a fix for Emacs 26) Harald Jörg
2020-11-03 14:29 ` Lars Ingebrigtsen
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=20180305084255.GA4786@ACM \
--to=acm@muc.de \
--cc=30393@debbugs.gnu.org \
--cc=dgutov@yandex.ru \
--cc=monnier@IRO.UMontreal.CA \
--cc=npostavs@users.sourceforge.net \
/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).