00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "backgroundparser.h"
00013
#include "javasupportpart.h"
00014
#include "javasupport_events.h"
00015
#include "driver.h"
00016
#include "kdevdeepcopy.h"
00017
#include "kdevdriver.h"
00018
00019
#if QT_VERSION < 0x030100
00020
#include <kdevmutex.h>
00021
#else
00022
#include <qmutex.h>
00023
#endif
00024
00025
#include <kparts/part.h>
00026
#include <ktexteditor/editinterface.h>
00027
#include <ktexteditor/document.h>
00028
#include <ktexteditor/view.h>
00029
00030
#include <kdevpartcontroller.h>
00031
#include <kdevproject.h>
00032
00033
#include <kurl.h>
00034
#include <kdebug.h>
00035
#include <kapplication.h>
00036
00037
#include <qfile.h>
00038
#include <qfileinfo.h>
00039
#include <qtextstream.h>
00040
#include <qprocess.h>
00041
00042
class KDevSourceProvider:
public SourceProvider
00043 {
00044
public:
00045 KDevSourceProvider(
JavaSupportPart* javaSupport )
00046 :
m_javaSupport( javaSupport ),
00047
m_readFromDisk( false ) {}
00048
00049 void setReadFromDisk(
bool b ) {
m_readFromDisk = b; }
00050 bool readFromDisk()
const {
return m_readFromDisk; }
00051
00052 virtual QString contents(
const QString& fileName )
00053 {
00054
if( !
m_readFromDisk ){
00055
00056
bool needToLock = kapp->locked() ==
false;
00057
00058
if( needToLock )
00059 kapp->lock();
00060
00061
00062
00063
QPtrList<KParts::Part> parts( *
m_javaSupport->
partController()->
parts() );
00064
QPtrListIterator<KParts::Part> it( parts );
00065
while( it.current() ){
00066
KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>( it.current() );
00067 ++it;
00068
00069
KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>( doc );
00070
if( !doc || !editIface || doc->
url().
path() != fileName )
00071
continue;
00072
00073
QString contents =
QString( editIface->
text().ascii() );
00074
00075
if( needToLock )
00076 kapp->unlock();
00077
00078
00079
00080
return contents;
00081 }
00082
00083
if( needToLock )
00084 kapp->unlock();
00085
00086 }
00087
00088
QFile f( fileName );
00089
QTextStream stream( &f );
00090
if( f.open(IO_ReadOnly) ){
00091
QString contents = stream.read();
00092 f.close();
00093
return contents;
00094 }
00095
00096
return QString::null;
00097 }
00098
00099 virtual bool isModified(
const QString& fileName )
00100 {
00101 Q_UNUSED( fileName );
00102
return true;
00103 }
00104
00105
private:
00106 JavaSupportPart*
m_javaSupport;
00107 bool m_readFromDisk;
00108
private:
00109
KDevSourceProvider(
const KDevSourceProvider& source );
00110
void operator = (
const KDevSourceProvider& source );
00111 };
00112
00113
class SynchronizedFileList
00114 {
00115
public:
00116 SynchronizedFileList() {}
00117
00118 bool isEmpty()
const
00119
{
00120
QMutexLocker locker( &
m_mutex );
00121
return m_fileList.isEmpty();
00122 }
00123
00124 uint
count()
const
00125
{
00126
QMutexLocker locker( &
m_mutex );
00127
return m_fileList.count();
00128 }
00129
00130 QPair<QString, bool> front()
const
00131
{
00132
QMutexLocker locker( &
m_mutex );
00133
return m_fileList.front();
00134 }
00135
00136 void clear()
00137 {
00138
QMutexLocker locker( &
m_mutex );
00139
m_fileList.clear();
00140 }
00141
00142 void push_back(
const QString& fileName,
bool readFromDisk=
false )
00143 {
00144
QMutexLocker locker( &
m_mutex );
00145
m_fileList.append( qMakePair(fileName, readFromDisk) );
00146 }
00147
00148 void pop_front()
00149 {
00150
QMutexLocker locker( &
m_mutex );
00151
m_fileList.pop_front();
00152 }
00153
00154 bool contains(
const QString& fileName )
const
00155
{
00156
QMutexLocker locker( &
m_mutex );
00157
QValueList< QPair<QString, bool> >::ConstIterator it =
m_fileList.begin();
00158
while( it !=
m_fileList.end() ){
00159
if( (*it).first == fileName )
00160
return true;
00161 ++it;
00162 }
00163
return false;
00164 }
00165
00166 void remove(
const QString& fileName )
00167 {
00168
QMutexLocker locker( &
m_mutex );
00169
QValueList< QPair<QString, bool> >::Iterator it =
m_fileList.begin();
00170
while( it !=
m_fileList.end() ){
00171
if( (*it).first == fileName )
00172
m_fileList.remove( it );
00173 ++it;
00174 }
00175 }
00176
00177
private:
00178 mutable QMutex m_mutex;
00179 QValueList< QPair<QString, bool> >
m_fileList;
00180 };
00181
00182 BackgroundParser::BackgroundParser(
JavaSupportPart* part,
QWaitCondition* consumed )
00183 : m_consumed( consumed ), m_javaSupport( part ), m_close( false )
00184 {
00185
m_fileList =
new SynchronizedFileList();
00186
m_driver =
new KDevDriver(
m_javaSupport );
00187
m_driver->
setSourceProvider(
new KDevSourceProvider(
m_javaSupport) );
00188
00189 }
00190
00191
BackgroundParser::~BackgroundParser()
00192 {
00193
removeAllFiles();
00194
00195
delete( m_driver );
00196 m_driver = 0;
00197
00198
delete m_fileList;
00199 m_fileList = 0;
00200 }
00201
00202
void BackgroundParser::addFile(
const QString& fileName,
bool readFromDisk )
00203 {
00204
QString fn =
deepCopy( fileName );
00205
00206
bool added =
false;
00207
if( !
m_fileList->
contains(fn) ){
00208
m_fileList->
push_back( fn, readFromDisk );
00209 added =
true;
00210 }
00211
00212
if( added )
00213
m_canParse.wakeAll();
00214 }
00215
00216
void BackgroundParser::removeAllFiles()
00217 {
00218
kdDebug(9013) <<
"BackgroundParser::removeAllFiles()" <<
endl;
00219
QMutexLocker locker( &m_mutex );
00220
00221
QMap<QString, Unit*>::Iterator it =
m_unitDict.begin();
00222
while( it !=
m_unitDict.end() ){
00223
Unit* unit = it.data();
00224 ++it;
00225
delete( unit );
00226 unit = 0;
00227 }
00228
m_unitDict.clear();
00229
m_driver->
reset();
00230
m_fileList->
clear();
00231
00232
m_isEmpty.wakeAll();
00233 }
00234
00235
void BackgroundParser::removeFile(
const QString& fileName )
00236 {
00237
QMutexLocker locker( &m_mutex );
00238
00239
if(
Unit* unit =
findUnit(fileName) ){
00240
m_driver->
remove( fileName );
00241
m_unitDict.remove( fileName );
00242
delete( unit );
00243 unit = 0;
00244 }
00245
00246
if(
m_fileList->
isEmpty() )
00247
m_isEmpty.wakeAll();
00248 }
00249
00250 Unit*
BackgroundParser::parseFile(
const QString& fileName,
bool readFromDisk )
00251 {
00252 static_cast<KDevSourceProvider*>(
m_driver->
sourceProvider() )->setReadFromDisk( readFromDisk );
00253
00254
m_driver->
remove( fileName );
00255
m_driver->
parseFile( fileName );
00256
RefJavaAST translationUnit =
m_driver->
takeTranslationUnit( fileName );
00257
00258
Unit* unit =
new Unit;
00259 unit->
fileName = fileName;
00260 unit->
translationUnit = translationUnit;
00261 unit->
problems =
m_driver->
problems( fileName );
00262
00263 static_cast<KDevSourceProvider*>(
m_driver->
sourceProvider() )->setReadFromDisk(
false );
00264
00265
if(
m_unitDict.find(fileName) !=
m_unitDict.end() ){
00266 Unit* u =
m_unitDict[ fileName ];
00267 m_unitDict.remove( fileName );
00268
delete( u );
00269 u = 0;
00270 }
00271
00272
m_unitDict.insert( fileName, unit );
00273
00274
if(
m_fileList->
contains(fileName) ){
00275
kdDebug(9013) <<
"========================> FILE: " << fileName <<
" IN QUEUE <=============" <<
endl;
00276 }
else {
00277 KApplication::postEvent(
m_javaSupport,
new FileParsedEvent(fileName, unit->
problems) );
00278 }
00279
00280
m_currentFile = QString::null;
00281
00282
if(
m_fileList->
isEmpty() )
00283
m_isEmpty.wakeAll();
00284
00285
return unit;
00286 }
00287
00288
Unit* BackgroundParser::findUnit(
const QString& fileName )
00289 {
00290
QMap<QString, Unit*>::Iterator it = m_unitDict.find( fileName );
00291
return it != m_unitDict.end() ? *it : 0;
00292 }
00293
00294
RefJavaAST BackgroundParser::translationUnit(
const QString& fileName )
00295 {
00296
Unit* u = 0;
00297
if( (u =
findUnit(fileName)) == 0 ){
00298
m_fileList->
remove( fileName );
00299 u =
parseFile( fileName,
false );
00300 }
00301
00302
return u->
translationUnit;
00303 }
00304
00305
QValueList<Problem> BackgroundParser::problems(
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 ? u->
problems :
QValueList<Problem>();
00314 }
00315
00316
void BackgroundParser::close()
00317 {
00318
QMutexLocker locker( &m_mutex );
00319
m_close =
true;
00320
m_canParse.wakeAll();
00321 }
00322
00323
bool BackgroundParser::filesInQueue()
00324 {
00325
QMutexLocker locker( &m_mutex );
00326
00327
return m_fileList->
count() || !
m_currentFile.isEmpty();
00328 }
00329
00330
void BackgroundParser::run()
00331 {
00332
00333
00334
while( !
m_close ){
00335
00336
m_mutex.lock();
00337
while(
m_fileList->
isEmpty() ){
00338
m_canParse.wait( &m_mutex );
00339
00340
if(
m_close ){
00341
break;
00342 }
00343 }
00344
00345
if(
m_close ){
00346
m_mutex.unlock();
00347
break;
00348 }
00349
00350
QPair<QString, bool> entry =
m_fileList->
front();
00351
QString fileName = entry.first;
00352
bool readFromDisk = entry.second;
00353
m_currentFile = fileName;
00354
m_fileList->
pop_front();
00355
00356 (
void)
parseFile( fileName, readFromDisk );
00357
m_mutex.unlock();
00358 }
00359
00360
kdDebug(9013) <<
"!!!!!!!!!!!!!!!!!! BG PARSER DESTROYED !!!!!!!!!!!!" <<
endl;
00361
00362 QThread::exit();
00363 }