umbrello API Documentation

rubycodeoperation.cpp

00001 /***************************************************************************
00002                           rubycodeoperation.cpp
00003                           Derived from the Java code generator by thomas
00004 
00005     begin                : Thur Jul 21 2005
00006     author               : Richard Dale
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   copyright (C) 2006-2007                                               *
00017  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00018  ***************************************************************************/
00019 
00020 // own header
00021 #include "rubycodeoperation.h"
00022 
00023 // qt/kde includes
00024 #include <qregexp.h>
00025 
00026 // local includes
00027 #include "rubyclassifiercodedocument.h"
00028 #include "rubycodedocumentation.h"
00029 #include "rubycodegenerator.h"
00030 #include "../uml.h"
00031 
00032 // Constructors/Destructors
00033 //
00034 
00035 RubyCodeOperation::RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment )
00036         : CodeOperation (doc, parent, body, comment)
00037 {
00038     // lets not go with the default comment and instead use
00039     // full-blown ruby documentation object instead
00040     setComment(new RubyCodeDocumentation(doc));
00041 
00042     // these things never change..
00043     setOverallIndentationLevel(1);
00044 
00045     updateMethodDeclaration();
00046     updateContent();
00047 
00048 }
00049 
00050 RubyCodeOperation::~RubyCodeOperation ( ) { }
00051 
00052 // Other methods
00053 //
00054 
00055 // we basically want to update the doc and start text of this method
00056 void RubyCodeOperation::updateMethodDeclaration()
00057 {
00058 
00059     CodeDocument * doc = getParentDocument();
00060     RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(doc);
00061     UMLClassifier *c = rubydoc->getParentClassifier();
00062     UMLOperation * o = getParentOperation();
00063     bool isInterface = rubydoc->getParentClassifier()->isInterface();
00064     QString endLine = getNewLineEndingChars();
00065 
00066     // now, the starting text.
00067     QString strVis = rubydoc->scopeToRubyDecl(o->getVisibility());
00068     // no return type for constructors
00069     QString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName());
00070     QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" "));
00071     QString methodName = o->getName();
00072 
00073     QString RubyClassName = rubydoc->getRubyClassName(c->getName());
00074 
00075     // Skip destructors, and operator methods which
00076     // can't be defined in ruby
00077     if (    methodName.startsWith("~")
00078             || QRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) )
00079     {
00080         getComment()->setText("");
00081         return;
00082     }
00083 
00084     if (RubyClassName == methodName) {
00085         methodName = "initialize";
00086     }
00087 
00088     methodName.replace(QRegExp("operator\\s*"), "");
00089     methodName = methodName.mid(0, 1).lower() + methodName.mid(1);
00090 
00091     QString paramStr = QString("");
00092     QStringList commentedParams;
00093 
00094     // assemble parameters
00095     UMLAttributeList list = getParentOperation()->getParmList();
00096     int nrofParam = list.count();
00097     int paramNum = 0;
00098     for(UMLAttribute* parm = list.first(); parm; parm = list.next())
00099     {
00100         QString paramName = RubyCodeGenerator::cppToRubyName(parm->getName());
00101         paramStr += paramName;
00102         if (! parm->getInitialValue().isEmpty()) {
00103             paramStr += QString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue());
00104         }
00105         paramNum++;
00106 
00107         if (paramNum != nrofParam )
00108             paramStr  += ", ";
00109     }
00110 
00111     QString startText;
00112     if (isInterface) {
00113         // Assume 'isInterface' means a module in Ruby, so
00114         // generate module methods
00115         startText = "def "+ RubyClassName + '.' + methodName + '(' + paramStr +')';
00116     } else {
00117         startText = "def "+ methodName + '(' + paramStr +')';
00118     }
00119 
00120     startText += "";
00121     setEndMethodText("end");
00122 
00123     setStartMethodText(startText);
00124 
00125     // Lastly, for text content generation, we fix the comment on the
00126     // operation, IF the codeop is autogenerated & currently empty
00127     QString comment = o->getDoc();
00128 
00129     if (comment.isEmpty()) {
00130         if (getContentType() == CodeBlock::AutoGenerated) {
00131             UMLAttributeList parameters = o->getParmList();
00132             for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
00133                 comment += endLine + "* _" + iterator.current()->getName() + "_ ";
00134                 comment += (' ' + iterator.current()->getDoc().replace( QRegExp("[\\n\\r]+[\\t ]*"),
00135                                                                         endLine + "  " ) );
00136             }
00137             // add a returns statement too
00138             if(!returnType.isEmpty() && !QRegExp("^void\\s*$").exactMatch(returnType))
00139                 comment += endLine + "* _returns_ " + returnType + ' ';
00140             getComment()->setText(comment);
00141         }
00142     } else {
00143         comment.replace(QRegExp("[\\n\\r]+ *"), endLine);
00144         comment.replace(QRegExp("[\\n\\r]+\\t*"), endLine);
00145 
00146         comment.replace(" m_", " ");
00147         comment.replace(QRegExp("\\s[npb](?=[A-Z])"), " ");
00148         QRegExp re_params("@param (\\w)(\\w*)");
00149         int pos = re_params.search(comment);
00150         while (pos != -1) {
00151             comment.replace( re_params.cap(0),
00152                             QString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' );
00153             commentedParams.append(re_params.cap(1).lower() + re_params.cap(2));
00154 
00155             pos += re_params.matchedLength() + 3;
00156             pos = re_params.search(comment, pos);
00157         }
00158 
00159         UMLAttributeList parameters = o->getParmList();
00160         for (UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
00161             // Only write an individual @param entry if one hasn't been found already
00162             // in the main doc comment
00163             if (commentedParams.contains(RubyCodeGenerator::cppToRubyName(iterator.current()->getName())) == 0) {
00164                 comment += (endLine + "@param _" + RubyCodeGenerator::cppToRubyName(iterator.current()->getName()) + '_');
00165                 if (iterator.current()->getDoc().isEmpty()) {
00166                     comment += (' ' + RubyCodeGenerator::cppToRubyType(iterator.current()->getTypeName()));
00167                 } else {
00168                     comment += (' ' + iterator.current()->getDoc().replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine + "  "));
00169                 }
00170             }
00171         }
00172 
00173         comment.replace("@ref ", "");
00174         comment.replace("@param", "*");
00175         comment.replace("@return", "* _returns_");
00176 
00177         // All lines after the first one starting with '*' in the doc comment
00178         // must be indented correctly. If they aren't a list
00179         // item starting with '*', then indent the text with
00180         // two spaces, '  ', to line up with the list item.
00181         pos = comment.find(endLine + '*');
00182         if (pos != -1) {
00183             pos += endLine.length() + 1;
00184             pos = comment.find(endLine, pos);
00185         }
00186 
00187         while (pos > 0) {
00188             pos += endLine.length();
00189             if (comment[pos] != '*') {
00190                 comment.insert(pos, "  ");
00191                 pos += 2;
00192             }
00193 
00194             pos = comment.find(endLine, pos);
00195         }
00196 
00197         QString typeStr = RubyCodeGenerator::cppToRubyType(o->getTypeName());
00198         if ( !typeStr.isEmpty()
00199                 && !QRegExp("^void\\s*$").exactMatch(typeStr)
00200                 && comment.contains("_returns_") == 0 )
00201         {
00202             comment += endLine + "* _returns_ " + typeStr;
00203         }
00204 
00205         getComment()->setText(comment);
00206     }
00207 
00208     // In Java, for interfaces..we DONT write out non-public
00209     // method declarations. And for Ruby modules?
00210     if (isInterface) {
00211         UMLOperation * o = getParentOperation();
00212         if(o->getVisibility() != Uml::Visibility::Public)
00213             setWriteOutText(false);
00214     }
00215 
00216 }
00217 
00218 int RubyCodeOperation::lastEditableLine() {
00219     ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
00220     if(doc->parentIsInterface())
00221         return -1; // very last line is NOT editable as its a one-line declaration w/ no body in
00222     // an interface.
00223     return 0;
00224 }
00225 
00226 #include "rubycodeoperation.moc"
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:08:00 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003