| 804 | } |
| 805 | |
| 806 | std::string |
| 807 | PropertyExpressionEngine::validateExpression(const ObjectIdentifier& path, |
| 808 | std::shared_ptr<const Expression> expr) const |
| 809 | { |
| 810 | std::string error; |
| 811 | ObjectIdentifier usePath(canonicalPath(path)); |
| 812 | |
| 813 | if (validator) { |
| 814 | error = validator(usePath, expr); |
| 815 | if (!error.empty()) { |
| 816 | return error; |
| 817 | } |
| 818 | } |
| 819 | |
| 820 | // Get document object |
| 821 | DocumentObject* pathDocObj = usePath.getDocumentObject(); |
| 822 | assert(pathDocObj); |
| 823 | |
| 824 | if (GetApplication().isFineGrainedRecomputeEnabled()) { |
| 825 | // Fully mimics the else part except for taking into account input properties. |
| 826 | auto inList = pathDocObj->getInListEx(true); |
| 827 | |
| 828 | std::map<DocumentObject*, bool> depObjects; |
| 829 | std::map<std::pair<std::string, DocumentObject*>, bool> propDeps; |
| 830 | expr->getDepObjects(depObjects, nullptr, &propDeps); |
| 831 | |
| 832 | for (const auto& [pair, hidden] : propDeps) { |
| 833 | auto* docObj = pair.second; |
| 834 | auto& propName = pair.first; |
| 835 | if (!hidden && inList.contains(docObj) && !docObj->isInputProperty(propName)) { |
| 836 | std::stringstream ss; |
| 837 | ss << "cyclic reference to " << docObj->getFullName() << "." << propName; |
| 838 | return ss.str(); |
| 839 | } |
| 840 | } |
| 841 | } |
| 842 | else { |
| 843 | auto inList = pathDocObj->getInListEx(true); |
| 844 | for (auto& v : expr->getDepObjects()) { |
| 845 | auto docObj = v.first; |
| 846 | if (!v.second && inList.contains(docObj)) { |
| 847 | std::stringstream ss; |
| 848 | ss << "cyclic reference to " << docObj->getFullName(); |
| 849 | return ss.str(); |
| 850 | } |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | |
| 855 | // Check for internal document object dependencies |
| 856 | |
| 857 | // Copy current expressions |
| 858 | ExpressionMap newExpressions = expressions; |
| 859 | |
| 860 | // Add expression in question |
| 861 | std::shared_ptr<Expression> exprClone(expr->copy()); |
| 862 | newExpressions[usePath].expression = exprClone; |
| 863 |
no test coverage detected