|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2003 Alexander Dymo *
|
|
|
|
* cloudtemple@mksat.net *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqwhatsthis.h>
|
|
|
|
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kdevgenericfactory.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <kstatusbar.h>
|
|
|
|
|
|
|
|
#include <antlr/ASTFactory.h>
|
|
|
|
|
|
|
|
#include "catalog.h"
|
|
|
|
#include <kdevcore.h>
|
|
|
|
#include <kdevmainwindow.h>
|
|
|
|
#include <kdevpartcontroller.h>
|
|
|
|
#include <kdevproject.h>
|
|
|
|
#include <kdevplugininfo.h>
|
|
|
|
|
|
|
|
#include "pascalsupport_part.h"
|
|
|
|
#include "problemreporter.h"
|
|
|
|
#include "PascalLexer.h"
|
|
|
|
#include "PascalParser.h"
|
|
|
|
#include "PascalStoreWalker.h"
|
|
|
|
|
|
|
|
struct PascalSupportPartData{
|
|
|
|
ProblemReporter* problemReporter;
|
|
|
|
|
|
|
|
PascalSupportPartData()
|
|
|
|
: problemReporter( 0 )
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef KDevGenericFactory<PascalSupportPart> PascalSupportFactory;
|
|
|
|
static const KDevPluginInfo data("kdevpascalsupport");
|
|
|
|
K_EXPORT_COMPONENT_FACTORY( libkdevpascalsupport, PascalSupportFactory( data ) )
|
|
|
|
|
|
|
|
PascalSupportPart::PascalSupportPart(TQObject *parent, const char *name, const TQStringList &)
|
|
|
|
: KDevLanguageSupport(&data, parent, name ? name : "KDevPascalSupport" ),
|
|
|
|
d( new PascalSupportPartData() )
|
|
|
|
{
|
|
|
|
setInstance(PascalSupportFactory::instance());
|
|
|
|
setXMLFile("kdevpascalsupport.rc");
|
|
|
|
|
|
|
|
d->problemReporter = new ProblemReporter( this );
|
|
|
|
connect( core(), TQT_SIGNAL(configWidget(KDialogBase*)),
|
|
|
|
d->problemReporter, TQT_SLOT(configWidget(KDialogBase*)) );
|
|
|
|
|
|
|
|
connect( core(), TQT_SIGNAL(projectOpened()), this, TQT_SLOT(projectOpened()) );
|
|
|
|
connect( core(), TQT_SIGNAL(projectClosed()), this, TQT_SLOT(projectClosed()) );
|
|
|
|
connect( partController(), TQT_SIGNAL(savedFile(const KURL&)),
|
|
|
|
this, TQT_SLOT(savedFile(const KURL&)) );
|
|
|
|
connect( core(), TQT_SIGNAL(contextMenu(TQPopupMenu *, const Context *)),
|
|
|
|
this, TQT_SLOT(contextMenu(TQPopupMenu *, const Context *)) );
|
|
|
|
connect( core(), TQT_SIGNAL(configWidget(KDialogBase*)),
|
|
|
|
this, TQT_SLOT(configWidget(KDialogBase*)) );
|
|
|
|
connect( core( ), TQT_SIGNAL( projectConfigWidget( KDialogBase* ) ), this,
|
|
|
|
TQT_SLOT( projectConfigWidget( KDialogBase* ) ) );
|
|
|
|
|
|
|
|
mainWindow()->embedOutputView( d->problemReporter, i18n("Problems"), i18n("problem reporter") );
|
|
|
|
TQWhatsThis::add(d->problemReporter, i18n("<b>Problem reporter</b><p>This window shows various \"problems\" in your project. "
|
|
|
|
"It displays errors reported by a language parser."));
|
|
|
|
}
|
|
|
|
|
|
|
|
PascalSupportPart::~PascalSupportPart()
|
|
|
|
{
|
|
|
|
mainWindow()->removeView( d->problemReporter );
|
|
|
|
delete( d->problemReporter );
|
|
|
|
|
|
|
|
delete( d );
|
|
|
|
}
|
|
|
|
|
|
|
|
PascalSupportPart::Features PascalSupportPart::features()
|
|
|
|
{
|
|
|
|
return Features(Classes | Structs | Functions | Variables | Declarations);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::projectOpened()
|
|
|
|
{
|
|
|
|
connect(project(), TQT_SIGNAL(addedFilesToProject(const TQStringList &)),
|
|
|
|
this, TQT_SLOT(addedFilesToProject(const TQStringList &)));
|
|
|
|
connect(project(), TQT_SIGNAL(removedFilesFromProject(const TQStringList &)),
|
|
|
|
this, TQT_SLOT(removedFilesFromProject(const TQStringList &)));
|
|
|
|
connect(project(), TQT_SIGNAL(projectCompiled()),
|
|
|
|
this, TQT_SLOT(slotProjectCompiled()) );
|
|
|
|
|
|
|
|
m_projectFileList = project()->allFiles();
|
|
|
|
m_projectClosed = false;
|
|
|
|
|
|
|
|
TQTimer::singleShot(0, this, TQT_SLOT(initialParse()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::projectClosed()
|
|
|
|
{
|
|
|
|
m_projectClosed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::configWidget(KDialogBase *dlg)
|
|
|
|
{
|
|
|
|
Q_UNUSED( dlg );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::projectConfigWidget(KDialogBase *dlg)
|
|
|
|
{
|
|
|
|
Q_UNUSED( dlg );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::contextMenu(TQPopupMenu *popup, const Context *context)
|
|
|
|
{
|
|
|
|
Q_UNUSED( popup );
|
|
|
|
Q_UNUSED( context );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::savedFile(const KURL &fileName)
|
|
|
|
{
|
|
|
|
maybeParse(fileName.path());
|
|
|
|
emit updatedSourceInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::addedFilesToProject(const TQStringList &fileList)
|
|
|
|
{
|
|
|
|
for (TQStringList::ConstIterator it = fileList.begin(); it != fileList.end() ;++it)
|
|
|
|
{
|
|
|
|
TQString fn = project()->projectDirectory() + "/" + *it;
|
|
|
|
maybeParse( fn );
|
|
|
|
kapp->processEvents( 500 );
|
|
|
|
emit addedSourceInfo(fn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::removedFilesFromProject(const TQStringList &fileList)
|
|
|
|
{
|
|
|
|
for (TQStringList::ConstIterator it = fileList.begin(); it != fileList.end() ;++it)
|
|
|
|
{
|
|
|
|
TQString fn = project()->projectDirectory() + "/" + *it;
|
|
|
|
|
|
|
|
emit aboutToRemoveSourceInfo(fn);
|
|
|
|
codeModel()->removeFile( codeModel()->fileByName(fn) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::slotProjectCompiled()
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::initialParse( )
|
|
|
|
{
|
|
|
|
kdDebug(9013) << "------------------------------------------> initialParse()" << endl;
|
|
|
|
|
|
|
|
if (project())
|
|
|
|
{
|
|
|
|
kapp->setOverrideCursor(waitCursor);
|
|
|
|
|
|
|
|
/// @todo Progress indicator!
|
|
|
|
|
|
|
|
TQStringList files = project()->allFiles();
|
|
|
|
for (TQStringList::Iterator it = files.begin(); it != files.end() ;++it){
|
|
|
|
TQString fn = project()->projectDirectory() + "/" + *it;
|
|
|
|
maybeParse( fn );
|
|
|
|
kapp->processEvents( 500 );
|
|
|
|
}
|
|
|
|
|
|
|
|
emit updatedSourceInfo();
|
|
|
|
|
|
|
|
kapp->restoreOverrideCursor();
|
|
|
|
mainWindow()->statusBar()->message( i18n("Found 1 problem", "Found %n problems", d->problemReporter->childCount()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::maybeParse( const TQString & fileName )
|
|
|
|
{
|
|
|
|
kdDebug(9013) << "Maybe parse: " << fileName << endl;
|
|
|
|
|
|
|
|
KMimeType::Ptr mime = KMimeType::findByURL( KURL( fileName ) );
|
|
|
|
if( !mime || mime->name() != "text/x-pascal" )
|
|
|
|
return;
|
|
|
|
|
|
|
|
mainWindow()->statusBar()->message( i18n("Parsing file: %1").arg(fileName) );
|
|
|
|
parse( fileName );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PascalSupportPart::parse( const TQString & fileName )
|
|
|
|
{
|
|
|
|
kdDebug(9013) << "PascalSupportPart::parse() -- " << fileName << endl;
|
|
|
|
|
|
|
|
std::ifstream stream( TQFile::encodeName( fileName ).data() );
|
|
|
|
TQCString _fn = fileName.utf8();
|
|
|
|
std::string fn( _fn.data() );
|
|
|
|
|
|
|
|
PascalLexer lexer( stream );
|
|
|
|
lexer.setFilename( fn );
|
|
|
|
lexer.setProblemReporter( d->problemReporter );
|
|
|
|
|
|
|
|
PascalParser parser( lexer );
|
|
|
|
parser.setFilename( fn );
|
|
|
|
parser.setProblemReporter( d->problemReporter );
|
|
|
|
|
|
|
|
try{
|
|
|
|
antlr::ASTFactory my_factory( "PascalAST", PascalAST::factory );
|
|
|
|
parser.initializeASTFactory(my_factory);
|
|
|
|
parser.setASTFactory( &my_factory );
|
|
|
|
|
|
|
|
lexer.resetErrors();
|
|
|
|
parser.resetErrors();
|
|
|
|
|
|
|
|
parser.compilationUnit();
|
|
|
|
int errors = lexer.numberOfErrors() + parser.numberOfErrors();
|
|
|
|
RefPascalAST ast = RefPascalAST( parser.getAST() );
|
|
|
|
|
|
|
|
if( errors == 0 && ast != antlr::nullAST ){
|
|
|
|
kdDebug(9013) << "-------------------> start StoreWalker" << endl;
|
|
|
|
/* PascalStoreWalker walker;
|
|
|
|
walker.setFileName( fileName );
|
|
|
|
walker.setCodeModel( codeModel() );
|
|
|
|
walker.compilationUnit( ast );*/
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch( antlr::ANTLRException& ex ){
|
|
|
|
kdDebug() << "*exception*: " << ex.toString().c_str() << endl;
|
|
|
|
d->problemReporter->reportError( ex.getMessage().c_str(),
|
|
|
|
fileName,
|
|
|
|
lexer.getLine(),
|
|
|
|
lexer.getColumn() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KMimeType::List PascalSupportPart::mimeTypes( )
|
|
|
|
{
|
|
|
|
KMimeType::List list;
|
|
|
|
KMimeType::Ptr mime = KMimeType::mimeType( "text/x-pascal" );
|
|
|
|
if( mime )
|
|
|
|
list << mime;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString PascalSupportPart::formatTag( const Tag & inputTag )
|
|
|
|
{
|
|
|
|
Tag tag = inputTag;
|
|
|
|
|
|
|
|
switch( tag.kind() )
|
|
|
|
{
|
|
|
|
case Tag::Kind_Namespace:
|
|
|
|
return TQString::fromLatin1("unit ") + tag.name();
|
|
|
|
|
|
|
|
case Tag::Kind_Class:
|
|
|
|
return TQString::fromLatin1("class ") + tag.name();
|
|
|
|
|
|
|
|
case Tag::Kind_Function:
|
|
|
|
case Tag::Kind_FunctionDeclaration:
|
|
|
|
{
|
|
|
|
return tag.name() + "()";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tag::Kind_Variable:
|
|
|
|
case Tag::Kind_VariableDeclaration:
|
|
|
|
{
|
|
|
|
return TQString::fromLatin1("var ") + tag.name();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return tag.name();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString PascalSupportPart::formatModelItem( const CodeModelItem * item, bool shortDescription )
|
|
|
|
{
|
|
|
|
if (item->isFunction() || item->isFunctionDefinition() )
|
|
|
|
{
|
|
|
|
const FunctionModel *model = static_cast<const FunctionModel*>(item);
|
|
|
|
TQString function;
|
|
|
|
TQString args;
|
|
|
|
ArgumentList argumentList = model->argumentList();
|
|
|
|
for (ArgumentList::const_iterator it = argumentList.begin(); it != argumentList.end(); ++it)
|
|
|
|
{
|
|
|
|
args.isEmpty() ? args += "" : args += ", " ;
|
|
|
|
args += formatModelItem((*it).data());
|
|
|
|
}
|
|
|
|
|
|
|
|
function += model->name() + "(" + args + ")";
|
|
|
|
|
|
|
|
if( !shortDescription )
|
|
|
|
function += (model->isVirtual() ? TQString("virtual; ") : TQString("") ) + model->resultType() + " ";
|
|
|
|
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
else if (item->isVariable())
|
|
|
|
{
|
|
|
|
const VariableModel *model = static_cast<const VariableModel*>(item);
|
|
|
|
if( shortDescription )
|
|
|
|
return model->name();
|
|
|
|
return model->name() + ": " + model->type();
|
|
|
|
}
|
|
|
|
else if (item->isArgument())
|
|
|
|
{
|
|
|
|
const ArgumentModel *model = static_cast<const ArgumentModel*>(item);
|
|
|
|
TQString arg;
|
|
|
|
arg += model->name();
|
|
|
|
arg += ": " + model->type();
|
|
|
|
if( !shortDescription )
|
|
|
|
arg += model->defaultValue().isEmpty() ? TQString("") : TQString(" = ") + model->defaultValue();
|
|
|
|
return arg.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return KDevLanguageSupport::formatModelItem( item, shortDescription );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "pascalsupport_part.moc"
|