00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
#include <fstream>
00011
00012
#include <qdir.h>
00013
#include <qtimer.h>
00014
#include <qwhatsthis.h>
00015
00016
#include <kiconloader.h>
00017
#include <klocale.h>
00018
#include <kdevgenericfactory.h>
00019
#include <kdebug.h>
00020
#include <kapplication.h>
00021
#include <kstatusbar.h>
00022
00023
#include <antlr/ASTFactory.hpp>
00024
00025
#include "catalog.h"
00026
#include <kdevcore.h>
00027
#include <kdevmainwindow.h>
00028
#include <kdevpartcontroller.h>
00029
#include <kdevproject.h>
00030
00031
#include "pascalsupport_part.h"
00032
#include "problemreporter.h"
00033
#include "PascalLexer.hpp"
00034
#include "PascalParser.hpp"
00035
#include "PascalStoreWalker.hpp"
00036
00037 struct PascalSupportPartData{
00038 ProblemReporter*
problemReporter;
00039
00040 PascalSupportPartData()
00041 :
problemReporter( 0 )
00042 {}
00043 };
00044
00045 typedef KDevGenericFactory<PascalSupportPart> PascalSupportFactory;
00046
static const KAboutData data(
"kdevpascalsupport",
I18N_NOOP(
"Language"),
"1.0");
00047 K_EXPORT_COMPONENT_FACTORY( libkdevpascalsupport,
PascalSupportFactory( &data ) )
00048
00049
PascalSupportPart::
PascalSupportPart(
QObject *parent, const
char *name, const
QStringList &)
00050 :
KDevLanguageSupport("PascalSupport", "pascal", parent, name ? name : "KDevPascalSupport" ),
00051 d( new
PascalSupportPartData() )
00052 {
00053 setInstance(PascalSupportFactory::instance());
00054 setXMLFile(
"kdevpascalsupport.rc");
00055
00056 d->problemReporter =
new ProblemReporter(
this );
00057 connect( core(), SIGNAL(configWidget(
KDialogBase*)),
00058 d->problemReporter, SLOT(configWidget(
KDialogBase*)) );
00059
00060 connect( core(), SIGNAL(projectOpened()),
this, SLOT(projectOpened()) );
00061 connect( core(), SIGNAL(projectClosed()),
this, SLOT(projectClosed()) );
00062 connect( partController(), SIGNAL(savedFile(
const QString&)),
00063
this, SLOT(savedFile(
const QString&)) );
00064 connect( core(), SIGNAL(contextMenu(
QPopupMenu *,
const Context *)),
00065
this, SLOT(contextMenu(
QPopupMenu *,
const Context *)) );
00066 connect( core(), SIGNAL(configWidget(
KDialogBase*)),
00067
this, SLOT(configWidget(
KDialogBase*)) );
00068 connect( core( ), SIGNAL( projectConfigWidget(
KDialogBase* ) ),
this,
00069 SLOT( projectConfigWidget(
KDialogBase* ) ) );
00070
00071 mainWindow()->embedOutputView( d->problemReporter, i18n(
"Problems"), i18n(
"problem reporter") );
00072 QWhatsThis::add(d->problemReporter, i18n(
"<b>Problem reporter</b><p>This window shows various \"problems\" in your project. "
00073
"It displays errors reported by a language parser."));
00074 }
00075
00076 PascalSupportPart::~PascalSupportPart()
00077 {
00078
mainWindow()->
removeView(
d->
problemReporter );
00079
delete(
d->
problemReporter );
00080
00081
delete(
d );
00082 }
00083
00084 PascalSupportPart::Features
PascalSupportPart::features()
00085 {
00086
return Features(Classes | Structs | Functions | Variables | Declarations);
00087 }
00088
00089 void PascalSupportPart::projectOpened()
00090 {
00091 connect(
project(), SIGNAL(
addedFilesToProject(
const QStringList &)),
00092
this, SLOT(
addedFilesToProject(
const QStringList &)));
00093 connect(
project(), SIGNAL(
removedFilesFromProject(
const QStringList &)),
00094
this, SLOT(
removedFilesFromProject(
const QStringList &)));
00095 connect(
project(), SIGNAL(projectCompiled()),
00096
this, SLOT(
slotProjectCompiled()) );
00097
00098 QDir::setCurrent(
project()->projectDirectory());
00099
m_projectFileList =
project()->
allFiles();
00100
m_projectClosed =
false;
00101
00102 QTimer::singleShot(0,
this, SLOT(
initialParse()));
00103 }
00104
00105 void PascalSupportPart::projectClosed()
00106 {
00107
m_projectClosed =
true;
00108 }
00109
00110 void PascalSupportPart::configWidget(
KDialogBase *dlg)
00111 {
00112 Q_UNUSED( dlg );
00113
return;
00114 }
00115
00116 void PascalSupportPart::projectConfigWidget(
KDialogBase *dlg)
00117 {
00118 Q_UNUSED( dlg );
00119
return;
00120 }
00121
00122 void PascalSupportPart::contextMenu(
QPopupMenu *popup,
const Context *context)
00123 {
00124 Q_UNUSED( popup );
00125 Q_UNUSED( context );
00126
return;
00127 }
00128
00129 void PascalSupportPart::savedFile(
const QString &fileName)
00130 {
00131
maybeParse(fileName);
00132 emit
updatedSourceInfo();
00133 }
00134
00135 void PascalSupportPart::addedFilesToProject(
const QStringList &fileList)
00136 {
00137
for (QStringList::ConstIterator it = fileList.begin(); it != fileList.end() ;++it)
00138 {
00139
QString fn =
project()->
projectDirectory() +
"/" + *it;
00140
maybeParse( fn );
00141 kapp->processEvents( 500 );
00142 emit addedSourceInfo(fn);
00143 }
00144 }
00145
00146 void PascalSupportPart::removedFilesFromProject(
const QStringList &fileList)
00147 {
00148
for (QStringList::ConstIterator it = fileList.begin(); it != fileList.end() ;++it)
00149 {
00150
QString fn =
project()->
projectDirectory() +
"/" + *it;
00151
00152 emit aboutToRemoveSourceInfo(fn);
00153
codeModel()->
removeFile(
codeModel()->fileByName(fn) );
00154 }
00155 }
00156
00157 void PascalSupportPart::slotProjectCompiled()
00158 {
00159
return;
00160 }
00161
00162 void PascalSupportPart::initialParse( )
00163 {
00164
kdDebug(9013) <<
"------------------------------------------> initialParse()" <<
endl;
00165
00166
if (
project())
00167 {
00168 kapp->setOverrideCursor(waitCursor);
00169
00171
00172
QStringList files =
project()->
allFiles();
00173
for (QStringList::Iterator it = files.begin(); it != files.end() ;++it){
00174
QString fn =
project()->
projectDirectory() +
"/" + *it;
00175
maybeParse( fn );
00176 kapp->processEvents( 500 );
00177 }
00178
00179 emit
updatedSourceInfo();
00180
00181 kapp->restoreOverrideCursor();
00182
mainWindow()->
statusBar()->message( i18n(
"Found 1 problem",
"Found %n problems",
d->
problemReporter->childCount()) );
00183 }
00184 }
00185
00186 void PascalSupportPart::maybeParse(
const QString & fileName )
00187 {
00188
kdDebug(9013) <<
"Maybe parse: " << fileName <<
endl;
00189
00190
KMimeType::Ptr mime = KMimeType::findByURL( fileName );
00191
if( !mime || mime->name() !=
"text/x-pascal" )
00192
return;
00193
00194
mainWindow()->
statusBar()->message( i18n(
"Parsing file: %1").arg(fileName) );
00195
parse( fileName );
00196 }
00197
00198 void PascalSupportPart::parse(
const QString & fileName )
00199 {
00200
kdDebug(9013) <<
"PascalSupportPart::parse() -- " << fileName <<
endl;
00201
00202 std::ifstream stream( QFile::encodeName( fileName ).
data() );
00203
QCString _fn = fileName.utf8();
00204 std::string fn( _fn.data() );
00205
00206
PascalLexer lexer( stream );
00207 lexer.setFilename( fn );
00208 lexer.
setProblemReporter(
d->
problemReporter );
00209
00210
PascalParser parser( lexer );
00211 parser.setFilename( fn );
00212 parser.
setProblemReporter(
d->
problemReporter );
00213
00214
try{
00215 antlr::ASTFactory my_factory(
"PascalAST", PascalAST::factory );
00216 parser.
initializeASTFactory(my_factory);
00217 parser.setASTFactory( &my_factory );
00218
00219 lexer.
resetErrors();
00220 parser.
resetErrors();
00221
00222 parser.
compilationUnit();
00223
int errors = lexer.
numberOfErrors() + parser.
numberOfErrors();
00224
RefPascalAST ast = parser.
getAST();
00225
00226
if( errors == 0 && ast != antlr::nullAST ){
00227
kdDebug(9013) <<
"-------------------> start StoreWalker" <<
endl;
00228
00229
00230
00231
00232 }
00233
00234 }
catch( antlr::ANTLRException& ex ){
00235
kdDebug() <<
"*exception*: " << ex.toString().c_str() <<
endl;
00236
d->
problemReporter->
reportError( ex.getMessage().c_str(),
00237 fileName,
00238 lexer.getLine(),
00239 lexer.getColumn() );
00240 }
00241 }
00242
00243 KMimeType::List PascalSupportPart::mimeTypes( )
00244 {
00245
KMimeType::List list;
00246
KMimeType::Ptr mime = KMimeType::mimeType(
"text/x-pascal" );
00247
if( mime )
00248 list << mime;
00249
return list;
00250 }
00251
00252 QString PascalSupportPart::formatTag(
const Tag & inputTag )
00253 {
00254
Tag tag = inputTag;
00255
00256
switch( tag.
kind() )
00257 {
00258
case Tag::Kind_Namespace:
00259
return QString::fromLatin1(
"unit ") + tag.
name();
00260
00261
case Tag::Kind_Class:
00262
return QString::fromLatin1(
"class ") + tag.
name();
00263
00264
case Tag::Kind_Function:
00265
case Tag::Kind_FunctionDeclaration:
00266 {
00267
return tag.
name() +
"()";
00268 }
00269
break;
00270
00271
case Tag::Kind_Variable:
00272
case Tag::Kind_VariableDeclaration:
00273 {
00274
return QString::fromLatin1(
"var ") + tag.
name();
00275 }
00276
break;
00277 }
00278
return tag.
name();
00279 }
00280
00281 QString PascalSupportPart::formatModelItem(
const CodeModelItem * item,
bool shortDescription )
00282 {
00283
if (item->
isFunction() || item->
isFunctionDefinition() )
00284 {
00285
const FunctionModel *model = static_cast<const FunctionModel*>(item);
00286
QString function;
00287
QString args;
00288
ArgumentList argumentList = model->
argumentList();
00289
for (ArgumentList::const_iterator it = argumentList.begin(); it != argumentList.end(); ++it)
00290 {
00291 args.isEmpty() ? args +=
"" : args +=
", " ;
00292 args +=
formatModelItem((*it).data());
00293 }
00294
00295 function += model->
name() +
"(" + args +
")";
00296
00297
if( !shortDescription )
00298 function += (model->
isVirtual() ?
QString(
"virtual; ") :
QString(
"") ) + model->
resultType() +
" ";
00299
00300
return function;
00301 }
00302
else if (item->
isVariable())
00303 {
00304
const VariableModel *model = static_cast<const VariableModel*>(item);
00305
if( shortDescription )
00306
return model->
name();
00307
return model->
name() +
": " + model->
type();
00308 }
00309
else if (item->
isArgument())
00310 {
00311
const ArgumentModel *model = static_cast<const ArgumentModel*>(item);
00312
QString arg;
00313 arg += model->
name();
00314 arg +=
": " + model->
type();
00315
if( !shortDescription )
00316 arg += model->
defaultValue().isEmpty() ?
QString(
"") :
QString(
" = ") + model->
defaultValue();
00317
return arg.stripWhiteSpace();
00318 }
00319
else
00320
return KDevLanguageSupport::formatModelItem( item, shortDescription );
00321 }
00322
00323
#include "pascalsupport_part.moc"