void CCTestFrame::OnMenuTokenSelected(wxCommandEvent& /*event*/) { ParserBase* pb = CCTest::Get()->GetParser(); TokenTree* tt = CCTest::Get()->GetTokenTree(); if (!pb || !tt) return; wxTextEntryDialog dlg(this, _T("Enter name of token to debug:"), _T("CCTest")); if (dlg.ShowModal()==wxID_OK) { wxString target = dlg.GetValue().Trim(true).Trim(false); if (target.IsEmpty()) return; // Search over all tokens, no AI whatsoever available bool found = false; for (size_t i=0; i<tt->size(); ++i) { Token* t = tt->at(i); if (t && t->m_Name.Matches(target)) { CCDebugInfo di(this, pb, t); di.ShowModal(); found = true; break; // found, exit for-loop } } if (!found) wxMessageBox(_("Token not found."), _("CCTest"), wxOK | wxICON_INFORMATION, this); } }
int MarkFileAsLocalThreadedTask::Execute() { TRACE(_T("MarkFileAsLocalThreadedTask::Execute()")); if (!m_Project) return 0; if (!m_Parser) return 0; // mark all project files as local for (FilesList::const_iterator it = m_Project->GetFilesList().begin(); it != m_Project->GetFilesList().end(); ++it) { ProjectFile* pf = *it; if (!pf) continue; if (ParserCommon::FileType(pf->relativeFilename) != ParserCommon::ftOther) { TokenTree* tree = m_Parser->GetTokenTree(); CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex) tree->MarkFileTokensAsLocal(pf->file.GetFullPath(), true, m_Project); CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex) } }
void CCDebugInfo::FillDescendants() { TokenTree* tree = m_Parser->GetTokenTree(); if (!tree) return; cmbDescendants->Clear(); for (TokenIdxSet::const_iterator it = m_Token->m_Descendants.begin(); it != m_Token->m_Descendants.end(); ++it) { const Token* descendant = tree->at(*it); const wxString msgInvalidToken = _("<invalid token>"); cmbDescendants->Append(wxString::Format(_T("%s (%d)"), descendant ? descendant->m_Name.wx_str() : msgInvalidToken.wx_str(), *it)); } cmbDescendants->SetSelection(0); }
void ClassBrowserBuilderThread::Init(NativeParser* np, CCTreeCtrl* treeTop, CCTreeCtrl* treeBottom, const wxString& active_filename, void* user_data, // active project const BrowserOptions& bo, TokenTree* tt, int idThreadEvent) { TRACE(_T("ClassBrowserBuilderThread::Init")); CC_LOCKER_TRACK_CBBT_MTX_LOCK(m_ClassBrowserBuilderThreadMutex); m_NativeParser = np; m_CCTreeCtrlTop = treeTop; m_CCTreeCtrlBottom = treeBottom; m_ActiveFilename = active_filename; m_UserData = user_data; m_BrowserOptions = bo; m_TokenTree = tt; m_idThreadEvent = idThreadEvent; m_CurrentFileSet.clear(); m_CurrentTokenSet.clear(); TokenTree* tree = m_NativeParser->GetParser().GetTokenTree(); // fill filter set for current-file-filter if ( m_BrowserOptions.displayFilter == bdfFile && !m_ActiveFilename.IsEmpty() ) { // m_ActiveFilename is the full filename up to the extension dot. No extension though. // get all filenames' indices matching our mask wxArrayString paths = m_NativeParser->GetAllPathsByFilename(m_ActiveFilename); // Should add locker after called m_NativeParser->GetAllPathsByFilename CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex) TokenFileSet result; for (size_t i = 0; i < paths.GetCount(); ++i) { tree->GetFileMatches(paths[i], result, true, true); for (TokenFileSet::const_iterator tfs_it = result.begin(); tfs_it != result.end(); ++tfs_it) m_CurrentFileSet.insert(*tfs_it); } CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex) }
void CCDebugInfo::OnFindClick(cb_unused wxCommandEvent& event) { TokenTree* tree = m_Parser->GetTokenTree(); if (!tree) return; wxString search = txtFilter->GetValue(); m_Token = 0; // first determine if the user entered an ID or a search mask long unsigned id; if (search.ToULong(&id, 10)) { // easy; ID m_Token = tree->at(id); } else { // find all matching tokens TokenIdxSet result; for (size_t i = 0; i < tree->size(); ++i) { const Token* token = tree->at(i); if (token && token->m_Name.Matches(search)) result.insert(i); } // a single result? if (result.size() == 1) m_Token = tree->at(*(result.begin())); else { // fill a list and ask the user which token to display wxArrayString arr; wxArrayInt intarr; for (TokenIdxSet::const_iterator it = result.begin(); it != result.end(); ++it) { const Token* token = tree->at(*it); arr.Add(token->DisplayName()); intarr.Add(*it); } int sel = wxGetSingleChoiceIndex(_("Please make a selection:"), _("Multiple matches"), arr, this); if (sel == -1) return; m_Token = tree->at(intarr[sel]); } } DisplayTokenInfo(); }
void CCTestFrame::Start() { if (m_ParserCtrl) m_ParserCtrl->SetSelection(1); // make sure "Output" tab is selected CCTestAppGlobal::s_includeDirs.Clear(); CCTestAppGlobal::s_fileQueue.Clear(); CCTestAppGlobal::s_filesParsed.Clear(); // Obtain all include directories wxStringTokenizer tkz_inc(m_IncludeCtrl->GetValue(), _T("\r\n")); while ( tkz_inc.HasMoreTokens() ) { wxString include = tkz_inc.GetNextToken().Trim(true).Trim(false); if (!include.IsEmpty()) CCTestAppGlobal::s_includeDirs.Add(include); } if (m_DoHeadersCtrl->IsChecked()) { // Obtain all priority header files wxStringTokenizer tkz_hdr(m_HeadersCtrl->GetValue(), _T(",")); while (tkz_hdr.HasMoreTokens()) { wxString header = tkz_hdr.GetNextToken().Trim(false).Trim(true); // Remove <> (if any) int lt = header.Find(wxT('<')); int gt = header.Find(wxT('>'),true); if (lt!=wxNOT_FOUND && gt!=wxNOT_FOUND && gt>lt) header = header.AfterFirst(wxT('<')).BeforeLast(wxT('>')); // Remove "" (if any) int oq = header.Find(wxT('"')); int cq = header.Find(wxT('"'),true); if (oq!=wxNOT_FOUND && cq!=wxNOT_FOUND && cq>oq) header = header.AfterFirst(wxT('"')).BeforeLast(wxT('"')); header = header.Trim(false).Trim(true); // Find the header files in include path's as provided // (practically the same as ParserBase::FindFileInIncludeDirs()) for (size_t i=0; i<CCTestAppGlobal::s_includeDirs.GetCount(); ++i) { // Normalize the path (as in C::B's "NormalizePath()") wxFileName f_header(header); wxString base_path(CCTestAppGlobal::s_includeDirs[i]); if (f_header.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, base_path)) { wxString this_header = f_header.GetFullPath(); if ( ::wxFileExists(this_header) ) CCTestAppGlobal::s_fileQueue.Add(this_header); } } } } if (CCTestAppGlobal::s_fileQueue.IsEmpty() && !m_Control->GetLength()) { wxMessageBox(wxT("Main file not found and buffer empty. Nothing to do."), _("Information"), wxOK | wxICON_INFORMATION, this); return; } if (m_DoHideCtrl && m_DoHideCtrl->IsChecked()) Hide(); m_ProgDlg = new wxProgressDialog(_T("Please wait, operating..."), _("Preparing...\nPlease wait..."), 0, this, wxPD_APP_MODAL); m_ProgDlg->SetSize(640,100); m_ProgDlg->Layout(); m_ProgDlg->CenterOnParent(); m_LogCount = 0; m_LogCtrl->Clear(); CCTest::Get()->Clear(); // initial clearance // make sure not to over-write an existing file (in case content had changed) wxString tf(wxFileName::CreateTempFileName(wxT("cc"))); // make the parser recognise it as header file: wxFileName fn(tf); fn.SetExt(wxT("h")); wxRemoveFile(tf); // no longer needed if (m_Control->SaveFile(fn.GetFullPath())) CCTestAppGlobal::s_fileQueue.Add(fn.GetFullPath()); else AppendToLog(_T("Unable to parse buffer (could not convert to file).")); AppendToLog(_T("--------------M-a-i-n--L-o-g--------------\r\n\r\n")); // parse file from the queue one-by-one while (!CCTestAppGlobal::s_fileQueue.IsEmpty()) { wxString file = CCTestAppGlobal::s_fileQueue.Item(0); CCTestAppGlobal::s_fileQueue.Remove(file); if (file.IsEmpty()) continue; AppendToLog(_T("-----------I-n-t-e-r-i-m--L-o-g-----------")); m_CurrentFile = file; m_ProgDlg->Update(-1, m_CurrentFile); m_StatuBar->SetStatusText(m_CurrentFile); // This is the core parse stage for files CCTest::Get()->Start(m_CurrentFile); CCTestAppGlobal::s_filesParsed.Add(m_CurrentFile); // done } // don't forget to remove the temporary file (w/ ".h" extension) wxRemoveFile(fn.GetFullPath()); m_ProgDlg->Update(-1, wxT("Creating tree log...")); AppendToLog(_T("--------------T-r-e-e--L-o-g--------------\r\n")); CCTest::Get()->PrintTree(); m_ProgDlg->Update(-1, wxT("Creating list log...")); AppendToLog(_T("--------------L-i-s-t--L-o-g--------------\r\n")); CCTest::Get()->PrintList(); if (m_DoTreeCtrl->IsChecked()) { m_ProgDlg->Update(-1, wxT("Serializing tree...")); Freeze(); m_TreeCtrl->SetValue( CCTest::Get()->SerializeTree() ); Thaw(); } // Here we are going to test the expression solving algorithm NativeParserTest nativeParserTest; wxString exp = _T("obj.m_Member1"); TokenIdxSet searchScope; searchScope.insert(-1); TokenIdxSet result; TokenTree *tree = CCTest::Get()->GetTokenTree(); nativeParserTest.TestExpression(exp, tree, searchScope, result ); wxLogMessage(_T("Result have %lu matches"), static_cast<unsigned long>(result.size())); for (TokenIdxSet::iterator it=result.begin(); it!=result.end(); ++it) { Token* token = tree->at(*it); if (token) { wxString log; log << token->GetTokenKindString() << _T(" ") << token->DisplayName() << _T("\t[") << token->m_Line << _T(",") << token->m_ImplLine << _T("]"); CCLogger::Get()->Log(log); } } if (m_ProgDlg) { delete m_ProgDlg; m_ProgDlg = 0; } if ( !IsShown() ) Show(); TokenTree* tt = CCTest::Get()->GetTokenTree(); if (tt) { AppendToLog((wxString::Format(_("The parser contains %lu tokens, found in %lu files."), static_cast<unsigned long>(tt->size()), static_cast<unsigned long>(tt->m_FileMap.size())))); } }
size_t CodeRefactoring::VerifyResult(const TokenIdxSet& targetResult, const wxString& targetText, bool isLocalVariable) { EditorManager* edMan = Manager::Get()->GetEditorManager(); cbEditor* editor = edMan->GetBuiltinActiveEditor(); if (!editor) return 0; const Token* parentOfLocalVariable = nullptr; if (isLocalVariable) { TokenTree* tree = m_NativeParser.GetParser().GetTokenTree(); CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex) const Token* token = tree->at(*targetResult.begin()); parentOfLocalVariable = tree->at(token->m_ParentIndex); CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex) } // now that list is filled, we'll search cbStyledTextCtrl* control = new cbStyledTextCtrl(editor->GetParent(), wxID_ANY, wxDefaultPosition, wxSize(0, 0)); control->Show(false); // styled the text to support control->GetStyleAt() cbEditor::ApplyStyles(control); EditorColourSet edColSet; size_t totalCount = 0; for (SearchDataMap::const_iterator it = m_SearchDataMap.begin(); it != m_SearchDataMap.end(); ++it) totalCount += it->second.size(); // let's create a progress dialog because it might take some time depending on the files count wxProgressDialog* progress = new wxProgressDialog(_("Code Refactoring"), _("Please wait while verifying result..."), totalCount, Manager::Get()->GetAppWindow(), wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); PlaceWindow(progress); size_t task = totalCount; TokenIdxSet result; bool userBreak = false; for (SearchDataMap::iterator it = m_SearchDataMap.begin(); it != m_SearchDataMap.end();) { // check if the file is already opened in built-in editor and do search in it cbEditor* ed = edMan->IsBuiltinOpen(it->first); if (ed) control->SetText(ed->GetControl()->GetText()); else // else load the file in the control { EncodingDetector detector(it->first); if (!detector.IsOK()) { task -= it->second.size(); m_SearchDataMap.erase(it++); continue; // failed } control->SetText(detector.GetWxStr()); } // apply the corlor setting edColSet.Apply(editor->GetLanguage(), control); ccSearchData searchData = { control, it->first }; for (SearchDataList::iterator itList = it->second.begin(); itList != it->second.end();) { // update the progress bar if (!progress->Update(totalCount - (--task))) { userBreak = true; break; // user pressed "Cancel" } // skip string or comment const int style = control->GetStyleAt(itList->pos); if (control->IsString(style) || control->IsComment(style)) { it->second.erase(itList++); continue; } // do cc search const int endOfWord = itList->pos + targetText.Len(); control->GotoPos(endOfWord); m_NativeParser.MarkItemsByAI(&searchData, result, true, false, true, endOfWord); if (result.empty()) { it->second.erase(itList++); continue; } // verify result TokenIdxSet::const_iterator findIter = targetResult.begin(); for (; findIter != targetResult.end(); ++findIter) { if (result.find(*findIter) != result.end()) break; } if (findIter == targetResult.end()) // not found it->second.erase(itList++); else { // handle for local variable if (isLocalVariable) { bool do_continue = false; TokenTree* tree = m_NativeParser.GetParser().GetTokenTree(); CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex) const Token* token = tree->at(*findIter); if (token) { const Token* parent = tree->at(token->m_ParentIndex); if (parent != parentOfLocalVariable) { it->second.erase(itList++); do_continue = true; } } CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex) if (do_continue) continue; } ++itList; } } if (it->second.empty()) m_SearchDataMap.erase(it++); else ++it; if (userBreak) break; } delete control; // done with it delete progress; // done here too return m_SearchDataMap.size(); }
bool CodeRefactoring::Parse() { cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor(); if (!editor) return false; const wxString targetText = GetSymbolUnderCursor(); if (targetText.IsEmpty()) return false; TokenIdxSet targetResult; const int endOfWord = editor->GetControl()->WordEndPosition(editor->GetControl()->GetCurrentPos(), true); m_NativeParser.MarkItemsByAI(targetResult, true, false, true, endOfWord); if (targetResult.empty()) { cbMessageBox(_("Symbol not found under cursor!"), _("Code Refactoring"), wxOK | wxICON_WARNING); return false; } // handle local variables bool isLocalVariable = false; TokenTree* tree = m_NativeParser.GetParser().GetTokenTree(); CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex) const Token* token = tree->at(*targetResult.begin()); if (token) { const Token* parent = tree->at(token->m_ParentIndex); if (parent && parent->m_TokenKind == tkFunction) isLocalVariable = true; } CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex) wxArrayString files; cbProject* project = m_NativeParser.GetProjectByEditor(editor); if (isLocalVariable || !project) files.Add(editor->GetFilename()); else { ScopeDialog scopeDlg(Manager::Get()->GetAppWindow(), _("Code Refactoring")); const int ret = scopeDlg.ShowModal(); if (ret == ScopeDialog::ID_OPEN_FILES) GetOpenedFiles(files); else if (ret == ScopeDialog::ID_PROJECT_FILES) GetAllProjectFiles(files, project); else return false; } if (files.IsEmpty()) return false; size_t count = SearchInFiles(files, targetText); if (count) count = VerifyResult(targetResult, targetText, isLocalVariable); return count != 0; }
void CCDebugInfo::OnSave(cb_unused wxCommandEvent& event) { TokenTree* tree = m_Parser->GetTokenTree(); wxArrayString saveWhat; saveWhat.Add(_("Dump the tokens tree")); saveWhat.Add(_("Dump the serialised tokens tree")); saveWhat.Add(_("Dump the file list")); saveWhat.Add(_("Dump the list of include directories")); saveWhat.Add(_("Dump the token list of files")); int sel = wxGetSingleChoiceIndex(_("What do you want to save?"), _("CC Debug Info"), saveWhat, this); switch (sel) { case -1: // cancelled return; case 0: { wxString tt; { // life time of wxWindowDisabler/wxBusyInfo wxWindowDisabler disableAll; wxBusyInfo running(_("Obtaining tokens tree... please wait (this may take several seconds)..."), Manager::Get()->GetAppWindow()); tt = tree->m_Tree.dump(); } CCDebugInfoHelper::SaveCCDebugInfo(_("Save tokens tree"), tt); } break; case 1: { wxString tt_ser; { // life time of wxWindowDisabler/wxBusyInfo wxWindowDisabler disableAll; wxBusyInfo running(_("Serialising tokens tree... please wait (this may take several seconds)..."), Manager::Get()->GetAppWindow()); tt_ser = tree->m_Tree.Serialize(); } CCDebugInfoHelper::SaveCCDebugInfo(_("Save serialised tokens tree"), tt_ser); } break; case 2: { wxString files; for (size_t i = 0; i < tree->m_FilenameMap.size(); ++i) { wxString file = tree->m_FilenameMap.GetString(i); if (!file.IsEmpty()) files += file + _T("\r\n"); } CCDebugInfoHelper::SaveCCDebugInfo(_("Save file list"), files); } break; case 3: { wxString dirs; const wxArrayString& dirsArray = m_Parser->GetIncludeDirs(); for (size_t i = 0; i < dirsArray.GetCount(); ++i) { const wxString& dir = dirsArray[i]; if (!dir.IsEmpty()) dirs += dir + _T("\r\n"); } CCDebugInfoHelper::SaveCCDebugInfo(_("Save list of include directories"), dirs); } break; case 4: { wxString fileTokens; { wxWindowDisabler disableAll; wxBusyInfo running(_("Obtaining tokens tree... please wait (this may take several seconds)..."), Manager::Get()->GetAppWindow()); for (size_t i = 0; i < tree->m_FilenameMap.size(); ++i) { const wxString file = tree->m_FilenameMap.GetString(i); if (!file.IsEmpty()) { fileTokens += file + _T("\r\n"); TokenIdxSet result; tree->FindTokensInFile(file, result, tkUndefined); for (TokenIdxSet::const_iterator it = result.begin(); it != result.end(); ++it) { const Token* token = tree->at(*it); fileTokens << token->GetTokenKindString() << _T(" "); if (token->m_TokenKind == tkFunction) fileTokens << token->m_Name << token->GetFormattedArgs() << _T("\t"); else fileTokens << token->DisplayName() << _T("\t"); fileTokens << _T("[") << token->m_Line << _T(",") << token->m_ImplLine << _T("]"); fileTokens << _T("\r\n"); } } fileTokens += _T("\r\n"); } } CCDebugInfoHelper::SaveCCDebugInfo(_("Save token list of files"), fileTokens); } break; default: cbMessageBox(_("Invalid selection."), _("CC Debug Info")); } }
void CCDebugInfo::DisplayTokenInfo() { if (!m_Token) { txtID->SetLabel(wxEmptyString); txtName->SetLabel(wxEmptyString); txtKind->SetLabel(wxEmptyString); txtScope->SetLabel(wxEmptyString); txtFullType->SetLabel(wxEmptyString); txtBaseType->SetLabel(wxEmptyString); txtArgs->SetLabel(wxEmptyString); txtArgsStripped->SetLabel(wxEmptyString); txtTemplateArg->SetLabel(wxEmptyString); txtIsOp->SetLabel(wxEmptyString); txtIsLocal->SetLabel(wxEmptyString); txtNamespace->SetLabel(wxEmptyString); txtParent->SetLabel(wxEmptyString); cmbChildren->Clear(); cmbAncestors->Clear(); cmbDescendants->Clear(); txtDeclFile->SetLabel(wxEmptyString); txtImplFile->SetLabel(wxEmptyString); return; } TokenTree* tree = m_Parser->GetTokenTree(); if (!tree) return; const Token* parent = tree->at(m_Token->m_ParentIndex); tree->RecalcInheritanceChain(m_Token); wxString args = m_Token->GetFormattedArgs(); wxString argsStr = m_Token->m_BaseArgs; wxString tmplArg = m_Token->m_TemplateArgument; wxString fullType = m_Token->m_FullType; // so they can be displayed in wxStaticText args.Replace(_T("&"), _T("&&"), true); argsStr.Replace(_T("&"), _T("&&"), true); tmplArg.Replace(_T("&"), _T("&&"), true); fullType.Replace(_T("&"), _T("&&"), true); txtID->SetLabel(wxString::Format(_T("%d"), m_Token->m_Index)); txtName->SetLabel(m_Token->m_Name); txtKind->SetLabel(m_Token->GetTokenKindString()); txtScope->SetLabel(m_Token->GetTokenScopeString()); txtFullType->SetLabel(fullType); txtBaseType->SetLabel(m_Token->m_BaseType); txtArgs->SetLabel(args); txtArgsStripped->SetLabel(argsStr); txtTemplateArg->SetLabel(tmplArg); txtIsOp->SetLabel(m_Token->m_IsOperator ? _("Yes") : _("No")); txtIsLocal->SetLabel(m_Token->m_IsLocal ? _("Yes") : _("No")); txtIsTemp->SetLabel(m_Token->m_IsTemp ? _("Yes") : _("No")); txtIsConst->SetLabel(m_Token->m_IsConst ? _("Yes") : _("No")); txtIsNoExcept->SetLabel(m_Token->m_IsNoExcept ? _("Yes") : _("No")); txtNamespace->SetLabel(m_Token->GetNamespace()); txtParent->SetLabel(wxString::Format(_T("%s (%d)"), parent ? parent->m_Name.c_str() : (const wxChar*)_("<Global namespace>"), m_Token->m_ParentIndex)); FillChildren(); FillAncestors(); FillDescendants(); if (!m_Token->GetFilename().IsEmpty()) txtDeclFile->SetLabel(wxString::Format(_T("%s : %u"), m_Token->GetFilename().c_str(), m_Token->m_Line)); else txtDeclFile->SetLabel(wxEmptyString); if (!m_Token->GetImplFilename().IsEmpty()) txtImplFile->SetLabel(wxString::Format(_("%s : %u (code lines: %u to %u)"), m_Token->GetImplFilename().c_str(), m_Token->m_ImplLine, m_Token->m_ImplLineStart, m_Token->m_ImplLineEnd)); else txtImplFile->SetLabel(wxEmptyString); txtUserData->SetLabel(wxString::Format(_T("0x%p"), m_Token->m_UserData)); }