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.
227 lines
8.5 KiB
227 lines
8.5 KiB
/***************************************************************************
|
|
rubycodeoperation.cpp
|
|
Derived from the Java code generator by thomas
|
|
|
|
begin : Thur Jul 21 2005
|
|
author : Richard Dale
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
* copyright (C) 2006-2007 *
|
|
* Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
|
|
***************************************************************************/
|
|
|
|
// own header
|
|
#include "rubycodeoperation.h"
|
|
|
|
// qt/kde includes
|
|
#include <tqregexp.h>
|
|
|
|
// local includes
|
|
#include "rubyclassifiercodedocument.h"
|
|
#include "rubycodedocumentation.h"
|
|
#include "rubycodegenerator.h"
|
|
#include "../uml.h"
|
|
|
|
// Constructors/Destructors
|
|
//
|
|
|
|
RubyCodeOperation::RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation *tqparent, const TQString & body, const TQString & comment )
|
|
: CodeOperation (doc, tqparent, body, comment)
|
|
{
|
|
// lets not go with the default comment and instead use
|
|
// full-blown ruby documentation object instead
|
|
setComment(new RubyCodeDocumentation(doc));
|
|
|
|
// these things never change..
|
|
setOverallIndentationLevel(1);
|
|
|
|
updateMethodDeclaration();
|
|
updateContent();
|
|
|
|
}
|
|
|
|
RubyCodeOperation::~RubyCodeOperation ( ) { }
|
|
|
|
// Other methods
|
|
//
|
|
|
|
// we basically want to update the doc and start text of this method
|
|
void RubyCodeOperation::updateMethodDeclaration()
|
|
{
|
|
|
|
CodeDocument * doc = getParentDocument();
|
|
RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(doc);
|
|
UMLClassifier *c = rubydoc->getParentClassifier();
|
|
UMLOperation * o = getParentOperation();
|
|
bool isInterface = rubydoc->getParentClassifier()->isInterface();
|
|
TQString endLine = getNewLineEndingChars();
|
|
|
|
// now, the starting text.
|
|
TQString strVis = rubydoc->scopeToRubyDecl(o->getVisibility());
|
|
// no return type for constructors
|
|
TQString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName());
|
|
TQString returnType = o->isConstructorOperation() ? TQString("") : (fixedReturn + TQString(" "));
|
|
TQString methodName = o->getName();
|
|
|
|
TQString RubyClassName = rubydoc->getRubyClassName(c->getName());
|
|
|
|
// Skip destructors, and operator methods which
|
|
// can't be defined in ruby
|
|
if ( methodName.startsWith("~")
|
|
|| TQRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) )
|
|
{
|
|
getComment()->setText("");
|
|
return;
|
|
}
|
|
|
|
if (RubyClassName == methodName) {
|
|
methodName = "initialize";
|
|
}
|
|
|
|
methodName.tqreplace(TQRegExp("operator\\s*"), "");
|
|
methodName = methodName.mid(0, 1).lower() + methodName.mid(1);
|
|
|
|
TQString paramStr = TQString("");
|
|
TQStringList commentedParams;
|
|
|
|
// assemble parameters
|
|
UMLAttributeList list = getParentOperation()->getParmList();
|
|
int nrofParam = list.count();
|
|
int paramNum = 0;
|
|
for(UMLAttribute* parm = list.first(); parm; parm = list.next())
|
|
{
|
|
TQString paramName = RubyCodeGenerator::cppToRubyName(parm->getName());
|
|
paramStr += paramName;
|
|
if (! parm->getInitialValue().isEmpty()) {
|
|
paramStr += TQString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue());
|
|
}
|
|
paramNum++;
|
|
|
|
if (paramNum != nrofParam )
|
|
paramStr += ", ";
|
|
}
|
|
|
|
TQString startText;
|
|
if (isInterface) {
|
|
// Assume 'isInterface' means a module in Ruby, so
|
|
// generate module methods
|
|
startText = "def "+ RubyClassName + '.' + methodName + '(' + paramStr +')';
|
|
} else {
|
|
startText = "def "+ methodName + '(' + paramStr +')';
|
|
}
|
|
|
|
startText += "";
|
|
setEndMethodText("end");
|
|
|
|
setStartMethodText(startText);
|
|
|
|
// Lastly, for text content generation, we fix the comment on the
|
|
// operation, IF the codeop is autogenerated & currently empty
|
|
TQString comment = o->getDoc();
|
|
|
|
if (comment.isEmpty()) {
|
|
if (getContentType() == CodeBlock::AutoGenerated) {
|
|
UMLAttributeList parameters = o->getParmList();
|
|
for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
|
|
comment += endLine + "* _" + iterator.current()->getName() + "_ ";
|
|
comment += (' ' + iterator.current()->getDoc().tqreplace( TQRegExp("[\\n\\r]+[\\t ]*"),
|
|
endLine + " " ) );
|
|
}
|
|
// add a returns statement too
|
|
if(!returnType.isEmpty() && !TQRegExp("^void\\s*$").exactMatch(returnType))
|
|
comment += endLine + "* _returns_ " + returnType + ' ';
|
|
getComment()->setText(comment);
|
|
}
|
|
} else {
|
|
comment.tqreplace(TQRegExp("[\\n\\r]+ *"), endLine);
|
|
comment.tqreplace(TQRegExp("[\\n\\r]+\\t*"), endLine);
|
|
|
|
comment.tqreplace(" m_", " ");
|
|
comment.tqreplace(TQRegExp("\\s[npb](?=[A-Z])"), " ");
|
|
TQRegExp re_params("@param (\\w)(\\w*)");
|
|
int pos = re_params.search(comment);
|
|
while (pos != -1) {
|
|
comment.tqreplace( re_params.cap(0),
|
|
TQString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' );
|
|
commentedParams.append(re_params.cap(1).lower() + re_params.cap(2));
|
|
|
|
pos += re_params.matchedLength() + 3;
|
|
pos = re_params.search(comment, pos);
|
|
}
|
|
|
|
UMLAttributeList parameters = o->getParmList();
|
|
for (UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) {
|
|
// Only write an individual @param entry if one hasn't been found already
|
|
// in the main doc comment
|
|
if (commentedParams.tqcontains(RubyCodeGenerator::cppToRubyName(iterator.current()->getName())) == 0) {
|
|
comment += (endLine + "@param _" + RubyCodeGenerator::cppToRubyName(iterator.current()->getName()) + '_');
|
|
if (iterator.current()->getDoc().isEmpty()) {
|
|
comment += (' ' + RubyCodeGenerator::cppToRubyType(iterator.current()->getTypeName()));
|
|
} else {
|
|
comment += (' ' + iterator.current()->getDoc().tqreplace(TQRegExp("[\\n\\r]+[\\t ]*"), endLine + " "));
|
|
}
|
|
}
|
|
}
|
|
|
|
comment.tqreplace("@ref ", "");
|
|
comment.tqreplace("@param", "*");
|
|
comment.tqreplace("@return", "* _returns_");
|
|
|
|
// All lines after the first one starting with '*' in the doc comment
|
|
// must be indented correctly. If they aren't a list
|
|
// item starting with '*', then indent the text with
|
|
// two spaces, ' ', to line up with the list item.
|
|
pos = comment.tqfind(endLine + '*');
|
|
if (pos != -1) {
|
|
pos += endLine.length() + 1;
|
|
pos = comment.tqfind(endLine, pos);
|
|
}
|
|
|
|
while (pos > 0) {
|
|
pos += endLine.length();
|
|
if (comment[pos] != '*') {
|
|
comment.insert(pos, " ");
|
|
pos += 2;
|
|
}
|
|
|
|
pos = comment.tqfind(endLine, pos);
|
|
}
|
|
|
|
TQString typeStr = RubyCodeGenerator::cppToRubyType(o->getTypeName());
|
|
if ( !typeStr.isEmpty()
|
|
&& !TQRegExp("^void\\s*$").exactMatch(typeStr)
|
|
&& comment.tqcontains("_returns_") == 0 )
|
|
{
|
|
comment += endLine + "* _returns_ " + typeStr;
|
|
}
|
|
|
|
getComment()->setText(comment);
|
|
}
|
|
|
|
// In Java, for interfaces..we DONT write out non-public
|
|
// method declarations. And for Ruby modules?
|
|
if (isInterface) {
|
|
UMLOperation * o = getParentOperation();
|
|
if(o->getVisibility() != Uml::Visibility::Public)
|
|
setWriteOutText(false);
|
|
}
|
|
|
|
}
|
|
|
|
int RubyCodeOperation::lastEditableLine() {
|
|
ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument());
|
|
if(doc->parentIsInterface())
|
|
return -1; // very last line is NOT editable as its a one-line declaration w/ no body in
|
|
// an interface.
|
|
return 0;
|
|
}
|
|
|
|
#include "rubycodeoperation.moc"
|