[LyX/master] Improve performance of macro validation (#13321)

Juergen Spitzmueller <[email protected]> Fri, 05 Jun 2026 08:52:33 +0000
Newsgroups gmane.editors.lyx.cvs
Message-ID <[email protected]>
commit 7d295d29e50fdabe21f7a84936523489205353de
Author: Juergen Spitzmueller <[email protected]>
Date:   Fri Jun 5 10:51:10 2026 +0200

    Improve performance of macro validation (#13321)
    
    The creation of a dedicated set is not needed here and costly.
    
    Co-production with Guillaume.
---
 src/Buffer.cpp                | 32 ++++++++++++++++++++++++++++++++
 src/Buffer.h                  |  2 ++
 src/mathed/InsetMathMacro.cpp | 10 ++++------
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 5471f89cfa..8122a05843 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -85,6 +85,7 @@
 #include "frontends/WorkAreaManager.h"
 
 #include "support/lassert.h"
+#include "support/Changer.h"
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/docstring_list.h"
@@ -4102,6 +4103,37 @@ void Buffer::listMacroNames(MacroNameSet & macros) const
 }
 
 
+bool Buffer::hasMacroName(docstring const & name) const
+{
+	// mark this buffer as already visited to avoid recursive loop
+	if (d->macro_lock)
+		return false;
+
+	// temporal macro lock that will be set false
+	// upon return
+	Changer dummy = changeVar(d->macro_lock, true);
+
+	// loop over macro names
+	if (d->macros.find(name) != d->macros.end())
+		return true;
+
+	// loop over children
+	for (auto const & p : d->children_positions) {
+		Buffer * child = const_cast<Buffer *>(p.first);
+		// The buffer might have been closed (see #10766).
+		if (theBufferList().isLoaded(child) && child->hasMacroName(name))
+			return true;
+	}
+
+	// call parent
+	Buffer const * const pbuf = d->parent();
+	if (pbuf)
+		return pbuf->hasMacroName(name);
+
+	return false;
+}
+
+
 void Buffer::listParentMacros(MacroSet & macros, LaTeXFeatures & features) const
 {
 	Buffer const * const pbuf = d->parent();
diff --git a/src/Buffer.h b/src/Buffer.h
index c4e328917e..0141bd5439 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -618,6 +618,8 @@ public:
 
 	/// List macro names of this buffer, the parent and the children
 	void listMacroNames(MacroNameSet & macros) const;
+	/// Check whether this buffer, its parent or a child, has a specific macro
+	bool hasMacroName(docstring const & name) const;
 	/// Collect macros of the parent and its children in front of this buffer.
 	void listParentMacros(MacroSet & macros, LaTeXFeatures & features) const;
 
diff --git a/src/mathed/InsetMathMacro.cpp b/src/mathed/InsetMathMacro.cpp
index 9354ef716e..290b461264 100644
--- a/src/mathed/InsetMathMacro.cpp
+++ b/src/mathed/InsetMathMacro.cpp
@@ -983,13 +983,11 @@ void InsetMathMacro::validate(LaTeXFeatures & features) const
 	// in this case the definition is only used for screen display.
 	MathWordList const & words = mathedWordList();
 	MathWordList::const_iterator it = words.find(name());
-	MacroNameSet macros;
-	buffer().listMacroNames(macros);
 	if (it == words.end() || it->second.inset != "macro"
-	    || macros.find(name()) != macros.end()) {
-		if (displayMode() == DISPLAY_NORMAL) {
-				d->definition_.validate(features);
-		} else if (displayMode() == DISPLAY_INIT) {
+	    || buffer().hasMacroName(name())) {
+		if (displayMode() == DISPLAY_NORMAL)
+			d->definition_.validate(features);
+		else if (displayMode() == DISPLAY_INIT) {
 			if (MacroData const * data = buffer().getMacro(name())) {
 				MathData md(const_cast<Buffer *>(&buffer()));
 				asMathData(data->definition(), md);
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs