// 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(); QString endLine = getNewLineEndingChars(); // now, the starting text. //:UNUSED: QString strVis = o->visibility().toString(); // no return type for constructors QString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName()); QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" ")); QString methodName = o->name(); QString RubyClassName = rubydoc->getRubyClassName(c->name()); // Skip destructors, and operator methods which // can't be defined in ruby if ( methodName.startsWith('~') || QRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) ) { getComment()->setText(""); return; } if (RubyClassName == methodName) { methodName = "initialize"; } methodName.remove(QRegExp("operator\\s*")); methodName = methodName.mid(0, 1).toLower() + methodName.mid(1); QString paramStr = QString(""); QStringList commentedParams; // assemble parameters UMLAttributeList list = getParentOperation()->getParmList(); int nrofParam = list.count(); int paramNum = 0; foreach (UMLAttribute* parm, list) { QString paramName = RubyCodeGenerator::cppToRubyName(parm->name()); paramStr += paramName; if (! parm->getInitialValue().isEmpty()) { paramStr += QString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue()); } paramNum++; if (paramNum != nrofParam ) paramStr += ", "; }
/** * Create a new classifier code document. * @param classifier the UML classifier * @return a new classifier code document */ CodeDocument * RubyCodeGenerator::newClassifierCodeDocument(UMLClassifier * classifier) { RubyClassifierCodeDocument * doc = new RubyClassifierCodeDocument(classifier); doc->initCodeClassFields(); return doc; }
void RubyCodeAccessorMethod::updateMethodDeclaration() { RubyCodeClassField * rubyfield = dynamic_cast<RubyCodeClassField*>(getParentClassField()); RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(rubyfield->getParentDocument()); // gather defs CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAttributeAccessorScope(); QString strVis = rubydoc->scopeToRubyDecl(rubyfield->getVisibility()); QString fieldName = RubyCodeGenerator::cppToRubyName(rubyfield->getFieldName()); QString fieldType = RubyCodeGenerator::cppToRubyType(rubyfield->getTypeName()); QString objectType = rubyfield->getListObjectType(); if(objectType.isEmpty()) objectType = fieldName; QString endLine = p->getNewLineEndingChars(); QString description = getParentObject()->getDoc(); description.replace(QRegExp("m_[npb](?=[A-Z])"), ""); description.replace("m_", ""); description.replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine); // set scope of this accessor appropriately..if its an attribute, // we need to be more sophisticated if(rubyfield->parentIsAttribute()) switch (scopePolicy) { case CodeGenerationPolicy::Public: case CodeGenerationPolicy::Private: case CodeGenerationPolicy::Protected: strVis = rubydoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy); break; default: case CodeGenerationPolicy::FromParent: // do nothing..already have taken parent value break; } // some variables we will need to populate QString headerText = ""; QString methodReturnType = ""; QString methodName = ""; QString methodParams = ""; switch(getType()) { case CodeAccessorMethod::ADD: methodName = "add" + Codegen_Utils::capitalizeFirstLetter(fieldType); methodReturnType = ""; methodParams = objectType+" value "; headerText = "Add an object of type "+objectType+" to the Array "+fieldName+endLine+description+endLine+"@return nil"; setStartMethodText("def "+ methodName + '(' + methodParams + ')'); setEndMethodText("end"); break; case CodeAccessorMethod::GET: headerText = "Get the value of " + fieldName + endLine + description; setStartMethodText(QString("attr_reader :") + fieldName); setEndMethodText(""); break; case CodeAccessorMethod::LIST: methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldType)+"List"; methodReturnType = ""; headerText = "Get the list of "+fieldName+endLine+description+endLine+"_returns_ List of "+fieldName; setStartMethodText("def "+ methodName + '(' + methodParams + ')'); setEndMethodText("end"); break; case CodeAccessorMethod::REMOVE: methodName = "remove" + Codegen_Utils::capitalizeFirstLetter(fieldType); methodReturnType = ""; methodParams = objectType+" value "; headerText = "Remove an object of type "+objectType+" from the List "+fieldName+endLine+description; setStartMethodText("def "+ methodName + '(' + methodParams + ')'); setEndMethodText("end"); break; case CodeAccessorMethod::SET: headerText = "Set the value of " + fieldName + endLine + description; setStartMethodText(QString("attr_writer :") + fieldName); setEndMethodText(""); break; default: // do nothing..no idea what this is kWarning()<<"Warning: can't generate RubyCodeAccessorMethod for type: "<<getType()<<endl; break; } // set header once. if (getComment()->getText().isEmpty()) getComment()->setText(headerText); }
void RubyCodeClassFieldDeclarationBlock::updateContent( ) { CodeClassField * cf = getParentClassField(); ClassifierCodeDocument * doc = cf->getParentDocument(); RubyCodeClassField * rcf = dynamic_cast<RubyCodeClassField*>(cf); RubyClassifierCodeDocument* rdoc = dynamic_cast<RubyClassifierCodeDocument*>(doc); CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAssociationFieldScope(); // Set the comment QString notes = getParentObject()->getDoc(); getComment()->setText(notes); // Set the body QString staticValue = getParentObject()->getStatic() ? "static " : ""; QString scopeStr = rdoc->scopeToRubyDecl(getParentObject()->getVisibility()); // IF this is from an association, then scope taken as appropriate to policy if(!rcf->parentIsAttribute()) { switch (scopePolicy) { case CodeGenerationPolicy::Public: case CodeGenerationPolicy::Private: case CodeGenerationPolicy::Protected: scopeStr = rdoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy); break; default: case CodeGenerationPolicy::FromParent: // do nothing here... will leave as from parent object break; } } QString typeName = rcf->getTypeName(); QString fieldName = rcf->getFieldName(); QString initialV = rcf->getInitialValue(); if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue()) typeName = "Array"; QString body = staticValue+scopeStr+' '+typeName+' '+fieldName; if (!initialV.isEmpty()) body.append(" = " + initialV); else if (!cf->parentIsAttribute()) { UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject()); if (role->getObject()->getBaseType() == Uml::ot_Interface) { // do nothing.. can't instanciate an interface } else { // FIX?: IF a constructor method exists in the classifiercodedoc // of the parent Object, then we can use that instead (if its empty). if(cf->fieldIsSingleValue()) { if(!typeName.isEmpty()) body.append(" = " + typeName + ".new()"); } else body.append(" = []"); } } setText(body); }
// 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(); QString endLine = getNewLineEndingChars(); // now, the starting text. QString strVis = rubydoc->scopeToRubyDecl(o->getVisibility()); // no return type for constructors QString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName()); QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" ")); QString methodName = o->getName(); QString RubyClassName = rubydoc->getRubyClassName(c->getName()); // Skip destructors, and operator methods which // can't be defined in ruby if ( methodName.startsWith("~") || QRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) ) { getComment()->setText(""); return; } if (RubyClassName == methodName) { methodName = "initialize"; } methodName.replace(QRegExp("operator\\s*"), ""); methodName = methodName.mid(0, 1).lower() + methodName.mid(1); QString paramStr = QString(""); QStringList commentedParams; // assemble parameters UMLAttributeList list = getParentOperation()->getParmList(); int nrofParam = list.count(); int paramNum = 0; for(UMLAttribute* parm = list.first(); parm; parm = list.next()) { QString paramName = RubyCodeGenerator::cppToRubyName(parm->getName()); paramStr += paramName; if (! parm->getInitialValue().isEmpty()) { paramStr += QString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue()); } paramNum++; if (paramNum != nrofParam ) paramStr += ", "; } QString 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 QString 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().replace( QRegExp("[\\n\\r]+[\\t ]*"), endLine + " " ) ); } // add a returns statement too if(!returnType.isEmpty() && !QRegExp("^void\\s*$").exactMatch(returnType)) comment += endLine + "* _returns_ " + returnType + ' '; getComment()->setText(comment); } } else { comment.replace(QRegExp("[\\n\\r]+ *"), endLine); comment.replace(QRegExp("[\\n\\r]+\\t*"), endLine); comment.replace(" m_", " "); comment.replace(QRegExp("\\s[npb](?=[A-Z])"), " "); QRegExp re_params("@param (\\w)(\\w*)"); int pos = re_params.search(comment); while (pos != -1) { comment.replace( re_params.cap(0), QString("@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.contains(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().replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine + " ")); } } } comment.replace("@ref ", ""); comment.replace("@param", "*"); comment.replace("@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.find(endLine + '*'); if (pos != -1) { pos += endLine.length() + 1; pos = comment.find(endLine, pos); } while (pos > 0) { pos += endLine.length(); if (comment[pos] != '*') { comment.insert(pos, " "); pos += 2; } pos = comment.find(endLine, pos); } QString typeStr = RubyCodeGenerator::cppToRubyType(o->getTypeName()); if ( !typeStr.isEmpty() && !QRegExp("^void\\s*$").exactMatch(typeStr) && comment.contains("_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); } }