KDevelop API Documentation

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           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     //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 
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 );  // romove all macros defined by this
00264                           // translation unit.
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     // (void) m_cppSupport->codeCompletion()->repository()->getEntriesInScope( QStringList(), false );
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 }
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:45 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003