backgroundparser.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
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
00062 kapp->lock();
00063
00064
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() );
00077
00078
00079
00080 break;
00081 }
00082
00083
00084 kapp->unlock();
00085
00086 }
00087 else
00088 {
00089 QFile f( fileName );
00090 if( f.open(IO_ReadOnly) ){
00091 QTextStream stream( &f );
00092 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
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
00259 static_cast<KDevSourceProvider*>( m_driver->sourceProvider() )->setReadFromDisk( readFromDisk );
00260
00261 m_driver->remove( fileName );
00262 m_driver->parseFile( fileName , false, true );
00263 m_driver->removeAllMacrosInFile( fileName );
00264
00265 TranslationUnitAST::Node translationUnit = m_driver->takeTranslationUnit( fileName );
00266
00267 Unit* unit = new Unit;
00268 unit->fileName = fileName;
00269 unit->translationUnit = translationUnit.release();
00270 unit->problems = m_driver->problems( fileName );
00271
00272 static_cast<KDevSourceProvider*>( m_driver->sourceProvider() )->setReadFromDisk( false );
00273
00274 if( lock )
00275 m_mutex.lock();
00276
00277 if( m_unitDict.find(fileName) != m_unitDict.end() ){
00278 Unit* u = m_unitDict[ fileName ];
00279 m_unitDict.remove( fileName );
00280 delete( u );
00281 u = 0;
00282 }
00283
00284 m_unitDict.insert( fileName, unit );
00285
00286 if( lock )
00287 m_mutex.unlock();
00288
00289 KApplication::postEvent( m_cppSupport, new FileParsedEvent(fileName, unit->problems) );
00290
00291 m_currentFile = QString::null;
00292
00293 if( m_fileList->isEmpty() )
00294 m_isEmpty.wakeAll();
00295
00296 return unit;
00297 }
00298
00299 Unit* BackgroundParser::findUnit( const QString& fileName )
00300 {
00301 QMap<QString, Unit*>::Iterator it = m_unitDict.find( fileName );
00302 return it != m_unitDict.end() ? *it : 0;
00303 }
00304
00305 TranslationUnitAST* BackgroundParser::translationUnit( const QString& fileName )
00306 {
00307 Unit* u = 0;
00308 if( (u = findUnit(fileName)) == 0 ){
00309 m_fileList->remove( fileName );
00310 u = parseFile( fileName, false );
00311 }
00312
00313 return u->translationUnit;
00314 }
00315
00316 QValueList<Problem> BackgroundParser::problems( const QString& fileName, bool readFromDisk, bool forceParse )
00317 {
00318 Unit* u = 0;
00319 if( (u = findUnit(fileName)) == 0 || forceParse ){
00320 m_fileList->remove( fileName );
00321 u = parseFile( fileName, readFromDisk );
00322 }
00323
00324 return u ? u->problems : QValueList<Problem>();
00325 }
00326
00327 void BackgroundParser::close()
00328 {
00329 QMutexLocker locker( &m_mutex );
00330 m_close = true;
00331 m_canParse.wakeAll();
00332
00333 while (running())
00334 sleep(1);
00335 }
00336
00337 bool BackgroundParser::filesInQueue()
00338 {
00339 QMutexLocker locker( &m_mutex );
00340
00341 return m_fileList->count() || !m_currentFile.isEmpty();
00342 }
00343
00344 void BackgroundParser::updateParserConfiguration()
00345 {
00346 QMutexLocker locker( &m_mutex );
00347
00348 QString conf_file_name = m_cppSupport->specialHeaderName();
00349 m_driver->removeAllMacrosInFile( conf_file_name );
00350 m_driver->parseFile( conf_file_name, true );
00351 }
00352
00353 void BackgroundParser::run()
00354 {
00355
00356
00357 while( !m_close ){
00358
00359 while( m_fileList->isEmpty() ){
00360 m_canParse.wait();
00361
00362 if( m_close )
00363 break;
00364 }
00365
00366 if( m_close )
00367 break;
00368
00369 QPair<QString, bool> entry = m_fileList->front();
00370 QString fileName = entry.first;
00371 bool readFromDisk = entry.second;
00372 m_currentFile = fileName;
00373
00374 (void) parseFile( fileName, readFromDisk, true );
00375 m_fileList->pop_front();
00376
00377 m_currentFile = QString::null;
00378 }
00379
00380 kdDebug(9007) << "!!!!!!!!!!!!!!!!!! BG PARSER DESTROYED !!!!!!!!!!!!" << endl;
00381
00382 QThread::exit();
00383 }
This file is part of the documentation for KDevelop Version 3.1.2.