You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
13 KiB
544 lines
13 KiB
/*
|
|
This file is part of kdepim.
|
|
|
|
Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "printer.h"
|
|
|
|
#include <kdebug.h>
|
|
#include <ksavefile.h>
|
|
|
|
#include <qfile.h>
|
|
#include <qtextstream.h>
|
|
|
|
using namespace KODE;
|
|
|
|
Printer::Printer()
|
|
: mCreationWarning( false ), mGenerator( "libkode" )
|
|
{
|
|
}
|
|
|
|
Printer::Printer( const Style &style )
|
|
: mStyle( style ), mCreationWarning( false ), mGenerator( "libkode" )
|
|
{
|
|
}
|
|
|
|
void Printer::setCreationWarning( bool v )
|
|
{
|
|
mCreationWarning = v;
|
|
}
|
|
|
|
void Printer::setGenerator( const QString &g )
|
|
{
|
|
mGenerator = g;
|
|
}
|
|
|
|
void Printer::setOutputDirectory( const QString &o )
|
|
{
|
|
mOutputDirectory = o;
|
|
}
|
|
|
|
void Printer::setSourceFile( const QString &s )
|
|
{
|
|
mSourceFile = s;
|
|
}
|
|
|
|
QString Printer::functionSignature( const Function &f,
|
|
const QString &className,
|
|
bool includeClassQualifier )
|
|
{
|
|
QString s;
|
|
|
|
if ( f.isStatic() && !includeClassQualifier ) {
|
|
s += "static ";
|
|
}
|
|
|
|
QString ret = f.returnType();
|
|
if ( !ret.isEmpty() ) {
|
|
s += ret;
|
|
if ( ret.right( 1 ) != "*" && ret.right( 1 ) != "&" ) {
|
|
s += " ";
|
|
}
|
|
}
|
|
if ( includeClassQualifier ) {
|
|
s += mStyle.className( className ) + "::";
|
|
}
|
|
if ( className == f.name() ) {
|
|
// Constructor
|
|
s += mStyle.className( f.name() );
|
|
} else {
|
|
s += f.name();
|
|
}
|
|
s += "(";
|
|
if ( !f.arguments().isEmpty() ) {
|
|
s += " " + f.arguments().join( ", " ) + " ";
|
|
}
|
|
s += ")";
|
|
if ( f.isConst() ) s += " const";
|
|
|
|
return s;
|
|
}
|
|
|
|
QString Printer::creationWarning()
|
|
{
|
|
// Create warning about generated file
|
|
QString str = "// This file is generated by " + mGenerator;
|
|
if ( !mSourceFile.isEmpty() ) {
|
|
str += " from " + mSourceFile;
|
|
}
|
|
str += ".\n";
|
|
|
|
str += "// All changes you do to this file will be lost.";
|
|
|
|
return str;
|
|
}
|
|
|
|
QString Printer::licenseHeader( const File &file )
|
|
{
|
|
Code code;
|
|
code += "/*";
|
|
code.setIndent( 4 );
|
|
|
|
code += "This file is part of " + file.project() + ".";
|
|
code.newLine();
|
|
|
|
QStringList copyrights = file.copyrightStrings();
|
|
if ( !copyrights.isEmpty() ) {
|
|
code.addBlock( copyrights.join( "\n" ) );
|
|
code.newLine();
|
|
}
|
|
|
|
code.addBlock( file.license().text() );
|
|
|
|
code.setIndent( 0 );
|
|
code += "*/";
|
|
|
|
return code.text();
|
|
}
|
|
|
|
Code Printer::functionHeaders( const Function::List &functions,
|
|
const QString &className,
|
|
int access )
|
|
{
|
|
bool needNewLine = false;
|
|
bool hasAccess = false;
|
|
|
|
Code code;
|
|
|
|
Function::List::ConstIterator it;
|
|
for( it = functions.begin(); it != functions.end(); ++it ) {
|
|
Function f = *it;
|
|
if ( f.access() == access ) {
|
|
if ( !hasAccess ) {
|
|
code += f.accessAsString() + ":";
|
|
hasAccess = true;
|
|
}
|
|
code.indent();
|
|
if ( !(*it).docs().isEmpty() ) {
|
|
code += "/**";
|
|
code.indent();
|
|
code.addFormattedText( (*it).docs() );
|
|
code.unindent();
|
|
code += "*/";
|
|
}
|
|
code += functionSignature( *it, className ) + ";";
|
|
code.unindent();
|
|
needNewLine = true;
|
|
}
|
|
}
|
|
if ( needNewLine ) code.newLine();
|
|
|
|
return code;
|
|
}
|
|
|
|
QString Printer::classHeader( const Class &c )
|
|
{
|
|
Code code;
|
|
|
|
if ( !c.docs().isEmpty() ) {
|
|
code += "/**";
|
|
code.indent();
|
|
code.addFormattedText( c.docs() );
|
|
code.unindent();
|
|
code += "*/";
|
|
}
|
|
|
|
QString txt = "class " + mStyle.className( c.name() );
|
|
|
|
Class::List baseClasses = c.baseClasses();
|
|
if ( !baseClasses.isEmpty() ) {
|
|
txt += " : ";
|
|
Class::List::ConstIterator it;
|
|
for( it = baseClasses.begin(); it != baseClasses.end(); ++it ) {
|
|
Class bc = *it;
|
|
|
|
if ( it != baseClasses.begin() ) txt +=", ";
|
|
txt += "public ";
|
|
if ( !bc.nameSpace().isEmpty() ) txt += bc.nameSpace() + "::";
|
|
txt += bc.name();
|
|
}
|
|
}
|
|
code += txt;
|
|
|
|
code += "{";
|
|
code.indent();
|
|
|
|
if ( c.isQObject() ) {
|
|
code += "Q_OBJECT";
|
|
code.newLine();
|
|
}
|
|
|
|
Function::List functions = c.functions();
|
|
|
|
Typedef::List typedefs = c.typedefs();
|
|
if ( typedefs.count() > 0 ) {
|
|
code += "public:";
|
|
code.indent();
|
|
Typedef::List::ConstIterator it;
|
|
for( it = typedefs.begin(); it != typedefs.end(); ++it ) {
|
|
code += (*it).declaration();
|
|
}
|
|
code.unindent();
|
|
code.newLine();
|
|
}
|
|
|
|
Enum::List enums = c.enums();
|
|
if ( enums.count() > 0 ) {
|
|
code += "public:";
|
|
code.indent();
|
|
Enum::List::ConstIterator it;
|
|
for( it = enums.begin(); it != enums.end(); ++it ) {
|
|
code += (*it).declaration();
|
|
}
|
|
code.unindent();
|
|
code.newLine();
|
|
}
|
|
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Public ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Public | Function::Slot ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Signal ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Protected ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Protected | Function::Slot ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Private ) );
|
|
code.addBlock( functionHeaders( functions, c.name(), Function::Private | Function::Slot ) );
|
|
|
|
if ( !c.memberVariables().isEmpty() ) {
|
|
Function::List::ConstIterator it;
|
|
for( it = functions.begin(); it != functions.end(); ++it ) {
|
|
if ( (*it).access() == Function::Private ) break;
|
|
}
|
|
if ( it == functions.end() ) code += "private:";
|
|
|
|
code.indent();
|
|
|
|
MemberVariable::List variables = c.memberVariables();
|
|
MemberVariable::List::ConstIterator it2;
|
|
for( it2 = variables.begin(); it2 != variables.end(); ++it2 ) {
|
|
MemberVariable v = *it2;
|
|
|
|
QString decl;
|
|
if ( v.isStatic() ) decl += "static ";
|
|
decl += v.type();
|
|
if ( v.type().right( 1 ) != "*" && v.type().right( 1 ) != "&" ) {
|
|
decl += " ";
|
|
}
|
|
decl += v.name() + ";";
|
|
|
|
code += decl;
|
|
}
|
|
}
|
|
|
|
code.setIndent( 0 );
|
|
code += "};";
|
|
|
|
return code.text();
|
|
}
|
|
|
|
QString Printer::classImplementation( const Class &c )
|
|
{
|
|
Code code;
|
|
|
|
bool needNewLine = false;
|
|
|
|
MemberVariable::List vars = c.memberVariables();
|
|
MemberVariable::List::ConstIterator itV;
|
|
for( itV = vars.begin(); itV != vars.end(); ++itV ) {
|
|
MemberVariable v = *itV;
|
|
if ( !v.isStatic() ) continue;
|
|
code += v.type() + c.name() + "::" + v.name() + " = " + v.initializer() +
|
|
";";
|
|
needNewLine = true;
|
|
}
|
|
if ( needNewLine ) code.newLine();
|
|
|
|
Function::List functions = c.functions();
|
|
Function::List::ConstIterator it;
|
|
for( it = functions.begin(); it != functions.end(); ++it ) {
|
|
Function f = *it;
|
|
|
|
// Omit signals
|
|
if ( f.access() == Function::Signal )
|
|
continue;
|
|
|
|
code += functionSignature( f, c.name(), true );
|
|
|
|
if ( !f.initializers().isEmpty() ) {
|
|
code += ": " + f.initializers().join( ", " );
|
|
}
|
|
|
|
code += "{";
|
|
code.addBlock( f.body(), 2 );
|
|
code += "}";
|
|
code += "";
|
|
}
|
|
|
|
if ( c.isQObject() ) {
|
|
code.newLine();
|
|
code += "#include \"" + c.name().lower() + ".moc\"";
|
|
}
|
|
|
|
return code.text();
|
|
}
|
|
|
|
void Printer::printHeader( const File &f )
|
|
{
|
|
Code out;
|
|
|
|
if ( mCreationWarning ) out += creationWarning();
|
|
|
|
out.addBlock( licenseHeader( f ) );
|
|
|
|
// Create include guard
|
|
QString className = f.filename();
|
|
className.replace( "-", "_" );
|
|
|
|
QString includeGuard;
|
|
if ( !f.nameSpace().isEmpty() ) includeGuard += f.nameSpace().upper() + "_";
|
|
includeGuard += className.upper() + "_H";
|
|
|
|
out += "#ifndef " + includeGuard;
|
|
out += "#define " + includeGuard;
|
|
|
|
out.newLine();
|
|
|
|
|
|
// Create includes
|
|
QStringList processed;
|
|
Class::List classes = f.classes();
|
|
Class::List::ConstIterator it;
|
|
for( it = classes.begin(); it != classes.end(); ++it ) {
|
|
QStringList includes = (*it).headerIncludes();
|
|
QStringList::ConstIterator it2;
|
|
for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) {
|
|
if ( processed.find( *it2 ) == processed.end() ) {
|
|
out += "#include <" + *it2 + ">";
|
|
processed.append( *it2 );
|
|
}
|
|
}
|
|
}
|
|
if ( !processed.isEmpty() ) out.newLine();
|
|
|
|
|
|
// Create forward declarations
|
|
processed.clear();
|
|
for( it = classes.begin(); it != classes.end(); ++it ) {
|
|
QStringList decls = (*it).forwardDeclarations();
|
|
QStringList::ConstIterator it2;
|
|
for( it2 = decls.begin(); it2 != decls.end(); ++it2 ) {
|
|
if ( processed.find( *it2 ) == processed.end() ) {
|
|
out += "class " + *it2 + ";";
|
|
processed.append( *it2 );
|
|
}
|
|
}
|
|
}
|
|
if ( !processed.isEmpty() ) out.newLine();
|
|
|
|
|
|
if ( !f.nameSpace().isEmpty() ) {
|
|
out += "namespace " + f.nameSpace() + " {";
|
|
out.newLine();
|
|
}
|
|
|
|
// Create content
|
|
for( it = classes.begin(); it != classes.end(); ++it ) {
|
|
out.addBlock( classHeader( *it ) );
|
|
out.newLine();
|
|
}
|
|
|
|
if ( !f.nameSpace().isEmpty() ) {
|
|
out += "}";
|
|
out.newLine();
|
|
}
|
|
|
|
// Finish file
|
|
out += "#endif";
|
|
|
|
|
|
// Print to file
|
|
QString filename = f.filename() + ".h";
|
|
|
|
if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" );
|
|
|
|
KSaveFile::backupFile( filename, QString::null, ".backup" );
|
|
|
|
QFile header( filename );
|
|
if ( !header.open( IO_WriteOnly ) ) {
|
|
kdError() << "Can't open '" << filename << "' for writing." << endl;
|
|
return;
|
|
}
|
|
|
|
QTextStream h( &header );
|
|
|
|
h << out.text();
|
|
|
|
header.close();
|
|
}
|
|
|
|
void Printer::printImplementation( const File &f, bool createHeaderInclude )
|
|
{
|
|
Code out;
|
|
|
|
if ( mCreationWarning ) out += creationWarning();
|
|
|
|
out.addBlock( licenseHeader( f ) );
|
|
|
|
out.newLine();
|
|
|
|
// Create includes
|
|
if ( createHeaderInclude ) {
|
|
out += "#include \"" + f.filename() + ".h\"";
|
|
out.newLine();
|
|
}
|
|
|
|
QStringList includes = f.includes();
|
|
QStringList::ConstIterator it2;
|
|
for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) {
|
|
out += "#include <" + *it2 + ">";
|
|
}
|
|
if ( !includes.isEmpty() ) out.newLine();
|
|
|
|
// Create class includes
|
|
QStringList processed;
|
|
Class::List classes = f.classes();
|
|
Class::List::ConstIterator it;
|
|
for( it = classes.begin(); it != classes.end(); ++it ) {
|
|
QStringList includes = (*it).includes();
|
|
QStringList::ConstIterator it2;
|
|
for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) {
|
|
if ( processed.find( *it2 ) == processed.end() ) {
|
|
out += "#include <" + *it2 + ">";
|
|
processed.append( *it2 );
|
|
}
|
|
}
|
|
}
|
|
if ( !processed.isEmpty() ) out.newLine();
|
|
|
|
if ( !f.nameSpace().isEmpty() ) {
|
|
out += "using namespace " + f.nameSpace() + ";";
|
|
out.newLine();
|
|
}
|
|
|
|
// 'extern "C"' declarations
|
|
QStringList externCDeclarations = f.externCDeclarations();
|
|
if ( !externCDeclarations.isEmpty() ) {
|
|
out += "extern \"C\" {";
|
|
QStringList::ConstIterator it;
|
|
for( it = externCDeclarations.begin(); it != externCDeclarations.end();
|
|
++it ) {
|
|
out += *it + ";";
|
|
}
|
|
out += "}";
|
|
out.newLine();
|
|
}
|
|
|
|
// File variables
|
|
Variable::List vars = f.fileVariables();
|
|
Variable::List::ConstIterator itV;
|
|
for( itV = vars.begin(); itV != vars.end(); ++itV ) {
|
|
Variable v = *itV;
|
|
QString str;
|
|
if ( v.isStatic() ) str += "static ";
|
|
str += v.type() + " " + v.name() + ";";
|
|
out += str;
|
|
}
|
|
if ( !vars.isEmpty() ) out.newLine();
|
|
|
|
// File code
|
|
if ( !f.fileCode().isEmpty() ) {
|
|
out += f.fileCode();
|
|
out.newLine();
|
|
}
|
|
|
|
// File functions
|
|
Function::List funcs = f.fileFunctions();
|
|
Function::List::ConstIterator itF;
|
|
for( itF = funcs.begin(); itF != funcs.end(); ++itF ) {
|
|
Function f = *itF;
|
|
out += functionSignature( f );
|
|
out += "{";
|
|
out.addBlock( f.body(), 2 );
|
|
out += "}";
|
|
out.newLine();
|
|
}
|
|
|
|
// Classes
|
|
for( it = classes.begin(); it != classes.end(); ++it ) {
|
|
QString str = classImplementation( *it );
|
|
if ( !str.isEmpty() ) out += classImplementation( *it );
|
|
}
|
|
|
|
// Print to file
|
|
QString filename = f.filename() + ".cpp";
|
|
|
|
if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" );
|
|
|
|
KSaveFile::backupFile( filename, QString::null, ".backup" );
|
|
|
|
QFile implementation( filename );
|
|
if ( !implementation.open( IO_WriteOnly ) ) {
|
|
kdError() << "Can't open '" << filename << "' for writing." << endl;
|
|
return;
|
|
}
|
|
|
|
QTextStream h( &implementation );
|
|
|
|
h << out.text();
|
|
|
|
implementation.close();
|
|
}
|
|
|
|
void Printer::printAutoMakefile( const AutoMakefile &am )
|
|
{
|
|
QString filename = "Makefile.am";
|
|
|
|
if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" );
|
|
|
|
KSaveFile::backupFile( filename, QString::null, ".backup" );
|
|
|
|
QFile file( filename );
|
|
if ( !file.open( IO_WriteOnly ) ) {
|
|
kdError() << "Can't open '" << filename << "' for writing." << endl;
|
|
return;
|
|
}
|
|
|
|
QTextStream ts( &file );
|
|
|
|
ts << am.text();
|
|
}
|