... In fact, I notice that when such hiccups occur, those two choosers are displayed ghosted (disabled) for a fraction of a second and then become enabled again.
Btw, which is the plugin responsible for those, so that I can try disabling it, to see if the hiccups disappear ?
Using latest NB, Win10 x64.
Thx
... for a very short time those two gadgets flash or kind of, like they becoming disabled and then enabled again, so I suspected it could be relatedTThanks for the screenshot
Oh what's up, a bug ?
It seems that if I close C::B and I reopen it, the "Update parser when typing" setting gets enabled again ! Can you check ?
NB svn 13598
// ----------------------------------------------------------------------------
void ClassBrowser::SetParser(ParserBase* parser)
// ----------------------------------------------------------------------------
{
if (m_Parser == parser)
return;
m_Parser = parser;
if (m_Parser)
{
const int sel = XRCCTRL(*this, "cmbView", wxChoice)->GetSelection();
BrowserDisplayFilter filter = static_cast<BrowserDisplayFilter>(sel);
if (!m_ParseManager->IsParserPerWorkspace() && filter == bdfWorkspace)
filter = bdfProject;
m_Parser->ClassBrowserOptions().displayFilter = filter;
m_Parser->WriteOptions();
UpdateClassBrowserView();
}
else
CCLogger::Get()->DebugLog("SetParser: No parser available.");
}
bool ParseManager::DeleteParser(cbProject* project)
{
wxString prj = (project ? project->GetTitle() : _T("*NONE*"));
ParserList::iterator it = m_ParserList.begin();
if (!m_ParserPerWorkspace)
{
for (; it != m_ParserList.end(); ++it)
{
if (it->first == project)
break;
}
}
if (it == m_ParserList.end())
{
CCLogger::Get()->DebugLog(wxString::Format("ParseManager::DeleteParser: Parser does not exist for delete '%s'!", prj));
return false;
}
bool removeProjectFromParser = false;
if (m_ParserPerWorkspace)
removeProjectFromParser = RemoveProjectFromParser(project);
if (m_ParsedProjects.empty()) // this indicates we are in one parser per one project mode
{
wxString log(wxString::Format(_("ParseManager::DeleteParser: Deleting parser for project '%s'!"), prj));
CCLogger::Get()->Log(log);
CCLogger::Get()->DebugLog(log);
// the logic here is : firstly delete the parser instance, then see whether we need an
// active parser switch (call SetParser())
delete it->second;
// if the active parser is deleted, set the active parser to nullptr
if (it->second == m_Parser)
{
m_Parser = nullptr;
SetParser(m_TempParser); // Also updates class browser
}
m_ParserList.erase(it);
return true;
}
if (removeProjectFromParser)
return true;
CCLogger::Get()->DebugLog(_T("ParseManager::DeleteParser: Deleting parser failed!"));
return false;
}
SetParser(m_TempParser); // Also updates class browser
Another thought might be to issue a shared event to tell all parsers to re-read (update its parser.options) if a user clicks OK in the CodeCompletion settings dialog.
I don't mean to create a new global event, but I know that an event using an XRCID("mySharedEventId") is possible if both sender and receiver use the same XRCID.
@ ollydbg
How about this idea.
The ccoptionsdlg can always record, in a global var, the address of the active parser that last updated the settings.
When the workspace is closed, if that var contains an address, that parser will be the only parser that is allows to update the .conf settings.
That way, any number of projects can be in the workspace, but only the last parser to update the settings can finally store them to the .conf .
Wouldn't that work for only one parser and also for multiple parsers?
If the global var is nullptr, ccoptionsdlg never got called to change any option, then we don't care about which parser updates the .conf .
ccoptionsdlg would only set the active parsers address in the global var, if the user clicked OK to dismiss the dialog.
I'm assuming that the dismiss dialog action (OK or Cancel) can be caught.
Else we'd have to find another way to determine that the user changed any option.
Edit: 10:35am
Got It. void CCOptionsDlg::OnApply() is only called when user clicks OK. I'm thinking that's the only place we need to set the global var with the active parser address.
Is all this true?
Index: ccoptionsdlg.cpp
===================================================================
--- ccoptionsdlg.cpp (revision 13609)
+++ ccoptionsdlg.cpp (working copy)
@@ -183,6 +183,10 @@
void CCOptionsDlg::OnApply()
{
+ //(ph 2025/02/04) // Set the project that changed the .conf data //(ph 2025/02/04)
+ cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ m_ParseManager->SetOptsChangerProject(pProject);
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// -----------------------------------------------------------------------
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13609)
+++ parsemanager.h (working copy)
@@ -258,6 +258,9 @@
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ cbProject* GetOptsChangerProject(){ return m_pOptsChangerProject;} //(ph 2025/02/04)
+ void SetOptsChangerProject(cbProject* pProject){m_pOptsChangerProject = pProject;} //(ph 2025/02/04)
+
protected:
/** When a Parser is created, we need a full parsing stage including:
* 1, parse the priority header files firstly.
@@ -527,6 +530,9 @@
bool m_ClassBrowserViewIsStale = true;
bool m_SymbolsWindowHasFocus = false;
+ //The last project to change the .conf file //(ph 2025/02/04)
+ cbProject* m_pOptsChangerProject = nullptr;
+
};
#endif // PARSEMANAGER_H
Index: parser/parser.cpp
===================================================================
--- parser/parser.cpp (revision 13609)
+++ parser/parser.cpp (working copy)
@@ -29,6 +29,7 @@
#include <wx/tokenzr.h>
#include <cbstyledtextctrl.h>
+#include "..\parsemanager.h" //(ph 2025/02/04)
#include "parser.h"
#include "parserthreadedtask.h"
@@ -921,6 +922,16 @@
void Parser::WriteOptions()
{
+ // If this project didn't change the options, then don't let it overwrite them. //(ph 2025/02/04)
+ cbProject* pActiveProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ ParseManager* pParseMgr = (ParseManager*)m_Parent;
+ cbProject* pOptsChangerProject = pParseMgr->GetOptsChangerProject();
+ if ( pActiveProject != pOptsChangerProject )
+ {
+ ReadOptions(); // force projects that did not change options to re-read them.
+ return;
+ }
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// Page "Code Completion"
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13609)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6(ph) 25/02/04" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
@ ollydbg
Would you try the following CC patch. It works well for me.
It simply remembers the project that applied an options change.
At WriteOptions() it only lets that project update the CC Options and .conf and makes the other projects refresh their cached options.
Patch is also attached to this msg.CodeIndex: ccoptionsdlg.cpp
===================================================================
--- ccoptionsdlg.cpp (revision 13609)
+++ ccoptionsdlg.cpp (working copy)
@@ -183,6 +183,10 @@
void CCOptionsDlg::OnApply()
{
+ //(ph 2025/02/04) // Set the project that changed the .conf data //(ph 2025/02/04)
+ cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ m_ParseManager->SetOptsChangerProject(pProject);
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// -----------------------------------------------------------------------
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13609)
+++ parsemanager.h (working copy)
@@ -258,6 +258,9 @@
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ cbProject* GetOptsChangerProject(){ return m_pOptsChangerProject;} //(ph 2025/02/04)
+ void SetOptsChangerProject(cbProject* pProject){m_pOptsChangerProject = pProject;} //(ph 2025/02/04)
+
protected:
/** When a Parser is created, we need a full parsing stage including:
* 1, parse the priority header files firstly.
@@ -527,6 +530,9 @@
bool m_ClassBrowserViewIsStale = true;
bool m_SymbolsWindowHasFocus = false;
+ //The last project to change the .conf file //(ph 2025/02/04)
+ cbProject* m_pOptsChangerProject = nullptr;
+
};
#endif // PARSEMANAGER_H
Index: parser/parser.cpp
===================================================================
--- parser/parser.cpp (revision 13609)
+++ parser/parser.cpp (working copy)
@@ -29,6 +29,7 @@
#include <wx/tokenzr.h>
#include <cbstyledtextctrl.h>
+#include "..\parsemanager.h" //(ph 2025/02/04)
#include "parser.h"
#include "parserthreadedtask.h"
@@ -921,6 +922,16 @@
void Parser::WriteOptions()
{
+ // If this project didn't change the options, then don't let it overwrite them. //(ph 2025/02/04)
+ cbProject* pActiveProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ ParseManager* pParseMgr = (ParseManager*)m_Parent;
+ cbProject* pOptsChangerProject = pParseMgr->GetOptsChangerProject();
+ if ( pActiveProject != pOptsChangerProject )
+ {
+ ReadOptions(); // force projects that did not change options to re-read them.
+ return;
+ }
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// Page "Code Completion"
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13609)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6(ph) 25/02/04" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
#include "..\parsemanager.h"
Code#include "..\parsemanager.h"
My guess is the above line will fail under Linux.
Tim S.
I'm not fully understand the patch, it looks like all the Parser instance will share the same "option".
If you set a breakpoint(BP) in the file: parser.cpp, in the function body: void Parser::WriteOptions()
Then do something like below:
1, start C::B, this will hit the BP
2, when you open a project, the BP will hit again, at this time, "ReadOptions()" will be called, and returned without writing to the configure file.
3, when you change the classbrowser's option, from current "project" to "everything", the BP will hit again, and "ReadOptions()" will be called again, but still not write to the configure file.
From my point of view, this is not correct.
As Tim said, we should use "../xxxxx.h" include directive, thanks.
ActiveProject OnAppy project ActiveProject != OnApplyProject action
-------------- -------------- ------------------------------- ----------
nullptr nullptr False, will write .conf written at startup
nullptr nullptr False, will write no projects,.option changed, .conf wrtten
Nullptr Not null Does not happen Can't happen, no project to record
Not null nullptr True, no write no setting changed, no writes
Not null not null False, will write option changed, .conf written
nullptr nullptr False, will write project closed but no options change, no write
nullptr not null True, no write project closed, .conf written for matching project
I can't find a "Class browser's option. Where is that?
I can possible make those options "always write" if I could figure out where that is.
// ----------------------------------------------------------------------------
void ClassBrowser::SetParser(ParserBase* parser)
// ----------------------------------------------------------------------------
{
if (m_Parser == parser)
return;
m_Parser = parser;
if (m_Parser)
{
const int sel = XRCCTRL(*this, "cmbView", wxChoice)->GetSelection();
BrowserDisplayFilter filter = static_cast<BrowserDisplayFilter>(sel);
if (!m_ParseManager->IsParserPerWorkspace() && filter == bdfWorkspace)
filter = bdfProject;
m_Parser->ClassBrowserOptions().displayFilter = filter;
m_Parser->WriteOptions();
UpdateClassBrowserView();
}
else
CCLogger::Get()->DebugLog("SetParser: No parser available.");
}
Any change made while no project is active gets written to .conf
When a project is loaded nothing has changed in .conf, so no write options need to be done.
If changes are made to settings (OnApply is entered), the active parser that made the changes is recorded by OnApply().
Those changes are then written to the .conf, and only the settings made by that active project are written to the .conf.
all other projects read those settings.
If no user setting are made via settings, no need to care about writing the .conf.I agree.
Index: ccoptionsdlg.cpp
===================================================================
--- ccoptionsdlg.cpp (revision 13610)
+++ ccoptionsdlg.cpp (working copy)
@@ -183,6 +183,12 @@
void CCOptionsDlg::OnApply()
{
+ cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ // Remember the project that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByProject(pProject);
+ // Renember the Parser that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByParser(&(m_ParseManager->GetParser())); //(ph 2025/02/07)
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// -----------------------------------------------------------------------
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13610)
+++ parsemanager.h (working copy)
@@ -9,8 +9,8 @@
#include "parsemanager_base.h"
#include "parser/parser.h"
-#include <queue>
-#include <map>
+//unused #include <queue>
+// unused #include <map>
#include <memory>
#include <unordered_map>
@@ -258,6 +258,14 @@
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ // Set or return Project that changed "Global setting" in workspace
+ cbProject* GetOptsChangedByProject(){ return m_pOptsChangedProject;}
+ void SetOptsChangedByProject(cbProject* pProject){m_pOptsChangedProject = pProject;}
+ // Set or return Parser that changed "Global setting" in Single File workspace
+ ParserBase* GetTempParser(){return m_TempParser;}
+ ParserBase* GetOptsChangedByParser(){ return m_pOptsChangedParser;}
+ void SetOptsChangedByParser(ParserBase* pParserBase){m_pOptsChangedParser = &(GetParser());}
+
protected:
/** When a Parser is created, we need a full parsing stage including:
* 1, parse the priority header files firstly.
@@ -474,11 +482,12 @@
*/
bool RemoveProjectFromParser(cbProject* project);
+
private:
typedef std::pair<cbProject*, ParserBase*> ProjectParserPair;
typedef std::list<ProjectParserPair> ParserList;
- /** a list holing all the cbp->parser pairs, if in one parser per project mode, there are many
+ /** a list holding all the cbp->parser pairs, if in one parser per project mode, there are many
* many pairs in this list. In one parser per workspace mode, there is only one pair, and the
* m_ParserList.begin()->second is the common parser for all the projects in workspace.
*/
@@ -527,6 +536,11 @@
bool m_ClassBrowserViewIsStale = true;
bool m_SymbolsWindowHasFocus = false;
+ //The latest project to change the .conf file //(ph 2025/02/04)
+ cbProject* m_pOptsChangedProject = nullptr;
+ //The latest parser to change the .conf file //(ph 2025/02/04)
+ ParserBase* m_pOptsChangedParser = nullptr;
+
};
#endif // PARSEMANAGER_H
Index: parser/parser.cpp
===================================================================
--- parser/parser.cpp (revision 13610)
+++ parser/parser.cpp (working copy)
@@ -32,9 +32,10 @@
#include "parser.h"
#include "parserthreadedtask.h"
+#include "../parsemanager.h" //(ph 2025/02/04)
#include "../classbrowser.h"
-#include "../classbrowserbuilderthread.h"
+//unused - #include "../classbrowserbuilderthread.h"
#ifndef CB_PRECOMP
@@ -921,19 +922,59 @@
void Parser::WriteOptions()
{
+ //(ph 2025/02/06)
+ // Assemble status to determine if a Parser or Project changed a global setting.
+ ProjectManager* pPrjMgr = Manager::Get()->GetProjectManager();
+ cbProject* pActiveProject = pPrjMgr->GetActiveProject();
+ ParseManager* pParseMgr = (ParseManager*)m_Parent;
+ ParserBase* pParser = &(pParseMgr->GetParser());
+ ParserBase* pTempParser = pParseMgr->GetTempParser();
+ cbProject* pOptsChangerProject = pParseMgr->GetOptsChangedByProject();
+
+ int projectsCount = pPrjMgr->GetProjects()->size();
+ bool isTempParser = (pParser == pTempParser);
+ bool globalOptionChanged = pParseMgr->GetOptsChangedByParser() or pParseMgr->GetOptsChangedByProject();
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
- // Page "Code Completion"
- cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
- cfg->Write(_T("/while_typing"), m_Options.whileTyping);
+ // **Debugging** use this global to verify logic
+ // bool parseWhileTypingStatus = m_Options.whileTyping;
- // Page "C / C++ parser"
- cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
- cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
- cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
- cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
- cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ // Do not allow stale parser settings to change the global settings
+ bool allowGlobalUpdate = false;
+ if ( (projectsCount == 0) and globalOptionChanged)
+ allowGlobalUpdate = true; //Single file settings changes
+ if (projectsCount and (pOptsChangerProject == pActiveProject) )
+ allowGlobalUpdate = true; // changes made by a project
+ if ( (projectsCount==0) and isTempParser and globalOptionChanged)
+ allowGlobalUpdate = false; // TempParser has stale settings on Close()
+ if (not globalOptionChanged)
+ allowGlobalUpdate = false; // no global settings have changed
+ if (allowGlobalUpdate)
+ {
+ // Page "Code Completion"
+ cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
+ cfg->Write(_T("/while_typing"), m_Options.whileTyping);
+
+ // Page "C / C++ parser"
+ cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
+ cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
+ cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
+ cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
+ cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ }
+ if ((projectsCount == 0) and isTempParser and globalOptionChanged)
+ {
+ // When no projects exists but the CB main settings have been changed,
+ // force the TempParser to reread settings/options else stale ones
+ // will be displayed on the next use of MenuBar/Settings/Editor/CodeCompletion dialog
+ ReadOptions();
+ // The global settings changed status can now be reset
+ pParseMgr->SetOptsChangedByParser(nullptr);
+ pParseMgr->SetOptsChangedByProject(nullptr);
+ }
+
// Page "Symbol browser"
cfg->Write(_T("/browser_show_inheritance"), m_BrowserOptions.showInheritance);
cfg->Write(_T("/browser_expand_ns"), m_BrowserOptions.expandNS);
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13610)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6 25/02/7" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
I've tested it with single and mult-project workspaces, Single file workspace and empty ones as well.
I debugged your patch, and I found it still has logic errors, here is my steps:
1, start the debuggee C::B
2, load a cbp file
3, change some CC setting(from the code completion plugin's setting dialog)
4, close the cbp
5, change some CC setting(from the code completion plugin's setting dialog)
6, exit the debugee C::B
Note that from my point of view, in step 5, when I open the CC setting dialog, and change some settings, when I close the dialog, I need to "Save the setting to the configure file).
But actually, it is NOT.
Index: ccoptionsdlg.cpp
===================================================================
--- ccoptionsdlg.cpp (revision 13610)
+++ ccoptionsdlg.cpp (working copy)
@@ -183,6 +183,12 @@
void CCOptionsDlg::OnApply()
{
+ cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ // Remember the project that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByProject(pProject);
+ // Renember the Parser that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByParser(&(m_ParseManager->GetParser())); //(ph 2025/02/07)
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// -----------------------------------------------------------------------
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13610)
+++ parsemanager.h (working copy)
@@ -9,8 +9,8 @@
#include "parsemanager_base.h"
#include "parser/parser.h"
-#include <queue>
-#include <map>
+//unused #include <queue>
+// unused #include <map>
#include <memory>
#include <unordered_map>
@@ -258,6 +258,14 @@
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ // Set or return Project that changed "Global setting" in workspace
+ cbProject* GetOptsChangedByProject(){ return m_pOptsChangedProject;}
+ void SetOptsChangedByProject(cbProject* pProject){m_pOptsChangedProject = pProject;}
+ // Set or return Parser that changed "Global setting" in Single File workspace
+ ParserBase* GetOptsChangedByParser(){ return m_pOptsChangedParser;}
+ void SetOptsChangedByParser(ParserBase* pParserBase){m_pOptsChangedParser = pParserBase;}
+ ParserBase* GetTempParser(){return m_TempParser;}
+
protected:
/** When a Parser is created, we need a full parsing stage including:
* 1, parse the priority header files firstly.
@@ -474,11 +482,12 @@
*/
bool RemoveProjectFromParser(cbProject* project);
+
private:
typedef std::pair<cbProject*, ParserBase*> ProjectParserPair;
typedef std::list<ProjectParserPair> ParserList;
- /** a list holing all the cbp->parser pairs, if in one parser per project mode, there are many
+ /** a list holding all the cbp->parser pairs, if in one parser per project mode, there are many
* many pairs in this list. In one parser per workspace mode, there is only one pair, and the
* m_ParserList.begin()->second is the common parser for all the projects in workspace.
*/
@@ -527,6 +536,11 @@
bool m_ClassBrowserViewIsStale = true;
bool m_SymbolsWindowHasFocus = false;
+ //The latest project to change the .conf file //(ph 2025/02/04)
+ cbProject* m_pOptsChangedProject = nullptr;
+ //The latest parser to change the .conf file //(ph 2025/02/04)
+ ParserBase* m_pOptsChangedParser = nullptr;
+
};
#endif // PARSEMANAGER_H
Index: parser/parser.cpp
===================================================================
--- parser/parser.cpp (revision 13610)
+++ parser/parser.cpp (working copy)
@@ -32,9 +32,10 @@
#include "parser.h"
#include "parserthreadedtask.h"
+#include "../parsemanager.h" //(ph 2025/02/04)
#include "../classbrowser.h"
-#include "../classbrowserbuilderthread.h"
+//unused - #include "../classbrowserbuilderthread.h"
#ifndef CB_PRECOMP
@@ -921,19 +922,66 @@
void Parser::WriteOptions()
{
+ //(ph 2025/02/06) Global settings bug fix
+ //https://forums.codeblocks.org/index.php/topic,25955 Hiccups while typing
+ // Assemble status to check if a Parser or Project changed a global setting.
+ ProjectManager* pPrjMgr = Manager::Get()->GetProjectManager();
+ cbProject* pActiveProject = pPrjMgr->GetActiveProject();
+ ParseManager* pParseMgr = (ParseManager*)m_Parent;
+ ParserBase* pParser = &(pParseMgr->GetParser());
+ ParserBase* pTempParser = pParseMgr->GetTempParser();
+ cbProject* pOptsChangerProject = pParseMgr->GetOptsChangedByProject();
+
+ int projectsCount = pPrjMgr->GetProjects()->size();
+ bool isTempParser = pTempParser == pParser;
+ bool globalOptionChanged = pParseMgr->GetOptsChangedByParser() or pParseMgr->GetOptsChangedByProject();
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
- // Page "Code Completion"
- cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
- cfg->Write(_T("/while_typing"), m_Options.whileTyping);
+ // **Debugging** use this global to verify logic (cached values)
+ bool OldWhileTypingStatus = m_Options.whileTyping;
+ asm("nop"); // **Debugging** set brkpt here
- // Page "C / C++ parser"
- cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
- cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
- cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
- cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
- cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ // Do not allow stale parser settings to change the global settings
+ bool allowGlobalUpdate = false;
+ if ( (projectsCount == 0) and globalOptionChanged)
+ allowGlobalUpdate = true; //Single file settings changes
+ if (projectsCount and (pOptsChangerProject == pActiveProject) )
+ allowGlobalUpdate = true; // changes made by a project
+ if ( (projectsCount==0) and isTempParser and globalOptionChanged)
+ {
+ // When no projects exists but the CB main settings have been changed,
+ // force the TempParser to reread settings/options else stale ones
+ // will be set and displayed on the next use of MenuBar/Settings/Editor/CodeCompletion dialog
+ #warning CodeCompletion: Remove the **Debugging** statements before commiting
+ bool oldWhileTypingStatus = m_Options.whileTyping; // **Debugging** //(ph 2025/02/08)
+ ReadOptions(); //force TempParser to update its settings
+ bool actualWhileTypingStatus = m_Options.whileTyping; // **Debugging** //(ph 2025/02/08)
+ allowGlobalUpdate = true;
+ }
+ if (not globalOptionChanged)
+ allowGlobalUpdate = false; // no global settings have changed
+ if (allowGlobalUpdate)
+ {
+ // Page "Code Completion"
+ cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
+ cfg->Write(_T("/while_typing"), m_Options.whileTyping);
+
+ // Page "C / C++ parser"
+ cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
+ cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
+ cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
+ cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
+ cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ }
+ if ((projectsCount == 0) and isTempParser and globalOptionChanged)
+ {
+ // The global settings changed status can now be reset
+ pParseMgr->SetOptsChangedByParser(nullptr);
+ pParseMgr->SetOptsChangedByProject(nullptr);
+ }
+
// Page "Symbol browser"
cfg->Write(_T("/browser_show_inheritance"), m_BrowserOptions.showInheritance);
cfg->Write(_T("/browser_expand_ns"), m_BrowserOptions.expandNS);
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13610)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6 25/02/8" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
@ ollydbg
Thanks for doing all this testing.
I moved the forced TempParse update to before the .conf write.
That seemed to do the trick.
When you get a chance, would you test to see if I'm doing any better. So far, I'm batting 0 for 5.
...
...
I'll remove all the "**debugging**" tags and statements before any commit.
if ( (projectsCount==0) and isTempParser and globalOptionChanged)
{
// When no projects exists but the CB main settings have been changed,
// force the TempParser to reread settings/options else stale ones
// will be set and displayed on the next use of MenuBar/Settings/Editor/CodeCompletion dialog
// #warning CodeCompletion: Remove the **Debugging** statements before commiting
// bool oldWhileTypingStatus = m_Options.whileTyping; // **Debugging** //(ph 2025/02/08)
ReadOptions(); //force TempParser to update its settings
// bool actualWhileTypingStatus = m_Options.whileTyping; // **Debugging** //(ph 2025/02/08)
allowGlobalUpdate = true;
}
Index: classbrowser.cpp
===================================================================
--- classbrowser.cpp (revision 13611)
+++ classbrowser.cpp (working copy)
@@ -46,7 +46,7 @@
#include "parser/ccdebuginfo.h"
-#include <stack>
+//unused #include <stack>
#include <chrono>
#define CC_CLASS_BROWSER_DEBUG_OUTPUT 0
@@ -242,6 +242,9 @@
filter = bdfProject;
m_Parser->ClassBrowserOptions().displayFilter = filter;
+ // Update stale CB globals in TempParser before WriteOptions() //(ph 2025/02/10)
+ if (m_Parser == m_ParseManager->GetTempParser())
+ m_Parser->ReadOptions();
m_Parser->WriteOptions();
UpdateClassBrowserView();
}
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13611)
+++ parsemanager.h (working copy)
@@ -9,8 +9,8 @@
#include "parsemanager_base.h"
#include "parser/parser.h"
-#include <queue>
-#include <map>
+//unused #include <queue>
+// unused #include <map>
#include <memory>
#include <unordered_map>
@@ -257,6 +257,7 @@
//(ph 2024/01/25)
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ ParserBase* GetTempParser(){return m_TempParser;} //(ph 2025/02/10)
protected:
/** When a Parser is created, we need a full parsing stage including:
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13611)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6 25/02/10" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
+----------+
+------------------------|Parser A |
| +----------+
+-------|------+
|Parse option | +----------+
|Browser option|-----------------|Parser B |
+-------|------+ +----------+
|
| +-----------+
+------------------------|Parser Temp|
+-----------+
Index: ccoptionsdlg.cpp
===================================================================
--- ccoptionsdlg.cpp (revision 13611)
+++ ccoptionsdlg.cpp (working copy)
@@ -183,6 +183,12 @@
void CCOptionsDlg::OnApply()
{
+ cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
+ // Remember the project that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByProject(pProject);
+ // Renember the Parser that changed the .conf data //(ph 2025/02/04)
+ m_ParseManager->SetOptsChangedByParser(&(m_ParseManager->GetParser())); //(ph 2025/02/07)
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
// -----------------------------------------------------------------------
Index: parsemanager.cpp
===================================================================
--- parsemanager.cpp (revision 13611)
+++ parsemanager.cpp (working copy)
@@ -623,6 +623,7 @@
// if the active parser is deleted, set the active parser to nullptr
if (it->second == m_Parser)
{
+ SetClosingParser(m_Parser); //(ph 2025/02/12)
m_Parser = nullptr;
SetParser(m_TempParser); // Also updates class browser
}
Index: parsemanager.h
===================================================================
--- parsemanager.h (revision 13611)
+++ parsemanager.h (working copy)
@@ -9,8 +9,8 @@
#include "parsemanager_base.h"
#include "parser/parser.h"
-#include <queue>
-#include <map>
+//unused #include <queue>
+// unused #include <map>
#include <memory>
#include <unordered_map>
@@ -258,6 +258,16 @@
void SetSymbolsWindowHasFocus(bool trueOrFalse){ m_SymbolsWindowHasFocus = trueOrFalse;}
bool GetSymbolsWindowHasFocus(){return m_SymbolsWindowHasFocus;}
+ // Set or return Project that changed "Global setting" in workspace
+ cbProject* GetOptsChangedByProject(){ return m_pOptsChangedProject;}
+ void SetOptsChangedByProject(cbProject* pProject){m_pOptsChangedProject = pProject;}
+ // Set or return Parser that changed "Global setting" in Single File workspace
+ ParserBase* GetOptsChangedByParser(){ return m_pOptsChangedParser;}
+ void SetOptsChangedByParser(ParserBase* pParserBase){m_pOptsChangedParser = pParserBase;}
+ ParserBase* GetTempParser(){return m_TempParser;}
+ ParserBase* GetClosingParser(){return m_pClosingParser;} //(ph 2025/02/12)
+ void SetClosingParser(ParserBase* pParser){m_pClosingParser = pParser;} //(ph 2025/02/12)
+
protected:
/** When a Parser is created, we need a full parsing stage including:
* 1, parse the priority header files firstly.
@@ -474,11 +484,12 @@
*/
bool RemoveProjectFromParser(cbProject* project);
+
private:
typedef std::pair<cbProject*, ParserBase*> ProjectParserPair;
typedef std::list<ProjectParserPair> ParserList;
- /** a list holing all the cbp->parser pairs, if in one parser per project mode, there are many
+ /** a list holding all the cbp->parser pairs, if in one parser per project mode, there are many
* many pairs in this list. In one parser per workspace mode, there is only one pair, and the
* m_ParserList.begin()->second is the common parser for all the projects in workspace.
*/
@@ -527,6 +538,13 @@
bool m_ClassBrowserViewIsStale = true;
bool m_SymbolsWindowHasFocus = false;
+ //The latest project to change the .conf file //(ph 2025/02/04)
+ cbProject* m_pOptsChangedProject = nullptr;
+ //The latest parser to change the .conf file //(ph 2025/02/04)
+ ParserBase* m_pOptsChangedParser = nullptr;
+ // the currently closing parser
+ ParserBase* m_pClosingParser = nullptr;
+
};
#endif // PARSEMANAGER_H
Index: parser/parser.cpp
===================================================================
--- parser/parser.cpp (revision 13611)
+++ parser/parser.cpp (working copy)
@@ -32,9 +32,10 @@
#include "parser.h"
#include "parserthreadedtask.h"
+#include "../parsemanager.h" //(ph 2025/02/04)
#include "../classbrowser.h"
-#include "../classbrowserbuilderthread.h"
+//unused - #include "../classbrowserbuilderthread.h"
#ifndef CB_PRECOMP
@@ -921,19 +922,64 @@
void Parser::WriteOptions()
{
+ // Global settings bug fix (ph 2025/02/12)
+ //https://forums.codeblocks.org/index.php/topic,25955 Hiccups while typing
+
+ // Assemble status to determine if a Parser or Project changed a global setting.
+ ParseManager* pParseMgr = (ParseManager*)m_Parent;
+ ParserBase* pTempParser = pParseMgr->GetTempParser();
+ ParserBase* pClosingParser = pParseMgr->GetClosingParser(); //see ParseManger::DeleteParser()
+ ParserBase* pCurrentParser = &(pParseMgr->GetParser()); //aka: m_parser
+
+ bool isClosingParser = pCurrentParser == pClosingParser;
+ bool isTempParser = pTempParser == pCurrentParser;
+ bool globalOptionChanged = pParseMgr->GetOptsChangedByParser() or pParseMgr->GetOptsChangedByProject();
+
+ // If this is a parser close, do not allow CB global settings writes.
+ bool allowGlobalUpdate = false;
+
+ // When no closing parser, but CB globals were changed, write to .conf
+ if ( (not isClosingParser) and globalOptionChanged)
+ allowGlobalUpdate = true;
+
+ // Closing parsers are not allowed to write to CB globals.
+ // CB Globals were already written when when user changed the setting.
+ if (isClosingParser) allowGlobalUpdate = false;
+ // If no changes to the CB globals, no need to write
+ if (not globalOptionChanged)
+ allowGlobalUpdate = false; // no global settings have changed
+
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
- // Page "Code Completion"
- cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
- cfg->Write(_T("/while_typing"), m_Options.whileTyping);
+ // ----------------------------------------------------------------------------
+ // set any user changed CB global settings for CodeCompletion
+ // ----------------------------------------------------------------------------
+ if (allowGlobalUpdate)
+ {
+ // Page "Code Completion"
+ cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
+ cfg->Write(_T("/while_typing"), m_Options.whileTyping);
- // Page "C / C++ parser"
- cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
- cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
- cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
- cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
- cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ // Page "C / C++ parser"
+ cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
+ cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
+ cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
+ cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
+ cfg->Write(_T("/platform_check"), m_Options.platformCheck);
+ }
+ // clean out any parser flags used to guard CB global settings
+ pParseMgr->SetOptsChangedByParser(nullptr); //(ph 2025/02/12)
+ pParseMgr->SetOptsChangedByProject(nullptr); //(ph 2025/02/12)
+ pParseMgr->SetClosingParser(nullptr);
+ // if currrent parser == TempParser, force it to update, else the next
+ // display of the setting dialog will show TempParser stale cached settings.
+ if (isTempParser) pTempParser->ReadOptions();
+
+ // ----------------------------------------------------------------------------
+ // set any user changed ClassBrowser settings
+ // ----------------------------------------------------------------------------
+
// Page "Symbol browser"
cfg->Write(_T("/browser_show_inheritance"), m_BrowserOptions.showInheritance);
cfg->Write(_T("/browser_expand_ns"), m_BrowserOptions.expandNS);
Index: resources/manifest.xml
===================================================================
--- resources/manifest.xml (revision 13611)
+++ resources/manifest.xml (working copy)
@@ -3,7 +3,7 @@
<SdkVersion major="1" minor="10" release="0" />
<Plugin name="CodeCompletion">
<Value title="Code completion" />
- <Value version="1.0.5 24/01/29" />
+ <Value version="1.0.6 25/02/12" />
<Value description="This plugin provides a symbols browser for your projects and code-completion inside the editor.
// ----------------------------------------------------------------------------
void ClassBrowser::SetParser(ParserBase* parser)
// ----------------------------------------------------------------------------
{
if (m_Parser == parser)
return;
m_Parser = parser;
if (m_Parser)
{
const int sel = XRCCTRL(*this, "cmbView", wxChoice)->GetSelection();
BrowserDisplayFilter filter = static_cast<BrowserDisplayFilter>(sel);
if (!m_ParseManager->IsParserPerWorkspace() && filter == bdfWorkspace)
filter = bdfProject;
m_Parser->ClassBrowserOptions().displayFilter = filter;
m_Parser->WriteOptions();
UpdateClassBrowserView();
}
else
CCLogger::Get()->DebugLog("SetParser: No parser available.");
}
So, what is the time we need to "read the Parser option from the .conf to the Parser instance", I think it should be in the constructor, and this should be the only place a Parser instance to read the initial parsing option.
If a parser only reads the settings at parser creation time, when the user later changes the global settings but the parser is not allowed to read them after the change, the user now is parsing without the settings he/she requested.
If that user was me, I'd call that a bug.
I think it would be better to throw up a message box saying "Sorry, sniff, global settings will not be applied for a project/parser until you request a re-parse of all the other loaded projects." Just kidding...
This is a hard problem. If we don't apply changes, we violate UI standards. If we do change them, a busy parser won't apply them anyway.
Maybe we should put up a message box that says, these changes will only be applied on the next re-parse for a project.
We could list the projects that have a 'busy' not done flag.
I remember this situation from about 13 years ago. The client asked me to throw up a message box that said "Options cannot be changed while a workspace is loaded".
// ----------------------------------------------------------------------------
void ClassBrowser::SetParser(ParserBase* parser)
// ----------------------------------------------------------------------------
OK, thanks, I have fixed an issue mentioned here: Re: The 14 June 2024 build (13529) is out. (https://forums.codeblocks.org/index.php/topic,25818.msg176887/topicseen.html#msg176887)
BTW: why do you have so many custom comments in the source code, do you added manually or by some tools?Code// ----------------------------------------------------------------------------
void ClassBrowser::SetParser(ParserBase* parser)
// ----------------------------------------------------------------------------