KDevelop API Documentation

languages/cpp/backgroundparser.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2002 by Roberto Raggi * 00003 * roberto@kdevelop.org * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 ***************************************************************************/ 00011 00012 #include "backgroundparser.h" 00013 #include "cppsupportpart.h" 00014 #include "cppsupport_events.h" 00015 #include "codeinformationrepository.h" 00016 #include "cppcodecompletion.h" 00017 #include "driver.h" 00018 #include "ast_utils.h" 00019 #include "kdevdeepcopy.h" 00020 #include "kdevdriver.h" 00021 00022 #if QT_VERSION < 0x030100 00023 #include <kdevmutex.h> 00024 #else 00025 #include <qmutex.h> 00026 #endif 00027 00028 #include <kparts/part.h> 00029 #include <ktexteditor/editinterface.h> 00030 #include <ktexteditor/document.h> 00031 #include <ktexteditor/view.h> 00032 00033 #include <kdevpartcontroller.h> 00034 #include <kdevproject.h> 00035 00036 #include <kurl.h> 00037 #include <kdebug.h> 00038 #include <kapplication.h> 00039 00040 #include <qfile.h> 00041 #include <qfileinfo.h> 00042 #include <qtextstream.h> 00043 #include <qprocess.h> 00044 00045 class KDevSourceProvider: public SourceProvider 00046 { 00047 public: 00048 KDevSourceProvider( CppSupportPart* cppSupport ) 00049 : m_cppSupport( cppSupport ), 00050 m_readFromDisk( false ) {} 00051 00052 void setReadFromDisk( bool b ) { m_readFromDisk = b; } 00053 bool readFromDisk() const { return m_readFromDisk; } 00054 00055 virtual QString contents( const QString& fileName ) 00056 { 00057 QString contents = QString::null; 00058 00059 if( !m_readFromDisk ) 00060 { 00061 // GET LOCK 00062 kapp->lock(); 00063 00064 //kdDebug(9007) << "-------> kapp locked" << endl; 00065 00066 QPtrList<KParts::Part> parts( *m_cppSupport->partController()->parts() ); 00067 QPtrListIterator<KParts::Part> it( parts ); 00068 while( it.current() ){ 00069 KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>( it.current() ); 00070 ++it; 00071 00072 KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>( doc ); 00073 if( !doc || !editIface || doc->url().path() != fileName ) 00074 continue; 00075 00076 contents = QString( editIface->text().ascii() ); // deep copy 00077 00078 //kdDebug(9007) << "-------> kapp unlocked" << endl; 00079 00080 break; 00081 } 00082 00083 // RELEASE LOCK 00084 kapp->unlock(); 00085 //kdDebug(9007) << "-------> kapp unlocked" << endl; 00086 } 00087 else 00088 { 00089 QFile f( fileName ); 00090 QTextStream stream( &f ); 00091 if( f.open(IO_ReadOnly) ){ 00092 QString contents = stream.read(); 00093 f.close(); 00094 } 00095 } 00096 00097 return contents; 00098 } 00099 00100 virtual bool isModified( const QString& fileName ) 00101 { 00102 Q_UNUSED( fileName ); 00103 return true; 00104 } 00105 00106 private: 00107 CppSupportPart* m_cppSupport; 00108 bool m_readFromDisk; 00109 private: 00110 KDevSourceProvider( const KDevSourceProvider& source ); 00111 void operator = ( const KDevSourceProvider& source ); 00112 }; 00113 00114 class SynchronizedFileList 00115 { 00116 public: 00117 SynchronizedFileList() {} 00118 00119 bool isEmpty() const 00120 { 00121 QMutexLocker locker( &m_mutex ); 00122 return m_fileList.isEmpty(); 00123 } 00124 00125 uint count() const 00126 { 00127 QMutexLocker locker( &m_mutex ); 00128 return m_fileList.count(); 00129 } 00130 00131 QPair<QString, bool> front() const 00132 { 00133 QMutexLocker locker( &m_mutex ); 00134 return m_fileList.front(); 00135 } 00136 00137 void clear() 00138 { 00139 QMutexLocker locker( &m_mutex ); 00140 m_fileList.clear(); 00141 } 00142 00143 void push_back( const QString& fileName, bool readFromDisk=false ) 00144 { 00145 QMutexLocker locker( &m_mutex ); 00146 m_fileList.append( qMakePair(fileName, readFromDisk) ); 00147 } 00148 00149 void pop_front() 00150 { 00151 QMutexLocker locker( &m_mutex ); 00152 m_fileList.pop_front(); 00153 } 00154 00155 bool contains( const QString& fileName ) const 00156 { 00157 QMutexLocker locker( &m_mutex ); 00158 QValueList< QPair<QString, bool> >::ConstIterator it = m_fileList.begin(); 00159 while( it != m_fileList.end() ){ 00160 if( (*it).first == fileName ) 00161 return true; 00162 ++it; 00163 } 00164 return false; 00165 } 00166 00167 void remove( const QString& fileName ) 00168 { 00169 QMutexLocker locker( &m_mutex ); 00170 QValueList< QPair<QString, bool> >::Iterator it = m_fileList.begin(); 00171 while( it != m_fileList.end() ){ 00172 if( (*it).first == fileName ) 00173 m_fileList.remove( it ); 00174 ++it; 00175 } 00176 } 00177 00178 private: 00179 mutable QMutex m_mutex; 00180 QValueList< QPair<QString, bool> > m_fileList; 00181 }; 00182 00183 BackgroundParser::BackgroundParser( CppSupportPart* part, QWaitCondition* consumed ) 00184 : m_consumed( consumed ), m_cppSupport( part ), m_close( false ) 00185 { 00186 m_fileList = new SynchronizedFileList(); 00187 m_driver = new KDevDriver( m_cppSupport ); 00188 m_driver->setSourceProvider( new KDevSourceProvider(m_cppSupport) ); 00189 00190 QString conf_file_name = m_cppSupport->specialHeaderName(); 00191 if( QFile::exists(conf_file_name) ) 00192 m_driver->parseFile( conf_file_name, true ); 00193 00194 //disabled for now m_driver->setResolveDependencesEnabled( true ); 00195 } 00196 00197 BackgroundParser::~BackgroundParser() 00198 { 00199 removeAllFiles(); 00200 00201 delete( m_driver ); 00202 m_driver = 0; 00203 00204 delete m_fileList; 00205 m_fileList = 0; 00206 } 00207 00208 void BackgroundParser::addFile( const QString& fileName, bool readFromDisk ) 00209 { 00210 QString fn = deepCopy( fileName ); 00211 00212 bool added = false; 00213 if( !m_fileList->contains(fn) ){ 00214 m_fileList->push_back( fn, readFromDisk ); 00215 added = true; 00216 } 00217 00218 if( added ) 00219 m_canParse.wakeAll(); 00220 } 00221 00222 void BackgroundParser::removeAllFiles() 00223 { 00224 kdDebug(9007) << "BackgroundParser::removeAllFiles()" << endl; 00225 QMutexLocker locker( &m_mutex ); 00226 00227 QMap<QString, Unit*>::Iterator it = m_unitDict.begin(); 00228 while( it != m_unitDict.end() ){ 00229 Unit* unit = it.data(); 00230 ++it; 00231 delete( unit ); 00232 unit = 0; 00233 } 00234 m_unitDict.clear(); 00235 m_driver->reset(); 00236 m_fileList->clear(); 00237 00238 m_isEmpty.wakeAll(); 00239 } 00240 00241 void BackgroundParser::removeFile( const QString& fileName ) 00242 { 00243 QMutexLocker locker( &m_mutex ); 00244 00245 if( Unit* unit = findUnit(fileName) ){ 00246 m_driver->remove( fileName ); 00247 m_unitDict.remove( fileName ); 00248 delete( unit ); 00249 unit = 0; 00250 } 00251 00252 if( m_fileList->isEmpty() ) 00253 m_isEmpty.wakeAll(); 00254 } 00255 00256 Unit* BackgroundParser::parseFile( const QString& fileName, bool readFromDisk, bool lock ) 00257 { 00258 static_cast<KDevSourceProvider*>( m_driver->sourceProvider() )->setReadFromDisk( readFromDisk ); 00259 00260 m_driver->remove( fileName ); 00261 m_driver->parseFile( fileName ); 00262 m_driver->removeAllMacrosInFile( fileName ); // romove all macros defined by this 00263 // translation unit. 00264 TranslationUnitAST::Node translationUnit = m_driver->takeTranslationUnit( fileName ); 00265 00266 Unit* unit = new Unit; 00267 unit->fileName = fileName; 00268 unit->translationUnit = translationUnit.release(); 00269 unit->problems = m_driver->problems( fileName ); 00270 00271 static_cast<KDevSourceProvider*>( m_driver->sourceProvider() )->setReadFromDisk( false ); 00272 00273 if( lock ) 00274 m_mutex.lock(); 00275 00276 if( m_unitDict.find(fileName) != m_unitDict.end() ){ 00277 Unit* u = m_unitDict[ fileName ]; 00278 m_unitDict.remove( fileName ); 00279 delete( u ); 00280 u = 0; 00281 } 00282 00283 m_unitDict.insert( fileName, unit ); 00284 00285 if( lock ) 00286 m_mutex.unlock(); 00287 00288 KApplication::postEvent( m_cppSupport, new FileParsedEvent(fileName, unit->problems) ); 00289 00290 m_currentFile = QString::null; 00291 00292 if( m_fileList->isEmpty() ) 00293 m_isEmpty.wakeAll(); 00294 00295 return unit; 00296 } 00297 00298 Unit* BackgroundParser::findUnit( const QString& fileName ) 00299 { 00300 QMap<QString, Unit*>::Iterator it = m_unitDict.find( fileName ); 00301 return it != m_unitDict.end() ? *it : 0; 00302 } 00303 00304 TranslationUnitAST* BackgroundParser::translationUnit( const QString& fileName ) 00305 { 00306 Unit* u = 0; 00307 if( (u = findUnit(fileName)) == 0 ){ 00308 m_fileList->remove( fileName ); 00309 u = parseFile( fileName, false ); 00310 } 00311 00312 return u->translationUnit; 00313 } 00314 00315 QValueList<Problem> BackgroundParser::problems( const QString& fileName ) 00316 { 00317 Unit* u = 0; 00318 if( (u = findUnit(fileName)) == 0 ){ 00319 m_fileList->remove( fileName ); 00320 u = parseFile( fileName, false ); 00321 } 00322 00323 return u ? u->problems : QValueList<Problem>(); 00324 } 00325 00326 void BackgroundParser::close() 00327 { 00328 QMutexLocker locker( &m_mutex ); 00329 m_close = true; 00330 m_canParse.wakeAll(); 00331 } 00332 00333 bool BackgroundParser::filesInQueue() 00334 { 00335 QMutexLocker locker( &m_mutex ); 00336 00337 return m_fileList->count() || !m_currentFile.isEmpty(); 00338 } 00339 00340 void BackgroundParser::updateParserConfiguration() 00341 { 00342 QMutexLocker locker( &m_mutex ); 00343 00344 QString conf_file_name = m_cppSupport->specialHeaderName(); 00345 m_driver->removeAllMacrosInFile( conf_file_name ); 00346 m_driver->parseFile( conf_file_name, true ); 00347 } 00348 00349 void BackgroundParser::run() 00350 { 00351 // (void) m_cppSupport->codeCompletion()->repository()->getEntriesInScope( QStringList(), false ); 00352 00353 while( !m_close ){ 00354 00355 while( m_fileList->isEmpty() ){ 00356 m_canParse.wait(); 00357 00358 if( m_close ) 00359 break; 00360 } 00361 00362 if( m_close ) 00363 break; 00364 00365 QPair<QString, bool> entry = m_fileList->front(); 00366 QString fileName = entry.first; 00367 bool readFromDisk = entry.second; 00368 m_currentFile = fileName; 00369 00370 (void) parseFile( fileName, readFromDisk, true ); 00371 m_fileList->pop_front(); 00372 00373 m_currentFile = QString::null; 00374 } 00375 00376 kdDebug(9007) << "!!!!!!!!!!!!!!!!!! BG PARSER DESTROYED !!!!!!!!!!!!" << endl; 00377 00378 QThread::exit(); 00379 }
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:41 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003