Beispiel #1
0
void UmlClassMember::remove_comments(Q3CString & s)
{
    int index1 = 0;

    if ((index1 = s.find("${comment}")) != -1)
        s.remove((unsigned) index1, 10);
    else if ((index1 = s.find("${description}")) != -1)
        s.remove((unsigned) index1, 14);

    while ((index1 = s.find('/', index1)) != -1) {
        int index2;

        switch (((const char *) s)[index1 + 1]) {
        case '/':
            if ((index2 = s.find('\n', index1 + 2)) != -1)
                s.remove(index1, index2 - index1 + 1);
            else
                s.truncate(index1);
            break;
        case '*':
            if ((index2 = s.find("*/", index1 + 2)) != -1)
                s.replace(index1, index2 - index1 + 1, " ");
            else
                s.truncate(index1);
            break;
        default:
            index1 += 1;
        }
    }
}
Beispiel #2
0
void UmlClass::addCopy(bool cte)
{
    TRACE_FUNCTION;
    UmlOperation * op = UmlOperation::create(this, name());

    if (op == 0)
        UmlCom::trace("can't add copy contructor");
    else {
        // to see that it is a copy constructor
        op->set_Stereotype("copy");

        // add 'source' parameter

        UmlParameter param;

        param.name = "source";
        param.dir = (cte) ? InputDirection : InputOutputDirection;
        param.type.type = this;

        op->addParameter(0, param);

        // add the parameter profile, and
        // remove the useless "${type} " mainly to remove the space

        Q3CString p = (cte) ? "const ${t0} & ${p0}" : "${t0} & ${p0}";
        Q3CString s;
        int index;

        s = op->cppDecl();

        if (s.isEmpty())
            s = CppSettings::operationDecl();

        if ((index = s.find("${(}")) != -1)
            s.insert(index + 4, (const char *)p); //[rageek] cast because Q3CString

        if ((index = s.find("${type} ")) != -1)
            s.remove(index, 8);

        op->set_CppDecl(s);

        s = op->cppDef();

        if (s.isEmpty())
            s = CppSettings::operationDef();

        if ((index = s.find("${(}")) != -1)
            s.insert(index + 4, (const char *)p); //[rageek] cast because Q3CString

        if ((index = s.find("${type} ")) != -1)
            s.remove(index, 8);

        op->set_CppDef(s);
    }
}
Beispiel #3
0
void UmlClassMember::write_type(FileOut & out, const UmlTypeSpec & t, Q3CString s, const char * k_name, const char * k_type)
{
    s = s.simplifyWhiteSpace();

    int index;

    // remove k_name and all after it except []
    if (k_name && *k_name && ((index = s.find(k_name, 0)) != -1)) {//[rageek] Removed CS=FALSE - rethink this, case sensitive
        //remove name
        s.remove(index, strlen(k_name));

        for (;;) {
            if (s[index] == ' ')
                s.remove(index, 1);

            if (s[index] != '[')
                break;

            index += 1;

            int index2;

            if ((index2 = s.find(index, ']')) == -1)
                break;

            index = index2 + 1;
        }

        s.resize(index);
    }
    else if ((index = s.find('=')) != -1) {
        s.resize(index);
        s = s.simplifyWhiteSpace();
    }

    if (k_type && *k_type && ((index = s.find(k_type)) == -1))
        out.idref_datatype(s);
    else if (s != k_type) {
        // have modifiers
        if (t.type != 0) {
            s.replace(index, strlen(k_type), t.type->name());
            out.idref(s, t.type);
        }
        else
            out.idref_datatype(s.replace(index, strlen(k_type), t.explicit_type));
    }
    else if (t.type != 0)
        out.idref(t.type);
    else
        out.idref_datatype(t.explicit_type);
}
Beispiel #4
0
void UmlRelation::compute_dependency(Q3PtrList<CppRefType> & dependencies,
				     const Q3CString & cl_stereotype,
				     bool all_in_h) {
  if (cl_stereotype == "enum")
    return;
  
  switch (relationKind()) {
  case aDependency:
    if (stereotype() == "friend")
      break;
    CppRefType::add(roleType(), dependencies, cppDecl() != "#include in source",
		    roleType()->isCppExternal());
    break;
  case aGeneralisation:
  case aRealization:
    CppRefType::add(roleType(), dependencies, TRUE);
    break;
  default:
    Q3CString decl = cppDecl();
    int index;
    
    if ((index = decl.find("${static}")) != -1)
      decl.remove((unsigned) index, 9);
    if ((index = decl.find("${mutable}")) != -1)
      decl.remove((unsigned) index, 10);
    if ((index = decl.find("${volatile}")) != -1)
      decl.remove((unsigned) index, 11);
    if ((index = decl.find("${const}")) != -1)
      decl.remove((unsigned) index, 8);
    if ((index = decl.find("${multiplicity}")) != -1)
      decl.remove((unsigned) index, 15);
    if ((index = decl.find("${name}")) != -1)
      decl.remove((unsigned) index, 7);
    if ((index = decl.find("${inverse_name}")) != -1)
      decl.remove((unsigned) index, 15);
    if ((index = decl.find("${value}")) != -1)
      decl.remove((unsigned) index, 8);
    if ((index = decl.find("${h_value}")) != -1)
      decl.remove((unsigned) index, 10);
    if ((index = decl.find("${stereotype}")) != -1)
      decl.replace((unsigned) index, 13,
		   CppSettings::relationAttributeStereotype(stereotype()));
    if ((index = decl.find("${association}")) != -1) {
      decl.replace((unsigned) index, 14,
		   association().toString());
    }
    replace_alias(decl);
    
    UmlTypeSpec type;
    
    type.type = roleType();
    UmlClassMember::compute_dependency(dependencies, decl, type, all_in_h);
  }
}
Beispiel #5
0
Q3CString Dialog::digest(const QString s)
{
    Q3CString c = (const char *) s;
    int index;

    index = 0;

    while ((index = c.find("\\n", index)) != -1) {
        c.replace(index, 2, "\n");
        index += 1;
    }

    index = 0;

    while ((index = c.find("\\t", index)) != -1) {
        c.replace(index, 2, "\t");
        index += 1;
    }

    index = 0;

    while ((index = c.find("\r", index)) != -1) {
        c.remove(index, 1);
    }

    return c;
}
Beispiel #6
0
void UmlClassMember::remove_comments(Q3CString & s)
{
    int index;

    if ((index = s.find("${comment}")) != -1)
        s.replace(index, 10, " ");

    index = 0;
    while ((index = s.find('#', index)) != -1) {
        int index2 = s.find('\n', index + 1);

        if (index2 == -1) {
            s.resize(index);
            break;
        }

        s.remove(index, index2 - index);
    }

    index = 0;
    while ((index = s.find("//", index)) != -1) {
        int index2 = s.find('\n', index + 2);

        if (index2 == -1) {
            s.resize(index);
            break;
        }

        s.remove(index, index2 - index);
    }

    index = 0;
    while ((index = s.find("/*", index)) != -1) {
        int index2 = s.find("*/", index + 2);

        if (index2 == -1) {
            s.resize(index);
            break;
        }

        s.replace(index, index2 + 2 - index, " ");
    }

    s = s.simplifyWhiteSpace();
}
Beispiel #7
0
void UmlClass::addContructor(bool expl)
{
    TRACE_FUNCTION;
    QLOG_INFO() << "1.1.1";
    UmlOperation * op = UmlOperation::create(this, name());
    QLOG_INFO() << "1.1.2";
    if (op == 0)
        UmlCom::trace("can't add contructor");
    else {
        QLOG_INFO() << "1.1.3";
        Q3CString s;
        int index;

        // remove the useless "${type} " mainly to remove the space

        s = op->cppDecl();
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.4";
        if (s.isEmpty())
            s = CppSettings::operationDecl();
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.5";
        if ((index = s.find("${type} ")) != -1)
            s.remove(index, 8);
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.6";
        if (expl && ((index = s.find("${name}")) != -1))
            s.insert(index, "explicit ");
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.7";
        op->set_CppDecl(s);
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.8";
        s = op->cppDef();
        QLOG_INFO() << s;
        QLOG_INFO() << "1.1.81";
        if (s.isEmpty())
            s = CppSettings::operationDef();
        QLOG_INFO() << "1.1.9";
        if ((index = s.find("${type} ")) != -1)
            s.remove(index, 8);
        QLOG_INFO() << "1.1.10";
        op->set_CppDef(s);
    }
}
Beispiel #8
0
void UmlClass::addDestructor(bool virt)
{
    TRACE_FUNCTION;
    UmlOperation * op = UmlOperation::create(this, "~" + name());

    if (op == 0)
        UmlCom::trace("can't add destructor");
    else {
        if (virt)
            op->set_isCppVirtual(TRUE);

        Q3CString s;
        int index;

        // remove the useless "${type} " mainly to remove the space

        s = op->cppDecl();

        if (s.isEmpty())
            s = CppSettings::operationDecl();

        if ((index = s.find("${type} ")) != -1) {
            s.remove(index, 8);
            op->set_CppDecl(s);
        }

        s = op->cppDef();

        if (s.isEmpty())
            s = CppSettings::operationDef();

        if ((index = s.find("${type} ")) != -1) {
            s.remove(index, 8);
            op->set_CppDef(s);
        }
    }
}
Beispiel #9
0
bool ClassContainer::find_type(Q3CString type, UmlTypeSpec & typespec,
			       NDict<Class> & defined) {
  typespec.explicit_type = 0;
  
  if ((typespec.type = UmlClass::used(type)) != 0)
    return TRUE;
  
  Class * cl = defined[type];
  
  if (cl == 0) {
    int index = 0;
    
    while ((index = type.find('<', index)) != -1) {
      // goes after <...>
      int index2 = index + 1;
      unsigned level = 1;
    
      for (;;) {
	int c = type[index2++];
      
	if (c == '<')
	  level += 1;
	else if (c == 0)
	  // wrong template spec
	  return FALSE;
	else if ((c == '>') && (--level == 0)) {
	  break;
	}
      }
      
      if ((type[index2] != (char)0) && (defined[type.left(index2)] != (char)0))
	// explicit template
	index = index2;
      else if (defined[type.left(index)] != 0)
	// non explicit template, remove <>
	type.remove(index, index2 - index);
      else
	// unknown type
	return FALSE;

      typespec.type = 0;
      
      if ((cl = defined[type]) != 0)
	break;
    }
  }
  
  return ((cl != 0) && ((typespec.type = cl->get_uml()) != 0));
}
Beispiel #10
0
// remove first and last line in comment if non significant
Q3CString Lex::simplify_comment(Q3CString & comment)
{
  if (comment.isEmpty())
    return comment;
  
  const char * s = comment;
  const char * p = s;
  
  for (;;) {
    switch (*p) {
    case 0:
      return comment;
    case ' ':
    case '\t':
      p += 1;
      break;
    case '\n':
      comment.remove(0, p - s + 1);
      
      if (comment.isEmpty())
	return comment;
      
      s = comment;
      // no break
    default:
      p = s + comment.length() - 1;

      while (p != s) {
	switch(*p) {
	case ' ':
	case '\t':
	  p -= 1;
	  break;
	case '\n':
	  comment.resize(p - s + 1);
	  // no break
	default:
	  return comment;
	}
      }
      
      if (*p == '\n')
	comment = "";
      return comment;
    }
  }
}
Beispiel #11
0
void UmlAttribute::compute_dependency(Q3PtrList<CppRefType> & dependency,
				      const Q3CString & cl_stereotype,
				      bool all_in_h) {
  if ((cl_stereotype == "enum") || (cl_stereotype == "typedef"))
    return;
  
  Q3CString decl = cppDecl();
  
  int index;
  
  if ((index = decl.find("${static}")) != -1)
    decl.remove((unsigned) index, 9);
  if ((index = decl.find("${mutable}")) != -1)
    decl.remove((unsigned) index, 10);
  if ((index = decl.find("${volatile}")) != -1)
    decl.remove((unsigned) index, 11);
  if ((index = decl.find("${const}")) != -1)
    decl.remove((unsigned) index, 8);
  if ((index = decl.find("${multiplicity}")) != -1)
    decl.remove((unsigned) index, 15);
  if ((index = decl.find("${value}")) != -1)
    decl.remove((unsigned) index, 8);
  if ((index = decl.find("${h_value}")) != -1)
    decl.remove((unsigned) index, 10);
  if ((index = decl.find("${name}")) != -1)
    decl.remove((unsigned) index, 7);
  if ((index = decl.find("${stereotype}")) != -1)
    decl.replace((unsigned) index, 13,
		 CppSettings::relationAttributeStereotype(stereotype()));
  replace_alias(decl);

  if (!UmlClassMember::compute_dependency(dependency, decl, type(), all_in_h)) {
    write_trace_header();
    UmlCom::trace(Q3CString("&nbsp;&nbsp;&nbsp;&nbsp;<font color=\"red\"><b>type missing for attribute <i>")
		  + name() + "</i></b></font><br>");
    incr_error();
  }
}
Beispiel #12
0
void UmlClassMember::remove_preprocessor(Q3CString & s)
{
    int index = 0;

    while ((index = s.find('#', index)) != -1) {
        // remove all up to the end of line
        int index2 = index + 1;
        int index3;

        while ((index3 = s.find('\n', index2)) != -1) {
            // manage multi lines #define
            if (((const char *) s)[index3 - 1] != '\\')
                break;
            else
                index2 = index3 + 1;
        }

        // the \n is still here to have a separator
        if (index3 == -1)
            s.truncate(index);
        else
            s.remove(index, index3 - index);
    }
}
Beispiel #13
0
bool UmlOperation::new_one(Class * container, const Q3CString & name,
                           const Q3ValueList<FormalParameterList> & tmplts,
                           const Q3CString & oper_templ,
                           UmlTypeSpec & type, Q3CString str_actuals,
                           UmlClass * first_actual_class, Q3CString type_def,
                           aVisibility visibility,
                           bool finalp, bool abstractp, bool staticp,
                           bool nativep, bool strictfp, bool synchronizedp,
                           const Q3CString & array, Q3CString comment,
                           Q3CString description, Q3CString annotation
#ifdef ROUNDTRIP
                           , bool roundtrip, Q3PtrList<UmlItem> & expected_order
#endif
                          )
{
    // the "(" was read

#ifdef TRACE
    QLOG_INFO() <<"OPERATION '" << name << "'\n";
#endif

    UmlClass * cl = container->get_uml();
    UmlOperation * op;
#ifdef ROUNDTRIP
    bool may_roundtrip = roundtrip &&
                         (!container->from_libp() ||	(visibility != PrivateVisibility));
    UmlTypeSpec return_type;
    Q3ValueList<UmlParameter> params;
    Q3ValueList<UmlTypeSpec> exceptions;
    Q3CString body;

    if (may_roundtrip)
#else
    if (
# ifdef REVERSE
        container->from_libp() &&
# endif
        (visibility == PrivateVisibility))
#endif
        op = 0;
    else {
        op = UmlBaseOperation::create(cl, name);

        if (op == 0) {
            JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>")
                                 + name + "</i> in <i>" + cl->name()
                                 + "</i></b></font><br>");
            return FALSE;
        }

#ifndef ROUNDTRIP
# if defined(REVERSE)
        Statistic::one_operation_more();
# endif
#endif
    }

    Q3CString def;

