void RefactoringStorage::StoreTokens(const wxString& filename, const CppToken::List_t& tokens, bool startTx) { if ( !IsCacheReady() ) { return; } if ( !m_db.IsOpen() ) return; try { if ( startTx ) { Begin(); } DoDeleteFile(filename); CppToken::List_t::const_iterator iter = tokens.begin(); for(; iter != tokens.end(); ++iter ) { iter->store( &m_db ); } DoUpdateFileTimestamp(filename); if ( startTx ) { Commit(); } } catch (wxSQLite3Exception &e) { if ( startTx ) { Rollback(); } wxUnusedVar(e); } }
void *Entry() { RefactoringStorage storage; storage.Open(m_workspaceFile); storage.m_cacheStatus = RefactoringStorage::CACHE_READY; wxCommandEvent evtStatus1(wxEVT_REFACTORING_ENGINE_CACHE_INITIALIZING); evtStatus1.SetInt(0); evtStatus1.SetString( m_workspaceFile ); EventNotifier::Get()->AddPendingEvent( evtStatus1 ); size_t count = 0; storage.Begin(); wxFileList_t::const_iterator iter = m_files.begin(); for(; iter != m_files.end(); ++iter ) { if ( TestDestroy() ) { // we requested to stop storage.Commit(); wxCommandEvent evtStatus2(wxEVT_REFACTORING_ENGINE_CACHE_INITIALIZING); evtStatus2.SetInt(100); evtStatus2.SetString( m_workspaceFile ); EventNotifier::Get()->AddPendingEvent( evtStatus2 ); return NULL; } if ( !TagsManagerST::Get()->IsValidCtagsFile( (*iter) ) ) { continue; } ++count; if ( count % 100 == 0 ) { storage.Commit(); storage.Begin(); } wxString fullpath = iter->GetFullPath(); if ( !storage.IsFileUpToDate(fullpath) ) { CppWordScanner scanner( fullpath ); CppToken::List_t tokens = scanner.tokenize(); if ( false ) { CppToken::List_t::iterator tokIter = tokens.begin(); for(; tokIter != tokens.end(); ++tokIter ) { wxPrintf("%s | %s | %d\n", tokIter->getFilename().c_str(), tokIter->getName().c_str(), (int)tokIter->getOffset()); } } storage.StoreTokens( fullpath, tokens, false ); } } storage.Commit(); wxCommandEvent evtStatus2(wxEVT_REFACTORING_ENGINE_CACHE_INITIALIZING); evtStatus2.SetInt(100); evtStatus2.SetString( m_workspaceFile ); EventNotifier::Get()->AddPendingEvent( evtStatus2 ); return NULL; }
CppToken::List_t RefactoringStorage::GetTokens(const wxString& symname, const wxFileList_t& filelist) { if ( !IsCacheReady() ) { return CppToken::List_t(); } CppToken::List_t tokens = CppToken::loadByName(&m_db, symname); // Include only tokens which belongs to the current list of files // unless the filelist is empty and in this case, we ignore this filter if ( filelist.empty() ) { return tokens; } CppToken::List_t::iterator iter = std::remove_if(tokens.begin(), tokens.end(), CppToken::RemoveIfNotIn(filelist)); tokens.resize(std::distance(tokens.begin(), iter)); return tokens; }
void RefactoringEngine::RenameLocalSymbol(const wxString& symname, const wxFileName& fn, int line, int pos) { // Clear previous results Clear(); // Load the file and get a state map + the text from the scanner CppWordScanner scanner(fn.GetFullPath()); // get the current file states TextStatesPtr states = scanner.states(); if( !states ) { return; } // get the local by scanning from the current function's TagEntryPtr tag = TagsManagerST::Get()->FunctionFromFileLine(fn, line + 1); if( !tag ) { return; } // Get the line number of the function int funcLine = tag->GetLine() - 1; // Convert the line number to offset int from = states->LineToPos (funcLine); int to = states->FunctionEndPos(from); if(to == wxNOT_FOUND) return; // search for matches in the given range CppTokensMap l; scanner.Match(symname, l, from, to); CppToken::List_t tokens; l.findTokens(symname, tokens); if (tokens.empty()) return; // Loop over the matches // Incase we did manage to resolve the word, it means that it is NOT a local variable (DoResolveWord only wors for globals NOT for locals) RefactorSource target; std::list<CppToken>::iterator iter = tokens.begin(); for (; iter != tokens.end(); iter++) { wxFileName f( iter->getFilename() ); if (!DoResolveWord(states, wxFileName(iter->getFilename()), iter->getOffset(), line, symname, &target)) { m_candidates.push_back( *iter ); } } }
void CppTokensMap::addToken(const wxString& name, const CppToken::List_t &list) { // try to locate an entry with this name std::map<wxString, std::list<CppToken>* >::iterator iter = m_tokens.find( name ); std::list<CppToken> *tokensList(NULL); if (iter != m_tokens.end()) { tokensList = iter->second; } else { // create new list and add it to the map tokensList = new std::list<CppToken>; m_tokens.insert( std::make_pair(name, tokensList) ); } tokensList->insert(tokensList->end(), list.begin(), list.end()); }
void RefactoringEngine::DoFindReferences(const wxString& symname, const wxFileName& fn, int line, int pos, const wxFileList_t& files, bool onlyDefiniteMatches) { // Clear previous results Clear(); if ( ! m_storage.IsCacheReady() ) { m_storage.InitializeCache( files ); return; } // Container for the results found in the 'files' CppTokensMap tokensMap; // Load the file and get a state map + the text from the scanner CppWordScanner scanner(fn.GetFullPath()); // get the current file states TextStatesPtr states = scanner.states(); if(!states) return; // Attempt to understand the expression that the caret is currently located at (using line:pos:file) RefactorSource rs; if(!DoResolveWord(states, fn, pos + symname.Len(), line, symname, &rs)) return; wxFileList_t modifiedFilesList = m_storage.FilterUpToDateFiles( files ); clProgressDlg* prgDlg = NULL; if ( !modifiedFilesList.empty() ) { prgDlg = CreateProgressDialog(_("Updating cache..."), files.size()); // Search the provided input files for the symbol to rename and prepare // a CppTokensMap for (size_t i=0; i<modifiedFilesList.size(); i++) { wxFileName curfile = modifiedFilesList.at(i); wxString msg; msg << _("Caching file: ") << curfile.GetFullName(); // update the progress bar if (!prgDlg->Update(i, msg)) { prgDlg->Destroy(); Clear(); return; } // Scan only valid C / C++ files switch(FileExtManager::GetType(curfile.GetFullName())) { case FileExtManager::TypeHeader: case FileExtManager::TypeSourceC: case FileExtManager::TypeSourceCpp: { // load matches for a give symbol m_storage.Match(symname, curfile.GetFullPath(), tokensMap); } break; default: break; } } prgDlg->Destroy(); } // load all tokens, first we need to parse the workspace files... CppToken::List_t tokens = m_storage.GetTokens(symname, files); if (tokens.empty()) return; // sort the tokens tokens.sort(); RefactorSource target; std::list<CppToken>::iterator iter = tokens.begin(); int counter(0); TextStatesPtr statesPtr(NULL); wxString statesPtrFileName; prgDlg = CreateProgressDialog(_("Stage 2/2: Parsing matches..."), (int) tokens.size()); for (; iter != tokens.end(); ++iter) { // TODO :: send an event here to report our progress wxFileName f( iter->getFilename() ); wxString msg; msg << _("Parsing expression ") << counter << wxT("/") << tokens.size() << _(" in file: ") << f.GetFullName(); if ( !prgDlg->Update(counter, msg) ) { // user clicked 'Cancel' Clear(); prgDlg->Destroy(); return; } counter++; // reset the result target.Reset(); if(!statesPtr || statesPtrFileName != iter->getFilename() ) { // Create new statesPtr CppWordScanner sc(iter->getFilename()); statesPtr = sc.states(); statesPtrFileName = iter->getFilename(); } if(!statesPtr) continue; if (DoResolveWord(statesPtr, wxFileName( iter->getFilename() ), iter->getOffset(), iter->getLineNumber(), symname, &target)) { // set the line number if(statesPtr->states.size() > iter->getOffset()) iter->setLineNumber( statesPtr->states[iter->getOffset()].lineNo ); if (target.name == rs.name && target.scope == rs.scope) { // full match m_candidates.push_back( *iter ); } else if (target.name == rs.scope && !rs.isClass) { // source is function, and target is class m_candidates.push_back( *iter ); } else if (target.name == rs.name && rs.isClass) { // source is class, and target is ctor m_candidates.push_back( *iter ); } else if (!onlyDefiniteMatches) { // add it to the possible match list m_possibleCandidates.push_back( *iter ); } } else if( !onlyDefiniteMatches) { // resolved word failed, add it to the possible list m_possibleCandidates.push_back( *iter ); } } prgDlg->Destroy(); }