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
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
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 );
00263
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
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 }