#ifdef ROUNDTRIP
    if (may_roundtrip || (op != 0)) {
#else
    if (op != 0) {
        op->set_Visibility(visibility);
        if (staticp) op->set_isClassMember(TRUE);
        if (abstractp) op->set_isAbstract(TRUE);
        if (finalp) op->set_isJavaFinal(TRUE);
        if (synchronizedp) op->set_isJavaSynchronized(TRUE);
        if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation);
#endif

        def = JavaSettings::operationDef();

        int index;

        if (((index = def.find("${(}")) == -1) ||
                ((index = def.find("${)}", index + 4)) == -1) ||
                ((index = def.find("${throws}", index + 4)) == -1) ||
                (def.find("${body}", index + 9) == -1) ||
                ((index = def.find("${type}")) == -1)) {
            // use a definition where ${body] is not indented
            def = "  ${comment}${@}${visibility}${final}${static}${abstract}${synchronized}${type} ${name}${(}${)}${throws}${staticnl}{\n${body}}\n";
            index = def.find("${type}");
        }

        if (!array.isEmpty())
            def.insert(index + 7, (const char *)array);

        if (nativep) {
            def.insert(index, "native ");
            index += 7;

            // no body
            int index2 = def.find("${throws}", index+7);

            if (index2 != -1) {
                def.resize(index2 + 12);
                def[index2 + 9] = ';';
                def[index2 + 10] = '\n';
            }
        }

        if (strictfp) {
            def.insert(index, "strictfp ");
            index += 9;
        }

        if (! oper_templ.isEmpty())
            def.insert(index, (const char *)(oper_templ + " "));

        if (name == cl->name()) {
            // constructor, remove useless ${}
            if ((index = def.find("${static}")) != -1)
                def.remove(index, 9);
            if ((index = def.find("${type}")) != -1)
                def.remove(index, (((const char *) def)[index + 7] == ' ') ? 8 : 7);
            if ((index = def.find("${final}")) != -1)
                def.remove(index, 8);
            if ((index = def.find("${abstract}")) != -1)
                def.remove(index, 11);
        }

        if (type.type != 0) {
            UmlClass::manage_generic(def, type, str_actuals, "${type}");
#ifdef ROUNDTRIP
            return_type = type;
#else
            op->set_ReturnType(type);
#endif
        }
        else if (first_actual_class != 0) {
#ifndef ROUNDTRIP
            UmlTypeSpec return_type;
#endif

            return_type.type = first_actual_class;
            def.replace(def.find("${type}"), 7, type_def);
#ifndef ROUNDTRIP
            op->set_ReturnType(return_type);
#endif
        }
        else if (!type.explicit_type.isEmpty()) {
            // not a contructor
#ifdef ROUNDTRIP
            return_type = type;
#else
            op->set_ReturnType(type);
#endif
        }
    }

    // parameters

    unsigned rank = 0;
    UmlParameter param;

#ifdef ROUNDTRIP
    if (may_roundtrip)
        while (read_param(container, rank++, tmplts, param, def, FALSE))
            params.append(param);
    else
#endif
        while (read_param(container, rank, tmplts, param, def, op == 0)) {
            if ((op != 0) && ! op->addParameter(rank, param)) {
                JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add param <i>")
                                     + name + "</i> in <i>" + cl->name()
                                     + "</i></b></font><br>");
# ifdef TRACE
                QLOG_INFO() <<"ERROR cannot add param '" << param.name << "' type '" << param.type.Type() << '\n';
# endif
                return FALSE;
            }
            rank += 1;
        }

    Q3CString s = Lex::read_word();

    if (!s.isEmpty() && (*((const char *) s) == '[')) {
#ifdef ROUNDTRIP
        if (may_roundtrip)
#else
        if (op != 0)
#endif
            // do not place it at the same place
            def.insert(def.find("${type}") + 7, (const char *)s);
        s = Lex::read_word();
    }

    if (s.isEmpty()) {
        Lex::premature_eof();
        return FALSE;
    }

    if (s == "throws") {

        // throws

        rank = 0;

        for (;;) {
            if ((s = Lex::read_word()).isEmpty()) {
                Lex::premature_eof();
                return FALSE;
            }

#ifdef ROUNDTRIP
            if (may_roundtrip) {
                UmlTypeSpec typespec;

                container->compute_type(s, typespec, tmplts);
                exceptions.append(typespec);
            }
            else
#endif
                if (op != 0) {
                    UmlTypeSpec typespec;

                    container->compute_type(s, typespec, tmplts);
                    if (! op->addException(rank++, typespec)) {
# ifdef TRACE
                        QLOG_INFO() <<"cannot add exception " << s << '\n';
# endif
                        return FALSE;
                    }
                }

            if (((s = Lex::read_word()) == "{") || (s == ";"))
                break;

            if (s != ",") {
                Lex::error_near(s, " ',' expected");
                return FALSE;
            }
        }
    }

    // definition

    if (abstractp || nativep ||
            (cl->stereotype() == "interface") ||
            (cl->stereotype() == "@interface")) {
        if ((s == "default") && (cl->stereotype() == "@interface")) {
            int index = def.find("${)}");

            Lex::mark();
            s = Lex::read_word();
            if (s == "{") {
                int level = 1;
                char c;

                for (;;) {
                    if ((c = Lex::read_word_bis()) == 0)
                        return FALSE;
                    else if (c == '{')
                        level += 1;
                    else if ((c == '}') && (--level == 0))
                        break;
                }
                s = Lex::region();
            }

            def.insert(index + 4, (const char *)(" default" + s));
            s = Lex::read_word();
        }
        if (s != ";") {
            Lex::error_near(s, " ';' expected");
            return FALSE;
        }
#ifdef REVERSE
# ifndef ROUNDTRIP
        if ((op != 0) && !container->from_libp())
            op->set_JavaBody(0);
# endif
#endif
    }
    else if (s != "{") {
        Lex::error_near(s, " '{' expected");
        return FALSE;
    }
    else {
        Lex::mark();

        // goto the end of the body

#ifndef ROUNDTRIP
        Q3CString body;
#endif
        int level = 1;	// '{' already read
        char c;

        for (;;) {
            if ((c = Lex::read_word_bis()) == 0)
                return FALSE;
            else if (c == '{')
                level += 1;
            else if ((c == '}') && (--level == 0))
                break;
        }

#ifdef REVERSE
        if (
# ifdef ROUNDTRIP
            may_roundtrip || (op != 0)
# else
            (op != 0) && !container->from_libp()
# endif
        ) {
            body = Lex::region();
            body.truncate(body.length() - 1);	// remove }

            // remove fist \n
            if (*((const char *) body) == '\n')
                body.remove(0, 1);

            // remove last spaces and tabs
            int ln = body.length();

            while (ln && ((body[ln - 1] == ' ') || (body[ln - 1] == '\t')))
                ln -= 1;
            body.truncate(ln);
            if (!body.isEmpty() && (body[ln - 1] != '\n'))
                body += "\n";

# ifndef ROUNDTRIP
            op->set_JavaBody(body);
            op->set_JavaContextualBodyIndent(FALSE);
# endif
        }
#endif
    }

