Code::Blocks  SVN r11506
parser.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11505 $
6  * $Id: parser.cpp 11505 2018-10-20 14:29:48Z ollydbg $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/codecompletion/parser/parser.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #ifndef CB_PRECOMP
13  #include <queue>
14 
15  #include <wx/app.h>
16  #include <wx/dir.h>
17  #include <wx/filename.h>
18  #include <wx/intl.h>
19  #include <wx/progdlg.h>
20 
21  #include <cbproject.h>
22  #include <configmanager.h>
23  #include <editormanager.h>
24  #include <globals.h>
25  #include <infowindow.h>
26  #include <logmanager.h>
27  #include <manager.h>
28 #endif
29 
30 #include <wx/tokenzr.h>
31 #include <cbstyledtextctrl.h>
32 
33 #include "parser.h"
34 #include "parserthreadedtask.h"
35 
36 #include "../classbrowser.h"
37 #include "../classbrowserbuilderthread.h"
38 
39 
40 #ifndef CB_PRECOMP
41  #include "editorbase.h"
42 #endif
43 
44 #define CC_PARSER_DEBUG_OUTPUT 0
45 
46 #if defined(CC_GLOBAL_DEBUG_OUTPUT)
47  #if CC_GLOBAL_DEBUG_OUTPUT == 1
48  #undef CC_PARSER_DEBUG_OUTPUT
49  #define CC_PARSER_DEBUG_OUTPUT 1
50  #elif CC_GLOBAL_DEBUG_OUTPUT == 2
51  #undef CC_PARSER_DEBUG_OUTPUT
52  #define CC_PARSER_DEBUG_OUTPUT 2
53  #endif
54 #endif
55 
56 #if CC_PARSER_DEBUG_OUTPUT == 1
57  #define TRACE(format, args...) \
58  CCLogger::Get()->DebugLog(F(format, ##args))
59  #define TRACE2(format, args...)
60 #elif CC_PARSER_DEBUG_OUTPUT == 2
61  #define TRACE(format, args...) \
62  do \
63  { \
64  if (g_EnableDebugTrace) \
65  CCLogger::Get()->DebugLog(F(format, ##args)); \
66  } \
67  while (false)
68  #define TRACE2(format, args...) \
69  CCLogger::Get()->DebugLog(F(format, ##args))
70 #else
71  #define TRACE(format, args...)
72  #define TRACE2(format, args...)
73 #endif
74 
75 namespace ParserCommon
76 {
77  static const int PARSER_BATCHPARSE_TIMER_DELAY = 300;
79  static const int PARSER_BATCHPARSE_TIMER_DELAY_LONG = 1000;
80  static const int PARSER_REPARSE_TIMER_DELAY = 100;
81 
82  // this static variable point to the Parser instance which is currently running the taskpool
83  // when the taskpool finishes, the pointer is set to nullptr.
84  static volatile Parser* s_CurrentParser = nullptr;
85 
86  // NOTE (ollydbg#1#): This static variable is used to prevent changing the member variables of
87  // the Parser class from different threads. Basically, It should not be a static wxMutex for all
88  // the instances of the Parser class, it should be a member variable of the Parser class.
89  // Maybe, the author of this locker (Loaden?) thought that accessing to different Parser instances
90  // from different threads should also be avoided.
92 
95 
96 }// namespace ParserCommon
97 
99  m_Parent(parent),
100  m_Project(project),
101  m_UsingCache(false),
102  m_Pool(this, wxNewId(), 1, 2 * 1024 * 1024), // in the meanwhile it'll have to be forced to 1
103  m_IsParsing(false),
104  m_NeedsReparse(false),
105  m_IsFirstBatch(false),
106  m_ReparseTimer(this, wxNewId()),
107  m_BatchTimer(this, wxNewId()),
108  m_StopWatchRunning(false),
109  m_LastStopWatchTime(0),
110  m_IgnoreThreadEvents(true),
111  m_IsBatchParseDone(false),
112  m_ParserState(ParserCommon::ptCreateParser),
113  m_NeedMarkFileAsLocal(true)
114 {
115  ReadOptions();
116  ConnectEvents();
117 }
118 
120 {
121  // Don't wrap the s_ParserMutex lock around TerminateAllThreads(), since, it will cause a deadlock
122  // in TerminateAllThreads() when calling DeleteParser() before parsing has finished.
123 
126 
128 
129  if (ParserCommon::s_CurrentParser == this)
131 
133 }
134 
136 {
138  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&Parser::OnAllThreadsDone);
139  Connect(m_ReparseTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(Parser::OnReparseTimer));
140  Connect(m_BatchTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(Parser::OnBatchTimer));
141 }
142 
144 {
145  Disconnect(m_Pool.GetId(), cbEVT_THREADTASK_ALLDONE,
146  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&Parser::OnAllThreadsDone);
147  Disconnect(m_ReparseTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(Parser::OnReparseTimer));
148  Disconnect(m_BatchTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(Parser::OnBatchTimer));
149 }
150 
152 {
154 
155  bool done = m_BatchParseFiles.empty()
158  && m_Pool.Done();
159 
161 
162  return done;
163 }
164 
166 {
168 
169  wxString reason = _T(" > Reasons:");
170  if (!m_BatchParseFiles.empty())
171  reason += _T("\n- still batch parse files to parse");
173  reason += _T("\n- still pre-defined macros to operate");
175  reason += _T("\n- still need to mark files as local");
176  if (!m_Pool.Done())
177  reason += _T("\n- thread pool is not done yet");
178 
180 
181  return reason;
182 }
183 
185 {
186  if (m_BatchTimer.IsRunning())
187  {
188  m_BatchTimer.Stop();
189  TRACE(_T("Parser::AddPredefinedMacros(): Stop the m_BatchTimer."));
190  }
191 
193 
194  m_PredefinedMacros << defs;
195 
196  // ptUndefined means at least the cbproject is parsed already, this means the user try to
197  // reparse the project, since the predefined macro buffer is only collected when a new Parser
198  // is created
201 
202  if (!m_IsParsing)
203  {
204  TRACE(_T("Parser::AddPredefinedMacros(): Starting m_BatchTimer."));
206  }
207 
209 }
210 
212 {
214 
217 
219 }
220 
222 {
223  CCLogger::Get()->DebugLog(_T("Parser::GetPredefinedMacros()"));
224  return m_LastPredefinedMacros;
225 }
226 
227 void Parser::AddBatchParse(const StringList& filenames)
228 {
229  // this function has the same logic as the previous function Parser::AddPriorityHeader
230  // it just add some files to a m_BatchParseFiles, and tick the m_BatchTimer timer.
231  if (m_BatchTimer.IsRunning())
232  m_BatchTimer.Stop();
233 
235 
236  if (m_BatchParseFiles.empty())
237  m_BatchParseFiles = filenames;
238  else
239  std::copy(filenames.begin(), filenames.end(), std::back_inserter(m_BatchParseFiles));
240 
243 
244  if (!m_IsParsing)
245  {
246  TRACE(_T("Parser::AddBatchParse(): Starting m_BatchTimer."));
248  }
249 
251 }
252 
253 void Parser::AddParse(const wxString& filename)
254 {
255  // similar logic as the Parser::AddBatchParse, but this function only add one file to
256  // m_BatchParseFiles member, also it does not change the m_ParserState state.
257  if (m_BatchTimer.IsRunning())
258  m_BatchTimer.Stop();
259 
261 
262  m_BatchParseFiles.push_back(filename);
263 
264  if (!m_IsParsing)
265  {
266  TRACE(_T("Parser::AddParse(): Starting m_BatchTimer."));
268  }
269 
271 }
272 
273 bool Parser::Parse(const wxString& filename, bool isLocal, bool locked)
274 {
275  // most ParserThreadOptions was copied from m_Options
276  ParserThreadOptions opts;
277 
278  opts.useBuffer = false;
279  opts.bufferSkipBlocks = false;
280  opts.bufferSkipOuterBlocks = false;
281 
287 
288  // whether to collect doxygen style documents.
290 
291  opts.loader = nullptr; // must be 0 at this point
292 
293  bool result = false;
294  // a (false) do while, so we can quickly exit the loop by break statement
295  do
296  {
297  bool canparse = false;
298  {
299  // check to see whether the filename is already parsed, if not, then we first add
300  // it to ReserveFileForParsing
301  if (!locked)
303 
304  //check to see whether it is assigned already
305  canparse = !m_TokenTree->IsFileParsed(filename);
306  if (canparse)
307  canparse = m_TokenTree->ReserveFileForParsing(filename, true) != 0;
308 
309  if (!locked)
311  }
312 
313  if (!canparse)
314  {
315  TRACE(_T("Parser::Parse(): file already parsed or reserved for parsing") + filename);
316  break;
317  }
318 
319  // once the Load function is called, it will return a loader pointer, and start loading
320  // the file content in a background thread(see: BackgroundThread class)
321  // the loader will be deleted in the ParserThread::InitTokenizer() function.
322  // the second argument is the option whether we should reuse the Editor buffer
323  // if m_NeedsReparse is true, thus means we need to load the file content from the editor
324  // buffer instead of the hard disk.
325  opts.loader = Manager::Get()->GetFileManager()->Load(filename, m_NeedsReparse);
326 
327  // we are going to parse this file, so create a ParserThread
328  ParserThread* thread = new ParserThread(this, filename, isLocal, opts, m_TokenTree);
329  TRACE(_T("Parser::Parse(): Parsing %s"), filename.wx_str());
330 
331  // We now properly parse each source file from top to bottom (i.e., expanding each
332  // #include directive: If locked is true, which means this function is called when handling
333  // #include directive, the tree is already locked, so recursive here.
334  if (locked)
335  {
336 
337  // release the tree locker, don't block the GUI to access the TokenTree for a long time
339  wxMilliSleep(1);
341 
342  TRACE(_T("Parser::Parse(): Parsing included header, %s"), filename.wx_str());
343  // run the parse recursively
344  AddParserThread(thread);
345  result = thread->Parse();
346  RemoveParserThread(thread);
347  delete thread;
348  return true;
349  }
350  else
351  {
352  // files should not be parsed immediately, so we need to put it to the pool.
353  TRACE(_T("Parser::Parse(): Adding a Parsing job for %s"), filename.wx_str());
354  m_Pool.AddTask(thread, true); // autodelete = true
355  }
356 
357  result = true;
358  }
359  while (false);
360 
361  return result;
362 }
363 
364 bool Parser::ParseBuffer(const wxString& buffer, bool isLocal,
365  bool bufferSkipBlocks, bool isTemp,
366  const wxString& filename, int parentIdx, int initLine)
367 {
368  ParserThreadOptions opts;
369 
370  opts.useBuffer = true;
371  opts.fileOfBuffer = filename;
372  opts.parentIdxOfBuffer = parentIdx;
373  opts.initLineOfBuffer = initLine;
374  opts.bufferSkipBlocks = bufferSkipBlocks;
375  opts.isTemp = isTemp;
376 
377  opts.followLocalIncludes = false;
378  opts.followGlobalIncludes = false;
381  opts.platformCheck = true;
382 
383  opts.handleFunctions = true; // enabled to support function ptr in local block
384 
386 
387  ParserThread thread(this, buffer, isLocal, opts, m_TokenTree);
388 
390 
391  bool success = thread.Parse();
392 
394 
395  return success;
396 }
397 
399 {
400  ParserThreadOptions opts;
401 
402  opts.useBuffer = true;
403  opts.bufferSkipBlocks = true;
404 
405  opts.followLocalIncludes = false;
406  opts.followGlobalIncludes = false;
410 
411  opts.handleFunctions = true;
412 
414 
415  ParserThread thread(this, buffer, false, opts, m_TempTokenTree);
416 
418 
419  bool success = thread.Parse();
420 
422 
423  return success;
424 }
425 
427 {
428  ParserThreadOptions opts;
429 
430  opts.useBuffer = true;
431 
432  opts.followLocalIncludes = false;
433  opts.followGlobalIncludes = false;
435  opts.parseComplexMacros = false;
436  opts.platformCheck = true;
437 
439 
440  ParserThread thread(this, wxEmptyString, true, opts, m_TempTokenTree);
441 
443 
444  bool success = thread.ParseBufferForNamespaces(buffer, result);
445 
447 
448  return success;
449 }
450 
451 bool Parser::ParseBufferForUsingNamespace(const wxString& buffer, wxArrayString& result, bool bufferSkipBlocks)
452 {
453  ParserThreadOptions opts;
454 
455  opts.useBuffer = true;
456 
457  opts.followLocalIncludes = false;
458  opts.followGlobalIncludes = false;
460  opts.parseComplexMacros = false;
461  opts.platformCheck = true;
462  opts.bufferSkipBlocks = bufferSkipBlocks;
463 
465 
466  ParserThread thread(this, wxEmptyString, false, opts, m_TempTokenTree);
467 
469 
470  bool success = thread.ParseBufferForUsingNamespace(buffer, result);
471 
473 
474  return success;
475 }
476 
477 bool Parser::RemoveFile(const wxString& filename)
478 {
480 
481  const size_t fileIdx = m_TokenTree->InsertFileOrGetIndex(filename);
482  const bool result = m_TokenTree->GetFileStatusCountForIndex(fileIdx);
483 
484  m_TokenTree->RemoveFile(filename);
488 
490 
491  return result;
492 }
493 
494 bool Parser::AddFile(const wxString& filename, cbProject* project, cb_unused bool isLocal)
495 {
496  // this function will lock the token tree twice
497  // the first place is the function IsFileParsed() function
498  // then the AddParse() call
499  if (project != m_Project)
500  return false;
501 
502  if ( IsFileParsed(filename) )
503  return false;
504 
507 
508  AddParse(filename);
509  if (project)
510  m_NeedMarkFileAsLocal = true;
511 
512  return true;
513 }
514 
515 bool Parser::Reparse(const wxString& filename, cb_unused bool isLocal)
516 {
517  if (!Done())
518  {
519  wxString msg(_T("Parser::Reparse : The Parser is not done."));
520  msg += NotDoneReason();
521  CCLogger::Get()->DebugLog(msg);
522  return false;
523  }
524 
527 
529 
531 
533 
534  m_NeedsReparse = true;
535  TRACE(_T("Parser::Reparse(): Starting m_ReparseTimer."));
537 
538  return true;
539 }
540 
542 {
543  // NOTE: This should not be locked with s_ParserMutex, otherwise we'll be stuck in an
544  // infinite loop below since the worker thread also enters s_ParserMutex.
545  // In fact cbThreadPool maintains it's own mutex, so m_Pool is probably threadsafe.
548  // wait for the running pool finishes, hopefully we exit the while loop quickly
549  while (!m_Pool.Done())
550  wxMilliSleep(1);
551 }
552 
554 {
555  if (m_Project == project)
556  return true;
557 
558  else if (!Done())
559  {
560  wxString msg(_T("Parser::UpdateParsingProject(): The Parser is not done."));
561  msg += NotDoneReason();
562  CCLogger::Get()->DebugLog(msg);
563  return false;
564  }
565  else
566  {
567  m_Project = project;
568  return true;
569  }
570 }
571 
573 {
574  // m_IgnoreThreadEvents is initialized to true, so we returned quickly.
575  // but when the parser try to parse the batchFiles, it will set the m_IgnoreThreadEvents to false
576  // so, the control will go forward. Finally, when the last stage: mark C::B project tokens as
577  // local thread finished, it will set m_IgnoreThreadEvents again
579  return;
580 
581  // only the m_Pool (thread pool) can send such message, so do sanity check here
582  if (event.GetId() != m_Pool.GetId())
583  {
584  CCLogger::Get()->DebugLog(_T("Parser::OnAllThreadsDone(): Why is event.GetId() not equal m_Pool.GetId()?"));
585  return;
586  }
587 
588  if (!m_TokenTree)
589  cbThrow(_T("m_TokenTree is a nullptr?!"));
590 
591  if (!m_IsParsing)
592  {
593  CCLogger::Get()->DebugLog(_T("Parser::OnAllThreadsDone(): Why is m_IsParsing false?"));
594  return;
595  }
596 
597  // Do next task in BatchTimer's event handler, so start the m_BatchTimer
599  || !m_BatchParseFiles.empty() )
600  {
601  TRACE(_T("Parser::OnAllThreadsDone(): Still some tasks left, starting m_BatchTimer."));
603  }
604 #if defined(CC_PARSER_PROFILE_TEST)
605  // Do nothing
606 #else
610  && m_Project)
611  {
612  m_NeedMarkFileAsLocal = false;
614  m_Pool.AddTask(thread, true);
615  TRACE(_T("Parser::OnAllThreadsDone(): Add a MarkFileAsLocalThreadedTask."));
616  }
617 #endif
618  // Finish all task, then we need post a PARSER_END event
619  else
620  {
621  if (!m_Project)
622  m_NeedMarkFileAsLocal = false;
623 
624  // since the last stage: mark project files as local is done, we finish all the stages now.
625  m_IgnoreThreadEvents = true;
626  m_NeedsReparse = false;
627  m_IsParsing = false; // not parsing, so clear the status
628  m_IsBatchParseDone = true;
629 
630  EndStopWatch(); // stop counting the time we take for parsing the files
631 
632  wxString prj = (m_Project ? m_Project->GetTitle() : _T("*NONE*"));
633  wxString parseEndLog;
634 
636 
637  parseEndLog.Printf(_T("Project '%s' parsing stage done (%lu total parsed files, ")
638  _T("%lu tokens in %ld minute(s), %ld.%03ld seconds)."), prj.wx_str(),
639  m_TokenTree ? static_cast<unsigned long>(m_TokenTree->GetFileMapSize()) : 0,
640  m_TokenTree ? static_cast<unsigned long>(m_TokenTree->realsize()) : 0,
641  (m_LastStopWatchTime / 60000),
642  (m_LastStopWatchTime / 1000) % 60,
643  (m_LastStopWatchTime % 1000) );
644 
646 
647  // tell the parent(native parser and the code completion plugin) that some tasks are done
648  // and the task pool switches to idle mode.
650 
651  // reset the parser state
653 
654  // the current parser is not parsing any files, so set the static pointer to NULL
656  TRACE(_T("Parser::OnAllThreadsDone(): Post a PARSER_END event"));
657  }
658 }
659 
660 bool Parser::ParseFile(const wxString& filename, bool isGlobal, bool locked)
661 {
662  if ( (!isGlobal && !m_Options.followLocalIncludes)
663  || ( isGlobal && !m_Options.followGlobalIncludes) )
664  return false;
665 
666  if (filename.IsEmpty())
667  return false;
668 
669  // TODO (Morten#9#) locker ?
670  const bool ret = Parse(filename, !isGlobal, locked);
671 
672  return ret;
673 }
674 
676 {
677  if (!m_StopWatchRunning)
678  {
679  m_StopWatchRunning = true;
680  m_StopWatch.Start();
681  }
682 }
683 
685 {
686  if (m_StopWatchRunning)
687  {
688  m_StopWatch.Pause();
689  m_StopWatchRunning = false;
690  if (m_IsBatchParseDone)
692  else
694  }
695 }
696 
698 {
700  event.Skip();
701 }
702 
703 void Parser::OnBatchTimer(cb_unused wxTimerEvent& event)
704 {
706  return;
707 
709  {
710  // Current batch parser already exists, just return later
711  TRACE(_T("Parser::OnBatchTimer(): Starting m_BatchTimer."));
713  return;
714  }
715 
716  StartStopWatch(); // start counting the time we take for parsing the files
717 
718  if (m_BatchParseFiles.empty()
719  && m_PredefinedMacros.IsEmpty() ) // easy case: is there any thing to do at all?
720  {
721  return;
722  }
723 
724  bool send_event = true;
725  bool sendStartParseEvent = false;
726  if ( !m_BatchParseFiles.empty()
728  {
730 
732  TRACE(_T("Parser::OnBatchTimer(): Adding a ParserThreadedTask thread to m_Pool."));
733 
734  // once this function is called, the thread will be executed from the pool immediately
735  m_Pool.AddTask(thread, true);
737  send_event = false;
738  else // Have not done any batch parsing yet -> assign parser
739  {
741  m_StopWatch.Start(); // reset timer
742  sendStartParseEvent = true;
743  }
744 
746  }
747 
748  if (send_event)
749  {
750  if (sendStartParseEvent)
752  else
754  }
755 }
756 
758 {
759  if ( !Done() )
760  {
761  wxString msg(_T("Parser::ReparseModifiedFiles : The Parser is not done."));
762  msg += NotDoneReason();
763  CCLogger::Get()->DebugLog(msg);
764 
765  TRACE(_T("Parser::ReparseModifiedFiles(): Starting m_ReparseTimer."));
767  return;
768  }
769 
770  if (!m_NeedsReparse)
771  m_NeedsReparse = true;
772 
773  std::queue<size_t> files_idx;
774  std::queue<wxString> files_list;
775  TokenFileSet::const_iterator it;
776 
778 
779  // Collect files to be re-parsed
780  // Loop two times so that we reparse modified *header* files first, next *implementation* files
781  for (it = m_TokenTree->GetFilesToBeReparsed()->begin(); it != m_TokenTree->GetFilesToBeReparsed()->end(); ++it)
782  {
783  wxString filename = m_TokenTree->GetFilename(*it);
784  if ( FileTypeOf(filename) == ftSource || FileTypeOf(filename) == ftTemplateSource ) // ignore source files (*.cpp etc)
785  continue;
786  files_list.push(filename);
787  files_idx.push(*it);
788  }
789  for (it = m_TokenTree->GetFilesToBeReparsed()->begin(); it != m_TokenTree->GetFilesToBeReparsed()->end(); ++it)
790  {
791  wxString filename = m_TokenTree->GetFilename(*it);
792  if ( FileTypeOf(filename) != ftSource && FileTypeOf(filename) != ftTemplateSource ) // ignore non-source files (*.h etc)
793  continue;
794  files_list.push(filename);
795  files_idx.push(*it);
796  }
797 
798  // Now actually remove the files from the tree, once a file is removed from the tree, the file
799  // and its tokens are totally removed
800  while (!files_idx.empty())
801  {
802  m_TokenTree->RemoveFile(files_idx.front());
803  files_idx.pop();
804  }
805 
807 
808  if (!files_list.empty() && m_ParserState == ParserCommon::ptUndefined)
810  else
811  m_NeedsReparse = false;
812 
813  while (!files_list.empty())
814  {
815  // add those files again, so they will be parsed later
816  AddParse(files_list.front());
817  files_list.pop();
818  }
819 }
820 
821 bool Parser::IsFileParsed(const wxString& filename)
822 {
823  bool isParsed = false;
824 
826 
827  isParsed = m_TokenTree->IsFileParsed(filename);
828 
830 
831  if (!isParsed)
832  {
834 
835  StringList::iterator it = std::find(m_BatchParseFiles.begin(), m_BatchParseFiles.end(), filename);
836  if (it != m_BatchParseFiles.end())
837  isParsed = true;
838 
840  }
841 
842  return isParsed;
843 }
844 
846 {
847  wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, id);
848  evt.SetEventObject(this); // Parser*
849  evt.SetClientData(m_Project); // cbProject*
850  evt.SetInt(state);
851  evt.SetString(info);
852  m_Parent->ProcessEvent(evt);
853 }
854 
856 {
857  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
858 
859  // one-time default settings change: upgrade everyone
860  bool force_all_on = !cfg->ReadBool(_T("/parser_defaults_changed"), false);
861  if (force_all_on)
862  {
863  cfg->Write(_T("/parser_defaults_changed"), true);
864 
865  cfg->Write(_T("/parser_follow_local_includes"), true);
866  cfg->Write(_T("/parser_follow_global_includes"), true);
867  cfg->Write(_T("/want_preprocessor"), true);
868  cfg->Write(_T("/parse_complex_macros"), true);
869  cfg->Write(_T("/platform_check"), true);
870  }
871 
872  // Page "Code Completion"
873  m_Options.useSmartSense = cfg->ReadBool(_T("/use_SmartSense"), true);
874  m_Options.whileTyping = cfg->ReadBool(_T("/while_typing"), true);
875 
876  // the m_Options.caseSensitive is following the global option in ccmanager
877  // ccmcfg means ccmanager's config
878  ConfigManager* ccmcfg = Manager::Get()->GetConfigManager(_T("ccmanager"));
879  m_Options.caseSensitive = ccmcfg->ReadBool(_T("/case_sensitive"), false);
880 
881  // Page "C / C++ parser"
882  m_Options.followLocalIncludes = cfg->ReadBool(_T("/parser_follow_local_includes"), true);
883  m_Options.followGlobalIncludes = cfg->ReadBool(_T("/parser_follow_global_includes"), true);
884  m_Options.wantPreprocessor = cfg->ReadBool(_T("/want_preprocessor"), true);
885  m_Options.parseComplexMacros = cfg->ReadBool(_T("/parse_complex_macros"), true);
886  m_Options.platformCheck = cfg->ReadBool(_T("/platform_check"), true);
887 
888  // Page "Symbol browser"
889  m_BrowserOptions.showInheritance = cfg->ReadBool(_T("/browser_show_inheritance"), false);
890  m_BrowserOptions.expandNS = cfg->ReadBool(_T("/browser_expand_ns"), false);
891  m_BrowserOptions.treeMembers = cfg->ReadBool(_T("/browser_tree_members"), true);
892 
893  // Token tree
894  m_BrowserOptions.displayFilter = (BrowserDisplayFilter)cfg->ReadInt(_T("/browser_display_filter"), bdfFile);
895  m_BrowserOptions.sortType = (BrowserSortType)cfg->ReadInt(_T("/browser_sort_type"), bstKind);
896 
897  // Page "Documentation:
898  m_Options.storeDocumentation = cfg->ReadBool(_T("/use_documentation_helper"), false);
899 
900  // force re-read of file types
902  wxUnusedVar(ft_dummy);
903 }
904 
906 {
907  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
908 
909  // Page "Code Completion"
910  cfg->Write(_T("/use_SmartSense"), m_Options.useSmartSense);
911  cfg->Write(_T("/while_typing"), m_Options.whileTyping);
912 
913  // Page "C / C++ parser"
914  cfg->Write(_T("/parser_follow_local_includes"), m_Options.followLocalIncludes);
915  cfg->Write(_T("/parser_follow_global_includes"), m_Options.followGlobalIncludes);
916  cfg->Write(_T("/want_preprocessor"), m_Options.wantPreprocessor);
917  cfg->Write(_T("/parse_complex_macros"), m_Options.parseComplexMacros);
918  cfg->Write(_T("/platform_check"), m_Options.platformCheck);
919 
920  // Page "Symbol browser"
921  cfg->Write(_T("/browser_show_inheritance"), m_BrowserOptions.showInheritance);
922  cfg->Write(_T("/browser_expand_ns"), m_BrowserOptions.expandNS);
923  cfg->Write(_T("/browser_tree_members"), m_BrowserOptions.treeMembers);
924 
925  // Token tree
926  cfg->Write(_T("/browser_display_filter"), m_BrowserOptions.displayFilter);
927  cfg->Write(_T("/browser_sort_type"), m_BrowserOptions.sortType);
928 
929  // Page "Documentation":
930  // m_Options.storeDocumentation will be written by DocumentationPopup
931 }
932 
934 {
935  if (task)
936  m_tasksQueue.push_back(task);
937 }
938 
940 {
941  if ( task && m_tasksQueue.size() )
942  m_tasksQueue.pop_back();
943 }
944 
946 {
947  if ( m_tasksQueue.size() )
948  {
949  for (TasksQueue::iterator it = m_tasksQueue.begin(); it != m_tasksQueue.end(); ++it)
950  (*it)->Abort();
951  }
952 }
LoaderBase * loader
Definition: parserthread.h:128
void AddParserThread(cbThreadedTask *task)
Remember a newly created internal running threads.
Definition: parser.cpp:933
bool Parse()
Do the main job (syntax analysis) here.
bool Done() const
Tells if the pool has finished its job.
Definition: cbthreadpool.h:345
bool m_IsBatchParseDone
used to measure batch parse time
Definition: parser.h:351
wxMutex s_TokenTreeMutex
Definition: tokentree.cpp:49
wxString fileOfBuffer
which file the buffer belongs to, this usually happens when we parse a piece of the cbEditor and the ...
Definition: parserthread.h:76
BrowserSortType
specify the sort order of the symbol tree nodes
Definition: parser_base.h:49
A parser threaded task, which can be assigned to the thread task pool, and run there.
Definition: parserthread.h:138
bool caseSensitive
parse XXX.h in directive #include <XXX.h>
Definition: parser_base.h:113
int wxNewId()
bool whileTyping
use real AI(scope sequence match) or not(plain text match)
Definition: parser_base.h:116
size_t InsertFileOrGetIndex(const wxString &filename)
put the filename in the m_FilenameMap, and return the file index, if this file is already in the m_Fi...
Definition: tokentree.cpp:835
bool m_IgnoreThreadEvents
Parser::OnAllThreadsDone will be called when m_Pool finished its job, but when we run a batch parsing...
Definition: parser.h:341
bool followLocalIncludes
parse the file in #include "file" directive
Definition: parserthread.h:96
bool useSmartSense
handle preprocessor directive in Tokenizer class
Definition: parser_base.h:115
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
int ReadInt(const wxString &name, int defaultVal=0)
static CCLogger * Get()
Definition: cclogger.cpp:60
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
friend class ParserThread
Definition: parser_base.h:126
bool IsRunning() const
bool followLocalIncludes
Definition: parser_base.h:111
static const int PARSER_BATCHPARSE_TIMER_RUN_IMMEDIATELY
Definition: parser.cpp:78
#define CC_LOCKER_TRACK_P_MTX_UNLOCK
Definition: cclogger.h:174
bool platformCheck
not used
Definition: parserthread.h:108
bool isTemp
this value is passed to the generated Token&#39;s m_IsTemp property
Definition: parserthread.h:93
virtual bool RemoveFile(const wxString &filename)
this usually happens when the user removes a file from the existing project, it will remove all the t...
Definition: parser.cpp:477
static bool IsAppShuttingDown()
Definition: manager.cpp:333
wxStopWatch m_StopWatch
a stop watch to measure parsing time
Definition: parser.h:331
ParserOptions m_Options
options for how the parser try to parse files
Definition: parser_base.h:196
virtual void ReadOptions()
read Parser options from configure file
Definition: parser.cpp:855
const wxString GetFilename(size_t fileIdx) const
Definition: tokentree.cpp:858
void AbortParserThreads()
Tell internal running threads to abort further processing.
Definition: parser.cpp:945
void OnBatchTimer(wxTimerEvent &event)
A timer is used to optimized the event handling for parsing, e.g.
Definition: parser.cpp:703
bool bufferSkipOuterBlocks
not used
Definition: parserthread.h:90
bool ReadBool(const wxString &name, bool defaultVal=false)
void EraseFilesToBeReparsedByIndex(size_t fileIdx)
Definition: tokentree.h:232
bool m_NeedMarkFileAsLocal
if true, all the files of the current project will be labeled as "local"
Definition: parser.h:357
bool storeDocumentation
this will check for the platform of the project/target when adding include folders to the parser ...
Definition: parser_base.h:119
FileManager * GetFileManager() const
Definition: manager.cpp:479
bool m_NeedsReparse
Indicates some files in the current project need to be re-parsed, this is commonly caused that the "r...
Definition: parser.h:310
bool showInheritance
whether the base class or derive class information is shown as a child node default: false ...
Definition: parser_base.h:72
BrowserOptions m_BrowserOptions
options for how the symbol browser was shown
Definition: parser_base.h:199
virtual void WriteOptions()
write Parse options to configure file
Definition: parser.cpp:905
alphabetical
Definition: parser_base.h:52
bool Parse(const wxString &filename, bool isLocal=true, bool locked=false)
parse the file, either immediately or delayed.
Definition: parser.cpp:273
long Time() const
bool platformCheck
this will let the Tokenizer to recursive expand macros
Definition: parser_base.h:118
int parentIdxOfBuffer
when parsing a function body, all the tokens are the children of the function token ...
Definition: parserthread.h:79
#define _T(string)
size_t realsize()
some position of the std::vector<Token*> are not used, so the real size maybe a bit smaller than the ...
Definition: tokentree.cpp:103
virtual bool AddFile(const wxString &filename, cbProject *project, bool isLocal=true)
this usually happens when user adds some files to an existing project, it just use AddParse() functio...
Definition: parser.cpp:494
virtual bool Done()
check to see whether Parser is in Idle mode, there is no work need to be done in the Parser ...
Definition: parser.cpp:151
int GetId() const
std::list< wxString > StringList
Definition: parser_base.h:20
DLLIMPORT FileType FileTypeOf(const wxString &filename)
Definition: globals.cpp:285
int idParserStart
Definition: parser.cpp:93
size_t GetFileMapSize() const
Definition: tokentree.h:207
void OnAllThreadsDone(CodeBlocksEvent &event)
When a ThreadPool batch parse stage is done, it will issue a cbEVT_THREADTASK_ALLDONE message...
Definition: parser.cpp:572
EVTIMPORT const wxEventType cbEVT_THREADTASK_ALLDONE
Definition: sdk_events.cpp:127
virtual bool Start(int milliseconds=-1, bool oneShot=wxTIMER_CONTINUOUS)
wxString m_LastPredefinedMacros
Definition: parser.h:348
A generic Code::Blocks event.
Definition: sdk_events.h:20
virtual void AddBatchParse(const StringList &filenames)
Add files to batch parse mode, internally.
Definition: parser.cpp:227
EFileType FileType(const wxString &filename, bool force_refresh=false)
return a file type, which can be either header files or implementation files or other files ...
void DebugLog(const wxString &msg)
Definition: cclogger.cpp:107
bool ParseBufferForNamespaces(const wxString &buffer, NameSpaceVec &result)
Get the context "namespace XXX { ... }" directive.
virtual ~Parser()
destructor
Definition: parser.cpp:119
StringList m_BatchParseFiles
All other batch parse files, like the normal headers/sources.
Definition: parser.h:344
mark all the tokens belong to the project as "local" E.g.
Parser(wxEvtHandler *parent, cbProject *project)
constructor
Definition: parser.cpp:98
bool expandNS
whether a namespaces node is auto-expand auto-expand means the child of the namespace is automaticall...
Definition: parser_base.h:79
std::vector< NameSpace > NameSpaceVec
Definition: parserthread.h:34
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
friend class ParserThreadedTask
Definition: parser.h:119
void Pause()
virtual void Stop()
virtual bool ParseBufferForUsingNamespace(const wxString &buffer, wxArrayString &result, bool bufferSkipBlocks=true)
parse the buffer for collecting using namespace directive
Definition: parser.cpp:451
Represents a Code::Blocks project.
Definition: cbproject.h:96
void RemoveFile(const wxString &filename)
remove tokens belong to the file
Definition: tokentree.cpp:549
TokenTree * m_TempTokenTree
a temp Token tree hold some temporary tokens, e.g.
Definition: parser_base.h:193
virtual bool ParseBufferForNamespaces(const wxString &buffer, NameSpaceVec &result)
parse the buffer for collecting exposed namespace scopes
Definition: parser.cpp:426
void ReparseModifiedFiles()
delete those files from the TokenTree, and add them again through AddParse() function ...
Definition: parser.cpp:757
size_t GetFileStatusCountForIndex(size_t fileIdx) const
Definition: tokentree.h:222
virtual const wxString & GetTitle() const
Read the target&#39;s title.
EFileType
the enum type of the file type
Definition: parser_base.h:25
cbProject * m_Project
referring to the C::B cbp project currently parsing in one parser per workspace mode ...
Definition: parser.h:288
bool handleFunctions
whether to parse the functions
Definition: parserthread.h:111
bool m_StopWatchRunning
Definition: parser.h:332
const TokenFileSet * GetFilesToBeReparsed() const
Definition: tokentree.h:202
void EndStopWatch()
Definition: parser.cpp:684
TokenTree * m_TokenTree
each Parser class contains a TokenTree object which used to record tokens per project this tree will ...
Definition: parser_base.h:187
bool wantPreprocessor
case sensitive in MarkItemsByAI
Definition: parser_base.h:114
void StartStopWatch()
Definition: parser.cpp:675
bool wantPreprocessor
handle the #if like preprocessor directives, this value is passed to Tokenizer
Definition: parserthread.h:102
wxEventType wxEVT_TIMER
#define CC_LOCKER_TRACK_TT_MTX_UNLOCK(M)
Definition: cclogger.h:165
const wxStringCharType * wx_str() const
virtual void AddPredefinedMacros(const wxString &defs)
set the predefined macro definition string was collected from the GCC command line, this function adds the string to an internal m_PredefinedMacros, and switch the ParserState
Definition: parser.cpp:184
#define wxTIMER_ONE_SHOT
wxEvtHandler * m_Parent
when initialized, this variable will be an instance of a NativeParser
Definition: parser.h:285
wxString wxEmptyString
virtual bool UpdateParsingProject(cbProject *project)
set the associated C::B project pointer.
Definition: parser.cpp:553
bool m_IsParsing
true, if the parser is still busy with parsing, false if the parsing stage has finished this value is...
Definition: parser.h:304
ParserCommon::ParserState m_ParserState
indicated the current state the parser
Definition: parser.h:354
bool parseComplexMacros
not used
Definition: parserthread.h:105
static const int PARSER_BATCHPARSE_TIMER_DELAY_LONG
Definition: parser.cpp:79
virtual bool IsFileParsed(const wxString &filename)
check to see a file is parsed already, it first check the TokenTree to see whether it has the specifi...
Definition: parser.cpp:821
bool storeDocumentation
should tokenizer detect and store doxygen documentation?
Definition: parserthread.h:126
bool followGlobalIncludes
parse XXX.h in directive #include "XXX.h"
Definition: parser_base.h:112
virtual void AddParse(const wxString &filename)
Add one file to Batch mode Parsing, this is the bridge between the main thread and the thread pool...
Definition: parser.cpp:253
#define cbThrow(message)
Definition: cbexception.h:42
#define CC_LOCKER_TRACK_TT_MTX_LOCK(M)
Definition: cclogger.h:159
cb_must_consume_result LoaderBase * Load(const wxString &file, bool reuseEditors=false)
Loads a file, once this function is called, the actually loading process is done in the worker thread...
virtual bool Reparse(const wxString &filename, bool isLocal=true)
mark this file to be re-parsed in the TokenTree, tick the reparse timer, note it looks like the isLoc...
Definition: parser.cpp:515
TasksQueue m_tasksQueue
Definition: parser.h:361
long m_LastStopWatchTime
Definition: parser.h:333
BrowserDisplayFilter displayFilter
token filter option
Definition: parser_base.h:88
void RemoveParserThread(cbThreadedTask *task)
Remove a completed internal running threads.
Definition: parser.cpp:939
int GetId() const
return the pool ID
Definition: cbthreadpool.h:49
bool IsEmpty() const
BrowserDisplayFilter
specify the scope of the shown symbols
Definition: parser_base.h:40
#define CC_LOCKER_TRACK_P_MTX_LOCK
Definition: cclogger.h:173
cbThreadPool m_Pool
Thread Pool, executing all the ParserThread, used in batch parse mode.
Definition: parser.h:298
void Clear()
This is what you have to use instead of wxThread to add tasks to the Thread Pool. ...
bool treeMembers
show members in the bottom tree.
Definition: parser_base.h:82
void Start(long milliseconds=0)
non of the above three status, this means our Parser has finish all the jobs, and it is in idle mode ...
Definition: parser.h:104
virtual const wxString GetPredefinedMacros() const
return the predefined macro definition string that has been collected
Definition: parser.cpp:221
some files are changed by the user, so we are parsing the changed files
Definition: parser.h:96
a cbThreadedTask can be executed in cbThreadPool to do a lot of parsing jobs in the begining stage of...
bool useBuffer
useBuffer specifies that we&#39;re not parsing a file, but a temporary buffer.
Definition: parserthread.h:71
wxString m_PredefinedMacros
Pre-defined macros, its a buffer queried from the compiler command line.
Definition: parser.h:347
void wxMilliSleep(unsigned long milliseconds)
virtual void ClearPredefinedMacros()
clears the list of predefined macros after it has been parsed
Definition: parser.cpp:211
bool ParseBufferForUsingNamespace(const wxString &buffer, wxArrayString &result)
Get the context "using namespace XXX" directive.
static const int PARSER_BATCHPARSE_TIMER_DELAY
Definition: parser.cpp:77
void AddTask(cbThreadedTask *task, bool autodelete=true)
Adds a new task to the pool.
void OnReparseTimer(wxTimerEvent &event)
some files in the Tokentree is marked as need to be reparsed, this can be done by a call of Reparse()...
Definition: parser.cpp:697
bool parseComplexMacros
reparse the active editor while editing
Definition: parser_base.h:117
BrowserSortType sortType
token sort option in the tree default: bstKind
Definition: parser_base.h:93
void EraseFileStatusByIndex(size_t fileIdx)
Definition: tokentree.h:227
void DisconnectEvents()
connect event handlers of the timers and thread pool
Definition: parser.cpp:143
virtual bool ParseBufferForFunctions(const wxString &buffer)
parser the current editor control, this function is used to list all the functions in the current cod...
Definition: parser.cpp:398
void ProcessParserEvent(ParserCommon::ParserState state, int id, const wxString &info=wxEmptyString)
The parser will let its parent (NativeParser) to handle the event, as the CodeCompletion instance was...
Definition: parser.cpp:845
int idParserEnd
Definition: parser.cpp:94
bool followGlobalIncludes
parse the file in #include <file> directive
Definition: parserthread.h:99
the Parser object is newly created, and we are parsing the predefined macro buffer, the source files, and finally mark the project&#39;s tokens as local
Definition: parser.h:93
static wxMutex s_ParserMutex
Definition: parser.cpp:91
size_t ReserveFileForParsing(const wxString &filename, bool preliminary=false)
mark a file to be parsed.
Definition: tokentree.cpp:896
the user has add some files to the cbproject, so we are parsing the new added files ...
Definition: parser.h:99
int initLineOfBuffer
since we are not parsing start from the first line of the file, this is the first line number of the ...
Definition: parserthread.h:84
void EraseFileMapInFileMap(size_t fileIdx)
Definition: tokentree.h:217
static const int PARSER_REPARSE_TIMER_DELAY
Definition: parser.cpp:80
virtual bool ParseFile(const wxString &filename, bool isGlobal, bool locked=false)
the only usage of this function is in the Parserthread class, when handling include directives the pa...
Definition: parser.cpp:660
virtual wxString NotDoneReason()
if the Parser is not in Idle mode, show which need to be done
Definition: parser.cpp:165
wxTimer m_BatchTimer
a timer to delay the operation of batch parsing, see OnBatchTimer() member function as a reference ...
Definition: parser.h:328
int Printf(const wxString &pszFormat,...)
wxTimer m_ReparseTimer
a file is need to be reparsed, maybe another file will to be reparsed very soon, so use a timer to co...
Definition: parser.h:323
bool IsFileParsed(const wxString &filename)
is the file name is in the tokentree, and it&#39;s status is either assigned or beingparsed or done also...
Definition: tokentree.cpp:863
static volatile Parser * s_CurrentParser
Definition: parser.cpp:84
#define TRACE(format, args...)
Definition: parser.cpp:71
bool bufferSkipBlocks
do we parse inside the {...} body
Definition: parserthread.h:87
void FlagFileForReparsing(const wxString &filename)
mark the file as "need to be reparsed" status, usually happens that this file is saved(updated) so a ...
Definition: tokentree.cpp:926
virtual bool ParseBuffer(const wxString &buffer, bool isLocal, bool bufferSkipBlocks=false, bool isTemp=false, const wxString &filename=wxEmptyString, int parentIdx=-1, int initLine=0)
Must add a locker before call all named ParseBufferXXX functions, ParseBuffer function will directly ...
Definition: parser.cpp:364
void TerminateAllThreads()
cancel all the tasks in the thread pool m_Pool
Definition: parser.cpp:541
void AbortAllTasks()
Aborts all running and pending tasks.
void ConnectEvents()
connect event handlers of the timers and thread pool
Definition: parser.cpp:135
Parser class holds all the tokens of a C::B project.
Definition: parser.h:117