diff --git a/OMCompiler/Compiler/NFFrontEnd/NFClass.mo b/OMCompiler/Compiler/NFFrontEnd/NFClass.mo index 03f773d8a76..be3773753f5 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFClass.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFClass.mo @@ -655,6 +655,7 @@ constant Prefixes DEFAULT_PREFIXES = Prefixes.PREFIXES( algorithm isEnum := match cls case PARTIAL_BUILTIN(ty = Type.ENUMERATION()) then true; + case INSTANCED_BUILTIN(ty = Type.ENUMERATION()) then true; case EXPANDED_DERIVED() then isEnumeration(InstNode.getClass(cls.baseClass)); case TYPED_DERIVED() then isEnumeration(InstNode.getClass(cls.baseClass)); else false; diff --git a/OMCompiler/Compiler/Script/NFApi.mo b/OMCompiler/Compiler/Script/NFApi.mo index c512e9f5c00..e1302b0c9d2 100644 --- a/OMCompiler/Compiler/Script/NFApi.mo +++ b/OMCompiler/Compiler/Script/NFApi.mo @@ -842,10 +842,16 @@ uniontype InstanceTree Boolean isExtends; end CLASS; + record BUILTIN_BASE_CLASS + String name; + end BUILTIN_BASE_CLASS; + record EMPTY end EMPTY; end InstanceTree; +constant InstanceTree ENUM_BASE = InstanceTree.BUILTIN_BASE_CLASS("enumeration"); + function getModelInstance input Absyn.Path classPath; input String modifier; @@ -955,7 +961,7 @@ algorithm cls_node := InstNode.resolveInner(node); cls := InstNode.getClass(cls_node); - if not isDerived and Class.isOnlyBuiltin(cls) then + if not isDerived and Class.isOnlyBuiltin(cls) and not Class.isEnumeration(cls) then tree := InstanceTree.EMPTY(); return; end if; @@ -976,7 +982,7 @@ algorithm InstanceTree.CLASS(node, elems, isDerived); case (_, ClassTree.FLAT_TREE()) - then InstanceTree.CLASS(node, {}, isDerived); + then InstanceTree.CLASS(node, if InstNode.isEnumerationType(cls_node) then {ENUM_BASE} else {}, isDerived); else algorithm @@ -1099,7 +1105,7 @@ algorithm json := JSON.addPairNotNull("dims", dumpJSONClassDims(node, def), json); json := JSON.addPair("restriction", - JSON.makeString(Restriction.toString(InstNode.restriction(node))), json); + JSON.makeString(SCodeDump.restrictionStringPP(SCodeUtil.getClassRestriction(def))), json); json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(def, InstNode.parent(node)), json); @@ -1232,6 +1238,7 @@ algorithm case InstanceTree.CLASS(isExtends = true) then dumpJSONExtends(e, isDeleted); case InstanceTree.CLASS() then dumpJSONReplaceableClass(e.node, scope); case InstanceTree.COMPONENT() then dumpJSONComponent(e.node, e.binding, e.cls); + case InstanceTree.BUILTIN_BASE_CLASS() then dumpJSONBuiltinBaseClass(e.name); else JSON.makeNull(); end match; @@ -1246,6 +1253,7 @@ function dumpJSONExtends output JSON json = JSON.makeNull(); protected InstNode node; + Class cls; SCode.Element cls_def, ext_def; SCode.Mod mod; algorithm @@ -1257,13 +1265,22 @@ algorithm json := dumpJSONSCodeMod(getExtendsModifier(ext_def, node), node, json); json := dumpJSONCommentOpt(SCodeUtil.getElementComment(ext_def), node, json); - if Class.isOnlyBuiltin(InstNode.getClass(node)) then + cls := InstNode.getClass(node); + if Class.isOnlyBuiltin(cls) and not Class.isEnumeration(cls) then json := JSON.addPair("baseClass", JSON.makeString(InstNode.name(node)), json); else json := JSON.addPair("baseClass", dumpJSONInstanceTree(ext, node, root = false, isDeleted = isDeleted), json); end if; end dumpJSONExtends; +function dumpJSONBuiltinBaseClass + input String name; + output JSON json = JSON.makeNull(); +algorithm + json := JSON.addPair("$kind", JSON.makeString("extends"), json); + json := JSON.addPair("baseClass", JSON.makeString(name), json); +end dumpJSONBuiltinBaseClass; + function getExtendsModifier input SCode.Element definition; input InstNode node; @@ -1377,7 +1394,7 @@ function dumpJSONComponentType output JSON json; algorithm json := match (cls, Type.arrayElementType(ty)) - case (_, Type.ENUMERATION()) then dumpJSONEnumType(node); + case (_, Type.ENUMERATION()) then dumpJSONEnumType(cls, node); case (_, Type.UNKNOWN()) then dumpJSONSCodeElementType(InstNode.definition(node)); case (InstanceTree.CLASS(), _) then dumpJSONInstanceTree(cls, node, isDeleted = isDeleted); else dumpJSONTypeName(ty); @@ -1401,23 +1418,31 @@ algorithm end dumpJSONSCodeElementType; function dumpJSONEnumType + input InstanceTree tree; input InstNode enumNode; output JSON json; protected InstNode node = InstNode.resolveInner(InstNode.classScope(enumNode)); SCode.Element def; array comps; + JSON json_elems, json_ext; + list elems; algorithm def := InstNode.definition(node); json := JSON.makeNull(); json := JSON.addPair("name", dumpJSONNodePath(node), json); json := JSON.addPairNotNull("dims", dumpJSONClassDims(node, def), json); - json := JSON.addPair("restriction", JSON.makeString("enumeration"), json); + json := JSON.addPair("restriction", + JSON.makeString(SCodeDump.restrictionStringPP(SCodeUtil.getClassRestriction(def))), json); json := dumpJSONCommentOpt(SCodeUtil.getElementComment(def), node, json); + InstanceTree.CLASS(elements = elems) := tree; + json_elems := dumpJSONElements(elems, node, false); + comps := ClassTree.getComponents(Class.classTree(InstNode.getClass(node))); - json := JSON.addPair("elements", dumpJSONEnumTypeLiterals(comps, InstNode.parent(node)), json); + json_elems := dumpJSONEnumTypeLiterals(comps, InstNode.parent(node), json_elems); + json := JSON.addPair("elements", json_elems, json); json := JSON.addPair("source", dumpJSONSourceInfo(InstNode.info(node)), json); end dumpJSONEnumType; @@ -1425,7 +1450,7 @@ end dumpJSONEnumType; function dumpJSONEnumTypeLiterals input array literals; input InstNode scope; - output JSON json = JSON.emptyArray(); + input output JSON json = JSON.emptyArray(); algorithm for i in 6:arrayLength(literals) loop json := JSON.addElement(dumpJSONEnumTypeLiteral(literals[i], scope), json); diff --git a/OMEdit/OMEditLIB/Modeling/Model.cpp b/OMEdit/OMEditLIB/Modeling/Model.cpp index affa5f59e4d..7d945dce464 100644 --- a/OMEdit/OMEditLIB/Modeling/Model.cpp +++ b/OMEdit/OMEditLIB/Modeling/Model.cpp @@ -1184,7 +1184,7 @@ namespace ModelInstance bool Model::isEnumeration() const { - return (mRestriction.compare(QStringLiteral("enumeration")) == 0); + return getRootType() == QLatin1String("enumeration"); } bool Model::isType() const diff --git a/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.cpp b/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.cpp index 37e20544c1a..6d6d3035005 100644 --- a/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.cpp +++ b/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.cpp @@ -487,72 +487,24 @@ void GraphicsView::drawConnections(ModelInstance::Model *pModelInstance, bool in // if connection is valid and has line annotation if (pConnection->getStartConnector() && pConnection->getEndConnector() && pConnection->getAnnotation()->getLine() && !connectionExists(pConnection->getStartConnector()->getName(), pConnection->getEndConnector()->getName(), inherited)) { - // get start and end elements - QStringList startElementList = pConnection->getStartConnector()->getNameParts(); - QStringList endElementList = pConnection->getEndConnector()->getNameParts(); - // get start element - Element *pStartElement = 0; - if (startElementList.size() > 0) { - QString startElementName = startElementList.at(0); - if (startElementName.contains("[")) { - startElementName = startElementName.mid(0, startElementName.indexOf("[")); - } - pStartElement = getElementObject(startElementName); - } - // get start connector - Element *pStartConnectorElement = 0; - Element *pEndConnectorElement = 0; - if (pStartElement) { - // if a element type is connector then we only get one item in startElementList - // check the startElementlist - // if conditional connector or condition is false or if type is missing then connect with the red cross box - if (startElementList.size() < 2 || pStartElement->isExpandableConnector() || !pStartElement->getModelComponent()->getCondition() || pStartElement->getModel()->isMissing()) { - pStartConnectorElement = pStartElement; - } else { - // look for port from the parent element - QString startElementName = startElementList.at(1); - if (startElementName.contains("[")) { - startElementName = startElementName.mid(0, startElementName.indexOf("[")); - } - pStartConnectorElement = mpModelWidget->getConnectorElement(pStartElement, startElementName); - } - } + //// get start and end elements + auto pStartConnectorElement = getConnectorElement(pConnection->getStartConnector()); // show error message if start element is not found. if (!pStartConnectorElement) { - MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, GUIMessages::getMessage(GUIMessages::UNABLE_FIND_COMPONENT_IN_CONNECTION_NEW) - .arg(pConnection->getStartConnector()->getName()).arg(pConnection->toString()) - .arg(mpModelWidget->getLibraryTreeItem()->getNameStructure()), Helper::scriptingKind, Helper::errorLevel)); + MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, + GUIMessages::getMessage(GUIMessages::UNABLE_FIND_COMPONENT_IN_CONNECTION_NEW) + .arg(pConnection->getStartConnector()->getName()).arg(pConnection->toString()) + .arg(mpModelWidget->getLibraryTreeItem()->getNameStructure()), Helper::scriptingKind, Helper::errorLevel)); continue; } - // get end element - Element *pEndElement = 0; - if (endElementList.size() > 0) { - QString endElementName = endElementList.at(0); - if (endElementName.contains("[")) { - endElementName = endElementName.mid(0, endElementName.indexOf("[")); - } - pEndElement = getElementObject(endElementName); - } - // get the end connector - if (pEndElement) { - // if a element type is connector then we only get one item in endElementList - // check the endElementList - // if conditional connector or condition is false or if type is missing then connect with the red cross box - if (endElementList.size() < 2 || pEndElement->isExpandableConnector() || !pEndElement->getModelComponent()->getCondition() || pEndElement->getModel()->isMissing()) { - pEndConnectorElement = pEndElement; - } else { - QString endElementName = endElementList.at(1); - if (endElementName.contains("[")) { - endElementName = endElementName.mid(0, endElementName.indexOf("[")); - } - pEndConnectorElement = mpModelWidget->getConnectorElement(pEndElement, endElementName); - } - } + + auto pEndConnectorElement = getConnectorElement(pConnection->getEndConnector()); // show error message if end element is not found. if (!pEndConnectorElement) { - MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, GUIMessages::getMessage(GUIMessages::UNABLE_FIND_COMPONENT_IN_CONNECTION_NEW) - .arg(pConnection->getEndConnector()->getName()).arg(pConnection->toString()) - .arg(mpModelWidget->getLibraryTreeItem()->getNameStructure()), Helper::scriptingKind, Helper::errorLevel)); + MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, + GUIMessages::getMessage(GUIMessages::UNABLE_FIND_COMPONENT_IN_CONNECTION_NEW) + .arg(pConnection->getEndConnector()->getName()).arg(pConnection->toString()) + .arg(mpModelWidget->getLibraryTreeItem()->getNameStructure()), Helper::scriptingKind, Helper::errorLevel)); continue; } @@ -3131,8 +3083,42 @@ bool GraphicsView::updateElementConnectorSizingParameter(GraphicsView *pGraphics return false; } -/*! - * \brief GraphicsView::getConnectorName +/*! * \brief GraphicsView::getConnectorElement + * Returns the element associated with a Connector. + * \param pConnector + */ +Element* GraphicsView::getConnectorElement(ModelInstance::Connector *pConnector) +{ + QStringList elementList = pConnector->getNameParts(); + Element *element = nullptr; + + // Get element. + if (elementList.size() > 0) { + QString elementName = elementList.front(); + elementName = elementName.left(elementName.indexOf('[')); + element = getElementObject(elementName); + } + + // Get connector element. + Element *connectorElement = nullptr; + if (element) { + // If an element type is connector then we only get one item in elementList + // Check the elementList + // If conditional connector or condition is false or if type is missing then connect with the red cross box + if (elementList.size() < 2 || element->isExpandableConnector() || !element->getModelComponent()->getCondition() || element->getModel()->isMissing()) { + connectorElement = element; + } else { + // Look for port from the parent element + QString elementName = elementList.at(1); + elementName = elementName.left(elementName.indexOf('[')); + connectorElement = mpModelWidget->getConnectorElement(element, elementName); + } + } + + return connectorElement; +} + +/*! * \brief GraphicsView::getConnectorName * Returns the name of the connector element as a string. * \param pConnector */ diff --git a/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.h b/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.h index 4fe9040b0fd..46633434fe0 100644 --- a/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.h +++ b/OMEdit/OMEditLIB/Modeling/ModelWidgetContainer.h @@ -369,7 +369,8 @@ class GraphicsView : public QGraphicsView Element* connectorElementAtPosition(QPoint position); Element* stateElementAtPosition(QPoint position); static bool updateElementConnectorSizingParameter(GraphicsView *pGraphicsView, QString className, Element *pElement); - QString getConnectorName(Element *connector); + Element* getConnectorElement(ModelInstance::Connector *pConnector); + QString getConnectorName(Element *pConnector); bool handleDoubleClickOnComponent(QMouseEvent *event); void uncheckAllShapeDrawingActions(); void setOriginAdjustAndInitialize(ShapeAnnotation* shapeAnnotation); diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceEnum1.mos b/testsuite/openmodelica/instance-API/GetModelInstanceEnum1.mos index 89c77ff1f9d..cc743d6c592 100644 --- a/testsuite/openmodelica/instance-API/GetModelInstanceEnum1.mos +++ b/testsuite/openmodelica/instance-API/GetModelInstanceEnum1.mos @@ -29,13 +29,17 @@ getModelInstance(M, prettyPrint=true); // \"name\": \"analogFil\", // \"type\": { // \"name\": \"AnalogFilter\", -// \"restriction\": \"enumeration\", +// \"restriction\": \"type\", // \"comment\": \"Enumeration defining the method of filtering\", // \"annotation\": { // \"Evaluate\": true // }, // \"elements\": [ // { +// \"$kind\": \"extends\", +// \"baseClass\": \"enumeration\" +// }, +// { // \"$kind\": \"component\", // \"name\": \"CriticalDamping\", // \"comment\": \"Filter with critical damping\" diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceEnum2.mos b/testsuite/openmodelica/instance-API/GetModelInstanceEnum2.mos index 1a20063a670..d780c5c6b64 100644 --- a/testsuite/openmodelica/instance-API/GetModelInstanceEnum2.mos +++ b/testsuite/openmodelica/instance-API/GetModelInstanceEnum2.mos @@ -26,9 +26,29 @@ getModelInstance(M, prettyPrint=true); // \"name\": \"e\", // \"type\": { // \"name\": \"E2\", -// \"restriction\": \"enumeration\", +// \"restriction\": \"type\", // \"elements\": [ // { +// \"$kind\": \"extends\", +// \"baseClass\": { +// \"name\": \"E1\", +// \"restriction\": \"type\", +// \"elements\": [ +// { +// \"$kind\": \"extends\", +// \"baseClass\": \"enumeration\" +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 3, +// \"columnStart\": 5, +// \"lineEnd\": 3, +// \"columnEnd\": 47 +// } +// } +// }, +// { // \"$kind\": \"component\", // \"name\": \"a\", // \"comment\": \"a\"