#ifdef ROUNDTRIP
    if (may_roundtrip) {
        if (((op = already_exist_from_id(container, body)) != 0) ||
                ((op = already_exist(container, name, params)) != 0)) {
            // update already existing operation
            op->set_usefull();

            {
                // remove \r in case of preserve body
                Q3CString current_body = op->javaBody();
                int index = 0;

                while ((index = current_body.find('\r', index)) != -1)
                    current_body.remove(index, 1);

                if (nequal(current_body, body)) {
                    container->set_updated();
                    op->set_JavaBody(body);
                    op->set_JavaContextualBodyIndent(FALSE);
                }
            }
            if (op->visibility() != visibility) {
                container->set_updated();
                op->set_Visibility(visibility);
            }
            if (op->isClassMember() != staticp) {
                container->set_updated();
                op->set_isClassMember(staticp);
            }
            if (op->isAbstract() != abstractp) {
                container->set_updated();
                op->set_isAbstract(abstractp);
            }
            if (op->isJavaFinal() != finalp) {
                container->set_updated();
                op->set_isJavaFinal(finalp);
            }
            if (op->isJavaSynchronized() != synchronizedp) {
                container->set_updated();
                op->set_isJavaSynchronized(synchronizedp);
            }
            if (nequal(op->javaAnnotations(), annotation)) {
                container->set_updated();
                op->set_JavaAnnotations(annotation);
            }

            if (!op->returnType().equal(return_type)) {
                container->set_updated();
                op->set_ReturnType(return_type);
            }

            Q3ValueList<UmlParameter>::Iterator itp1;
            const Q3ValueList<UmlParameter> old_params = op->params();
            Q3ValueList<UmlParameter>::ConstIterator itp2;

            for (rank = 0, itp1 = params.begin(), itp2 = old_params.begin();
                    (itp1 != params.end()) && (itp2 != old_params.end());
                    ++itp1, ++itp2, rank += 1) {
                UmlParameter & p1 = *itp1;
                const UmlParameter & p2 = *itp2;

                if ((p1.name != p2.name) ||
                        nequal(p1.default_value, p2.default_value) ||
                        !p1.type.equal(p2.type)) {
                    if (p1.dir != InputDirection)
                        p1.dir = p2.dir;
                    op->replaceParameter(rank, p1);
                    container->set_updated();
                }
                else if ((p1.dir == InputDirection) && (p2.dir != InputDirection)) {
                    op->replaceParameter(rank, p1);
                    container->set_updated();
                }
            }

            if (itp1 != params.end()) {
                // have missing params
                container->set_updated();
                do {
                    op->addParameter(rank, *itp1);
                    itp1++;
                    rank += 1;
                } while (itp1 != params.end());
            }
            else if (itp2 != old_params.end()) {
                // have extra params
                container->set_updated();
                do {
                    op->removeParameter(rank);
                    itp2++;
                } while (itp2 != old_params.end());
            }

            Q3ValueList<UmlTypeSpec>::ConstIterator ite1;
            const Q3ValueList<UmlTypeSpec> old_exceptions = op->exceptions();
            Q3ValueList<UmlTypeSpec>::ConstIterator ite2;

            for (rank = 0, ite1 = exceptions.begin(), ite2 = old_exceptions.begin();
                    (ite1 != exceptions.end()) && (ite2 != old_exceptions.end());
                    ++ite1, ++ite2, rank += 1) {
                const UmlTypeSpec & e1 = *ite1;

                if (!e1.equal(*ite2)) {
                    op->replaceException(rank, e1);
                    container->set_updated();
                }
            }

            if (ite1 != exceptions.end()) {
                // have missing exceptions
                container->set_updated();
                do {
                    op->addException(rank, *ite1);
                    ite1++;
                    rank += 1;
                } while (ite1 != exceptions.end());
            }
            else if (ite2 != old_exceptions.end()) {
                // have extra exceptions
                container->set_updated();
                do {
                    op->removeException(rank);
                    ite2++;
                } while (ite2 != old_exceptions.end());
            }

            if (neq(def, op->javaDecl())) {
                container->set_updated();
                op->set_JavaDecl(def);
            }

            Lex::clear_comments();	// params & body comments
            Lex::finish_line();

            if (def.find("${description}") != -1) {
                if (nequal(op->description(), description)) {
                    container->set_updated();
                    op->set_Description(description);
                }
            }
            else if (nequal(op->description(), Lex::simplify_comment(comment))) {
                op->set_Description(comment); // comment was set
                container->set_updated();
            }

            expected_order.append(op);

            return TRUE;
        }

        // operation doesn't yet exist
        container->set_updated();
        op = UmlBaseOperation::create(cl, name);

        if (op == 0) {
            JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>")
                                 + name + "</i> in <i>" + cl->name()
                                 + "</i></b></font><br>");
            throw 0;
        }

        expected_order.append(op);

        Q3ValueList<UmlParameter>::ConstIterator itp;

        for (rank = 0, itp = params.begin(); itp != params.end(); ++itp)
            op->addParameter(rank++, *itp);

        Q3ValueList<UmlTypeSpec>::ConstIterator ite;

        for (rank = 0, ite = exceptions.begin(); ite != exceptions.end(); ++ite)
            op->addException(rank++, *ite);
    }

    if (op != 0) {
        op->set_JavaContextualBodyIndent(FALSE);
        op->set_Visibility(visibility);
        if (staticp) op->set_isClassMember(TRUE);
        if (abstractp) op->set_isAbstract(TRUE);
        if (finalp) op->set_isJavaFinal(TRUE);
        if (synchronizedp) op->set_isJavaSynchronized(TRUE);
        if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation);
        op->set_JavaBody(body);
        op->set_ReturnType(return_type);
        if (def != JavaSettings::operationDef())
            op->set_JavaDecl(def);
    }
