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 KURL&)),
00063 this, SLOT(savedFile(const KURL&)) );
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 KURL &fileName)
00130 {
00131 maybeParse(fileName.path());
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( KURL( 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"