#else
    if ((op != 0) && (def != JavaSettings::operationDef()))
        op->set_JavaDecl(def);
#endif

    Lex::clear_comments();	// params & body comments
    Lex::finish_line();
    if (!comment.isEmpty())
        if (op != 0)
            op->set_Description((def.find("${description}") != -1)
                                ? description : Lex::simplify_comment(comment));

    return TRUE;
}

bool UmlOperation::read_param(Class * container, unsigned rank,
                              const Q3ValueList<FormalParameterList> & tmplts,
                              UmlParameter & param, Q3CString & def, bool bypass)
{
#ifdef TRACE
    QLOG_INFO() <<"UmlOperation::manage_param " << rank << "\n";
#endif

    bool finalp = FALSE;
    bool in = FALSE;
    bool ellipsis = FALSE;
    Q3CString array;
    bool type_read = FALSE;
    Q3ValueList<UmlTypeSpec> actuals;
    Q3CString str_actuals;
    Q3CString annotation;

    param.name = param.default_value = 0;

    Q3CString s = Lex::read_word();

#ifdef TRACE
    QLOG_INFO() <<"commence par " << s << '\n';
#endif

    if (s == ")")
        return FALSE;

    for (;;) {
        if (s.isEmpty()) {
            Lex::premature_eof();
            return FALSE;
        }
        else if (s == "final")
            finalp = TRUE;
        else if ((s == "void") || (s == "byte") || (s == "char") ||
                 (s == "short") || (s == "int") || (s == "long") ||
                 (s == "float") || (s == "double")) {
            if (type_read) {
                Lex::error_near(s);
                return FALSE;
            }
            param.type.type = 0;
            param.type.explicit_type = s;
            type_read = TRUE;
            in = TRUE;
        }
        else if ((s == ")") || (s == ",")) {
            if (param.name.isEmpty() && !type_read) {
                Lex::error_near(s);
                return FALSE;
            }
            if (s == ")")
                Lex::unread_word(s);

            if (! bypass) {
                param.dir = (finalp || in)
                            ? InputDirection : InputOutputDirection;

                Q3CString s;

                if (rank != 0)
                    s = ", ";
                if (! annotation.isEmpty())
                    s += annotation + " ";
                if (finalp)
                    s += "final ";
                if ((param.type.type != 0) &&
                        !param.type.explicit_type.isEmpty())
                    s += param.type.explicit_type;
                else {
                    s += "${t";
                    s += Q3CString().setNum(rank);
                    s += "}";
                    if (param.type.type != 0)
                        s += str_actuals;
                }
                s += array;
                s += (ellipsis) ? " ... ${p": " ${p";
                s += Q3CString().setNum(rank);
                s += "}";
                def.insert(def.find("${)}"), 	// cannot be -1
                           (const char *)s);
            }
            return TRUE;
        }
        else if (Lex::identifierp(s)) {
            if (!type_read) {
                while (s.at(s.length() - 1) == '.') {
                    // type on several lines, managed in this case
                    Q3CString s2 = Lex::read_word();

                    if (Lex::identifierp(s2))
                        s += s2;
                    else {
                        Lex::error_near(s, " identifier expected");
                        return FALSE;
                    }
                }
#ifdef TRACE
                QLOG_INFO() <<"type = '" << s << "...'\n";
#endif
                if (! bypass) {
                    Q3CString dummy;

                    container->read_type(param.type, 0, tmplts, 0, str_actuals, s,
                                         0, dummy, dummy);

                    if (param.type.explicit_type == "String")
                        // at least for it !
                        in = TRUE;
                }
                else
                    Lex::bypass_type(s);

                type_read = TRUE;
            }
            else if (param.name.isEmpty()) {
                if (s == "...")
                    ellipsis = TRUE;
                else {
                    param.name = s;
#ifdef TRACE
                    QLOG_INFO() <<"name = '" << param.name << "'\n";
#endif
                }
            }
            else {
                Lex::error_near(s);
#ifdef TRACE
                QLOG_INFO() <<"ERROR '" << s << "' alors qu a deja le type et le nom '" << param.name << "'\n";
#endif
                return FALSE;
            }
        }
        else if (*((const char *) s) == '@')
            annotation = s;
        else if (*((const char *) s) == '[') {
            in = FALSE;
            array = s;
        }
        else {
            Lex::error_near(s);
#ifdef TRACE
            QLOG_INFO() <<"ERROR : '" << s << "'\n";
#endif
            return FALSE;
        }

        s = Lex::read_word();
    }
}
Beispiel #14
0
void UmlClass::compute_dependency(Q3PtrList<CppRefType> & dependencies,
				  const Q3CString &, bool all_in_h) {
  Q3PtrVector<UmlItem> ch = children();
  const Q3CString stereotype = cpp_stereotype();
  bool a_typedef = (stereotype == "typedef");
  bool an_enum = (stereotype == "enum");
  const Q3ValueList<UmlFormalParameter> formals = this->formals();
  const Q3ValueList<UmlActualParameter> actuals = this->actuals();  
  
  if (!formals.isEmpty())
    // template class, force depend in h
    all_in_h = TRUE;
  
  for (unsigned index = 0; index != ch.size(); index += 1) {
    if (ch[index]->kind() != aNcRelation) {
      UmlClassItem * it = (UmlClassItem *) ch[index];
      
      if (! it->cppDecl().isEmpty())
	it->compute_dependency(dependencies, stereotype, all_in_h);
    }
  }
  
  if (an_enum && (!formals.isEmpty() || !actuals.isEmpty())) {
    write_trace_header();
    UmlCom::trace("&nbsp;&nbsp;&nbsp;&nbsp;<font color=\"red\"><b><i>template enum</i></b></font><br>");
    incr_warning();
  }
  else if (a_typedef && !formals.isEmpty()) {
    write_trace_header();
    UmlCom::trace("&nbsp;&nbsp;&nbsp;&nbsp;<font color=\"red\"><b><i>template typedef</i></b></font><br>");
    incr_warning();
  }
  else {
    Q3ValueList<UmlFormalParameter>::ConstIterator itf;
    
    for (itf = formals.begin(); itf != formals.end(); ++itf)
      CppRefType::remove((*itf).name(), dependencies);
  
    Q3ValueList<UmlActualParameter>::ConstIterator ita;
    
    for (ita = actuals.begin(); ita != actuals.end(); ++ita)
      UmlClassMember::compute_dependency(dependencies, "${type}",
					 (*ita).value(), all_in_h);
    
    if (a_typedef) {
      Q3CString decl = cppDecl();
      int index;
      
      remove_comments(decl);
      if ((index = decl.find("${name}")) != -1)
	decl.remove((unsigned) index, 7);
      replace_alias(decl);

      UmlClassMember::compute_dependency(dependencies, decl,
					 baseType(), all_in_h);
    }
  }
  
  if ((associatedArtifact() == 0) ||
      (associatedArtifact()->associatedClasses().count() == 1))
    CppRefType::remove(this, dependencies);
  else
    CppRefType::force_ref(this, dependencies);
}
Beispiel #15
0
bool UmlOperation::new_one(Class * container, aVisibility visibility,
			   bool finalp, bool abstractp, bool staticp,
			   Q3CString comment, Q3CString description)
{
  // 'function' was read, it is followed by :
  // ['&'] name'(' {'array' | <classname>] ['&'] '$'<varname> ['=' <value>]}* ')' '{' ... '}'
  Q3CString s = Lex::read_word();
  bool refp;
  
  if (s == "&") {
    refp = TRUE;
    s = Lex::read_word();
  }
  else
    refp = FALSE;
  
  if (s.isEmpty()) {
    Lex::premature_eof();
    return FALSE;
  }
    
  Q3CString name = s;
  
#ifdef TRACE
  QLOG_INFO() <<"OPERATION '" << name << "'\n";
#endif
  
  s = Lex::read_word();
  if (s != "(") {
    Lex::syntax_error("'(' expected rather than '" + s + "'");
    return FALSE;
  }
  
  UmlClass * cl = container->get_uml();
  UmlOperation * op;
  
#ifndef REVERSE
  if (visibility == PrivateVisibility)
    op = 0;
  else
#endif
  {
    op = UmlBaseOperation::create(cl, name);
    
    if (op == 0) {
      PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>")
			   + name + "</i> in <i>" + cl->name() 
			   + "</i></b></font><br>");  
      return FALSE;
    }
    
#ifdef REVERSE
    Statistic::one_operation_more();
#endif
  }
    
  Q3CString def;
    
  if (op != 0) {
    op->set_Visibility(visibility);
    if (staticp) op->set_isClassMember(TRUE);
    if (finalp) op->set_isPhpFinal(TRUE);
  
    def = PhpSettings::operationDef();
  
    int index;
    
    if (((index = def.find("${(}")) == -1) ||
	(def.find("${)}", index + 4) == -1) ||
	((index = def.find("${name}")) == -1) ||
	(def.find("${body}") == -1)) {
      // use a definition where ${body] is not indented
      def = "  ${comment}${final}${visibility}${abstract}${static}function ${name}${(}${)}\n{\n  ${body}}\n";
      index = def.find("${name}");
    }
    
    if (refp)
      def.insert(index, "&");
    
    if ((name == cl->name()) || (name == "__construct")) {
      // constructor, remove useless ${}
      if ((index = def.find("${static}")) != -1)
	def.remove(index, 9);
      if ((index = def.find("${final}")) != -1)
	def.remove(index, 8);
      if ((index = def.find("${abstract}")) != -1)
	def.remove(index, 11);
    }
    
    if (abstractp) {
      op->set_isAbstract(TRUE);
      
      def = def.left(def.find("${)}") + 4) + ";";
    }
  }
  
  // parameters
  
  unsigned rank = 0;
  UmlParameter param;
  
  while (read_param(container, rank, param, def, op == 0)) {
    if ((op != 0) && ! op->addParameter(rank++, param)) {
      PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add param <i>")
			   + name + "</i> in <i>" + cl->name() 
			   + "</i></b></font><br>");  
#ifdef TRACE
      QLOG_INFO() <<"ERROR cannot add param '" << param.name << '\n';
#endif
      return FALSE;
    }
  }
  
  s = Lex::read_word();
  
  if (s.isEmpty()) {
    Lex::premature_eof();
    return FALSE;
  }
    
  // definition
  
  if (abstractp || (cl->stereotype() == "interface")) {
    if (s != ";") {
      Lex::error_near(s);
      return FALSE;
    }
#ifdef REVERSE
    if (op != 0)
      op->set_PhpBody(0);
#endif
  }
  else if (s != "{") {
    Lex::error_near(s);
    return FALSE;
  }
  else {
    Lex::mark();
    
    // goto the end of the body
    
    char c;
    int level = 1;	// '{' already read
    
    for (;;) {
      if ((c = Lex::read_word_bis()) == 0)
	return FALSE;
      else if (c == '{')
	level += 1;
      else if ((c == '}') && (--level == 0))
	break;
    }
    
#ifdef REVERSE
    if (op != 0) {
      Q3CString e = Lex::region();
      
      e.truncate(e.length() - 1);	// remove }

      // remove fist \n
      if (*((const char *) e) == '\n')
	e.remove(0, 1);
      
      // remove last spaces and tabs
      int ln = e.length();
      
      while (ln && ((e[ln - 1] == ' ') || (e[ln - 1] == '\t')))
	ln -= 1;
      e.truncate(ln);
      
      op->set_PhpBody(e);
      op->set_PhpContextualBodyIndent(FALSE);
    }
#endif
  }
  
  if ((op != 0) && (def != op->phpDecl()))
    op->set_PhpDecl(def);
  
  Lex::clear_comments();	// params & body comments
  Lex::finish_line();
  
  if ((op != 0) && !comment.isEmpty()) {
    s = (def.find("${description}") != -1) ? description : comment;
    
    UmlTypeSpec t;
    int index1;
    
    if (! (t.explicit_type = value_of(s, "@return", index1)).isEmpty()) {
      op->set_ReturnType(t);
      s.replace(index1, t.explicit_type.length(), "${type}");
    }
    
    Q3ValueList<UmlParameter> l = op->params();
    unsigned nparams = l.count();

    if (nparams != 0) {
      Q3CString varname;
      int index2;
      char xn[16];

      index1 = 0;
      rank = 0;
      
      while (!((t.explicit_type = value_of(s, "@param", index1, varname, index2))
	       .isEmpty())) {
	if (varname.isEmpty() || (varname[0] != '$')) {
	  if (rank < nparams) {
	    UmlParameter & p = l[rank];
	    
	    p.type = t;
	    op->replaceParameter(rank, p);
	  }
	}
	else {
	  varname = varname.mid(1);
	  
	  Q3ValueList<UmlParameter>::Iterator it;
	  
	  for (it = l.begin(), rank = 0; it != l.end(); ++it, rank += 1) {
	    if ((*it).name == varname) {
	      (*it).type = t;
	      op->replaceParameter(rank, *it);
	      sprintf(xn, "${p%d}", rank);
	      s.replace(index2, varname.length() + 1, xn);
	      break;
	    }
	  }
	}
	sprintf(xn, "${t%d}", rank++);
	s.replace(index1, t.explicit_type.length(), xn);
      }
    }
    op->set_Description(s);
  }
  
  return TRUE;
}