From 5b229cdf323271a06f38136bf80584b622a3f230 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 23 Oct 2026 10:10:47 +0200 Subject: [PATCH] #14912 Reject duplicate generated Python enum names --- .../Completions/RimCompletionEnums.h | 47 +++++++++++++++++++ .../Completions/RimFractureTemplate.cpp | 10 ---- .../Completions/RimFractureTemplate.h | 12 ++--- .../RimMswCompletionParameters.cpp | 26 +++++----- .../Completions/RimMswCompletionParameters.h | 22 ++------- .../RimNonDarcyPerforationParameters.cpp | 10 ++-- .../RimNonDarcyPerforationParameters.h | 12 ++--- .../Completions/RimSegmentCollection.cpp | 8 ---- .../Completions/RimSegmentCollection.h | 7 +-- .../RimWellPathCompletionSettings.cpp | 17 ------- .../RimWellPathCompletionSettings.h | 15 ++---- .../WellEvents/RimWellEventEnums.h | 27 +++++++++++ .../WellEvents/RimWellEventPerf.cpp | 8 ++-- .../WellEvents/RimWellEventPerf.h | 8 ++-- .../WellEvents/RimWellEventValve.cpp | 8 ---- .../WellEvents/RimWellEventValve.h | 8 ++-- .../cafPdmScripting/cafPdmPythonGenerator.cpp | 25 ++++++++++ .../cafMockObjects.cpp | 30 ++++++++++++ .../cafMockObjects.h | 24 ++++++++++ .../cafPdmPythonGeneratorTest.cpp | 20 ++++++++ 20 files changed, 223 insertions(+), 121 deletions(-) create mode 100644 ApplicationLibCode/ProjectDataModel/Completions/RimCompletionEnums.h create mode 100644 ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventEnums.h diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimCompletionEnums.h b/ApplicationLibCode/ProjectDataModel/Completions/RimCompletionEnums.h new file mode 100644 index 0000000000..043c5325a4 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimCompletionEnums.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- Equinor ASA +// +// ResInsight 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 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +namespace RimCompletionEnums +{ +enum class ReferenceMDType +{ + AUTO_REFERENCE_MD = 0, + MANUAL_REFERENCE_MD +}; + +enum class PressureDropType +{ + HYDROSTATIC, + HYDROSTATIC_FRICTION, + HYDROSTATIC_FRICTION_ACCELERATION +}; + +enum class LengthAndDepthType +{ + ABS, + INC +}; + +enum NonDarcyFlowType +{ + NON_DARCY_NONE, + NON_DARCY_COMPUTED, + NON_DARCY_USER_DEFINED, +}; +} // namespace RimCompletionEnums diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.cpp index 263d2e4f6f..b2edd6872c 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.cpp @@ -78,16 +78,6 @@ void caf::AppEnum::setUp() setDefault( RimFractureTemplate::WIDTH_FROM_FRACTURE ); } -template <> -void caf::AppEnum::setUp() -{ - addItem( RimFractureTemplate::NON_DARCY_NONE, "None", "None" ); - addItem( RimFractureTemplate::NON_DARCY_COMPUTED, "Computed", "Compute D-factor" ); - addItem( RimFractureTemplate::NON_DARCY_USER_DEFINED, "UserDefined", "User Defined D-factor" ); - - setDefault( RimFractureTemplate::NON_DARCY_NONE ); -} - template <> void caf::AppEnum::setUp() { diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.h b/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.h index 1bc24b4ba5..ee4e2517fa 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimFractureTemplate.h @@ -18,6 +18,8 @@ #pragma once +#include "RimCompletionEnums.h" + #include "RiaDefines.h" #include "cafAppEnum.h" @@ -115,12 +117,10 @@ public: BETA_FACTOR_FROM_FRACTURE, }; - enum NonDarcyFlowEnum - { - NON_DARCY_NONE, - NON_DARCY_COMPUTED, - NON_DARCY_USER_DEFINED, - }; + using NonDarcyFlowEnum = RimCompletionEnums::NonDarcyFlowType; + static constexpr NonDarcyFlowEnum NON_DARCY_NONE = RimCompletionEnums::NON_DARCY_NONE; + static constexpr NonDarcyFlowEnum NON_DARCY_COMPUTED = RimCompletionEnums::NON_DARCY_COMPUTED; + static constexpr NonDarcyFlowEnum NON_DARCY_USER_DEFINED = RimCompletionEnums::NON_DARCY_USER_DEFINED; public: RimFractureTemplate(); diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp index 15eaa42ba7..d0e0c34344 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.cpp @@ -37,28 +37,28 @@ namespace caf { template <> -void RimMswCompletionParameters::ReferenceMDEnum::setUp() +void AppEnum::setUp() { - addItem( RimMswCompletionParameters::ReferenceMDType::AUTO_REFERENCE_MD, "GridEntryPoint", "Grid Entry Point", { "GridIntersectionRefMD" } ); - addItem( RimMswCompletionParameters::ReferenceMDType::MANUAL_REFERENCE_MD, "UserDefined", "User Defined", { "ManualRefMD" } ); - setDefault( RimMswCompletionParameters::ReferenceMDType::AUTO_REFERENCE_MD ); + addItem( RimCompletionEnums::ReferenceMDType::AUTO_REFERENCE_MD, "GridEntryPoint", "Grid Entry Point", { "GridIntersectionRefMD" } ); + addItem( RimCompletionEnums::ReferenceMDType::MANUAL_REFERENCE_MD, "UserDefined", "User Defined", { "ManualRefMD" } ); + setDefault( RimCompletionEnums::ReferenceMDType::AUTO_REFERENCE_MD ); } template <> -void RimMswCompletionParameters::PressureDropEnum::setUp() +void AppEnum::setUp() { - addItem( RimMswCompletionParameters::PressureDropType::HYDROSTATIC, "H--", "Hydrostatic" ); - addItem( RimMswCompletionParameters::PressureDropType::HYDROSTATIC_FRICTION, "HF-", "Hydrostatic + Friction" ); - addItem( RimMswCompletionParameters::PressureDropType::HYDROSTATIC_FRICTION_ACCELERATION, "HFA", "Hydrostatic + Friction + Acceleration" ); - setDefault( RimMswCompletionParameters::PressureDropType::HYDROSTATIC_FRICTION ); + addItem( RimCompletionEnums::PressureDropType::HYDROSTATIC, "H--", "Hydrostatic" ); + addItem( RimCompletionEnums::PressureDropType::HYDROSTATIC_FRICTION, "HF-", "Hydrostatic + Friction" ); + addItem( RimCompletionEnums::PressureDropType::HYDROSTATIC_FRICTION_ACCELERATION, "HFA", "Hydrostatic + Friction + Acceleration" ); + setDefault( RimCompletionEnums::PressureDropType::HYDROSTATIC_FRICTION ); } template <> -void RimMswCompletionParameters::LengthAndDepthEnum::setUp() +void AppEnum::setUp() { - addItem( RimMswCompletionParameters::LengthAndDepthType::INC, "INC", "Incremental" ); - addItem( RimMswCompletionParameters::LengthAndDepthType::ABS, "ABS", "Absolute" ); - setDefault( RimMswCompletionParameters::LengthAndDepthType::ABS ); + addItem( RimCompletionEnums::LengthAndDepthType::INC, "INC", "Incremental" ); + addItem( RimCompletionEnums::LengthAndDepthType::ABS, "ABS", "Absolute" ); + setDefault( RimCompletionEnums::LengthAndDepthType::ABS ); } template <> diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h index 55051e189d..8944e22df2 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimMswCompletionParameters.h @@ -18,6 +18,7 @@ #pragma once #include "RiaDefines.h" +#include "RimCompletionEnums.h" #include "cafPdmChildField.h" #include "cafPdmField.h" @@ -34,24 +35,9 @@ class RimMswCompletionParameters : public caf::PdmObject CAF_PDM_HEADER_INIT; public: - enum class ReferenceMDType - { - AUTO_REFERENCE_MD = 0, - MANUAL_REFERENCE_MD - }; - - enum class PressureDropType - { - HYDROSTATIC, - HYDROSTATIC_FRICTION, - HYDROSTATIC_FRICTION_ACCELERATION - }; - - enum class LengthAndDepthType - { - ABS, - INC - }; + using ReferenceMDType = RimCompletionEnums::ReferenceMDType; + using PressureDropType = RimCompletionEnums::PressureDropType; + using LengthAndDepthType = RimCompletionEnums::LengthAndDepthType; enum class DiameterRoughnessMode { diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.cpp index d9112f5964..1f515adf41 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.cpp @@ -28,13 +28,13 @@ namespace caf { template <> -void caf::AppEnum::setUp() +void caf::AppEnum::setUp() { - addItem( RimNonDarcyPerforationParameters::NON_DARCY_NONE, "None", "None" ); - addItem( RimNonDarcyPerforationParameters::NON_DARCY_COMPUTED, "Computed", "Compute D-factor" ); - addItem( RimNonDarcyPerforationParameters::NON_DARCY_USER_DEFINED, "UserDefined", "User Defined D-factor" ); + addItem( RimCompletionEnums::NON_DARCY_NONE, "None", "None" ); + addItem( RimCompletionEnums::NON_DARCY_COMPUTED, "Computed", "Compute D-factor" ); + addItem( RimCompletionEnums::NON_DARCY_USER_DEFINED, "UserDefined", "User Defined D-factor" ); - setDefault( RimNonDarcyPerforationParameters::NON_DARCY_NONE ); + setDefault( RimCompletionEnums::NON_DARCY_NONE ); } } // namespace caf diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.h b/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.h index edca615d2c..ef7e46335c 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimNonDarcyPerforationParameters.h @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RimCompletionEnums.h" + #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmUiGroup.h" @@ -26,12 +28,10 @@ class RimNonDarcyPerforationParameters : public caf::PdmObject CAF_PDM_HEADER_INIT; public: - enum NonDarcyFlowEnum - { - NON_DARCY_NONE, - NON_DARCY_COMPUTED, - NON_DARCY_USER_DEFINED, - }; + using NonDarcyFlowEnum = RimCompletionEnums::NonDarcyFlowType; + static constexpr NonDarcyFlowEnum NON_DARCY_NONE = RimCompletionEnums::NON_DARCY_NONE; + static constexpr NonDarcyFlowEnum NON_DARCY_COMPUTED = RimCompletionEnums::NON_DARCY_COMPUTED; + static constexpr NonDarcyFlowEnum NON_DARCY_USER_DEFINED = RimCompletionEnums::NON_DARCY_USER_DEFINED; RimNonDarcyPerforationParameters(); ~RimNonDarcyPerforationParameters() override; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.cpp index 26830af9c2..d6363ac92e 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.cpp @@ -43,14 +43,6 @@ namespace caf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -template <> -void RimSegmentCollection::ReferenceMDEnum::setUp() -{ - addItem( RimSegmentCollection::ReferenceMDType::AUTO_REFERENCE_MD, "GridEntryPoint", "Grid Entry Point", { "GridIntersectionRefMD" } ); - addItem( RimSegmentCollection::ReferenceMDType::MANUAL_REFERENCE_MD, "UserDefined", "User Defined", { "ManualRefMD" } ); - setDefault( RimSegmentCollection::ReferenceMDType::AUTO_REFERENCE_MD ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.h b/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.h index 2ad22949a1..66b6e74b28 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimSegmentCollection.h @@ -18,6 +18,7 @@ #pragma once #include "RiaDefines.h" +#include "RimCompletionEnums.h" #include "cafPdmChildArrayField.h" #include "cafPdmField.h" @@ -41,11 +42,7 @@ class RimSegmentCollection : public caf::PdmObject CAF_PDM_HEADER_INIT; public: - enum class ReferenceMDType - { - AUTO_REFERENCE_MD = 0, - MANUAL_REFERENCE_MD - }; + using ReferenceMDType = RimCompletionEnums::ReferenceMDType; enum class CompsegsSegmentNumberType { diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp index 7f5be0cc12..f8888f0468 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.cpp @@ -74,23 +74,6 @@ void RimWellPathCompletionSettings::HydrostaticDensityEnum::setUp() setDefault( RimWellPathCompletionSettings::SEGMENTED ); } -template <> -void RimWellPathCompletionSettings::PressureDropEnum::setUp() -{ - addItem( RimWellPathCompletionSettings::PressureDropType::HYDROSTATIC, "H--", "Hydrostatic" ); - addItem( RimWellPathCompletionSettings::PressureDropType::HYDROSTATIC_FRICTION, "HF-", "Hydrostatic + Friction" ); - addItem( RimWellPathCompletionSettings::PressureDropType::HYDROSTATIC_FRICTION_ACCELERATION, "HFA", "Hydrostatic + Friction + Acceleration" ); - setDefault( RimWellPathCompletionSettings::PressureDropType::HYDROSTATIC_FRICTION ); -} - -template <> -void RimWellPathCompletionSettings::LengthAndDepthEnum::setUp() -{ - addItem( RimWellPathCompletionSettings::LengthAndDepthType::INC, "INC", "Incremental" ); - addItem( RimWellPathCompletionSettings::LengthAndDepthType::ABS, "ABS", "Absolute" ); - setDefault( RimWellPathCompletionSettings::LengthAndDepthType::ABS ); -} - } // namespace caf namespace diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h index 36cb8c4aba..4d5ac643e4 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimWellPathCompletionSettings.h @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RimCompletionEnums.h" + #include "cafPdmChildField.h" #include "cafPdmField.h" #include "cafPdmObject.h" @@ -65,19 +67,10 @@ public: }; using HydrostaticDensityEnum = caf::AppEnum; - enum class PressureDropType - { - HYDROSTATIC, - HYDROSTATIC_FRICTION, - HYDROSTATIC_FRICTION_ACCELERATION - }; + using PressureDropType = RimCompletionEnums::PressureDropType; using PressureDropEnum = caf::AppEnum; - enum class LengthAndDepthType - { - ABS, - INC - }; + using LengthAndDepthType = RimCompletionEnums::LengthAndDepthType; using LengthAndDepthEnum = caf::AppEnum; public: diff --git a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventEnums.h b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventEnums.h new file mode 100644 index 0000000000..54f0a72a52 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventEnums.h @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026- Equinor ASA +// +// ResInsight 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 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +namespace RimWellEventEnums +{ +enum class State +{ + OPEN, + SHUT +}; +} // namespace RimWellEventEnums diff --git a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.cpp b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.cpp index 306b8dc07c..d9806a3b13 100644 --- a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.cpp @@ -27,11 +27,11 @@ namespace caf { template <> -void caf::AppEnum::setUp() +void caf::AppEnum::setUp() { - addItem( RimWellEventPerf::State::OPEN, "OPEN", "Open" ); - addItem( RimWellEventPerf::State::SHUT, "SHUT", "Shut" ); - setDefault( RimWellEventPerf::State::OPEN ); + addItem( RimWellEventEnums::State::OPEN, "OPEN", "Open" ); + addItem( RimWellEventEnums::State::SHUT, "SHUT", "Shut" ); + setDefault( RimWellEventEnums::State::OPEN ); } } // namespace caf diff --git a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.h b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.h index 3325a8bbae..6ce66f59f0 100644 --- a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.h +++ b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventPerf.h @@ -18,6 +18,8 @@ #pragma once +#include "RimWellEventEnums.h" + #include "RimWellEvent.h" #include "cafAppEnum.h" @@ -36,11 +38,7 @@ class RimWellEventPerf : public RimWellEvent CAF_PDM_HEADER_INIT; public: - enum class State - { - OPEN, - SHUT - }; + using State = RimWellEventEnums::State; RimWellEventPerf(); ~RimWellEventPerf() override; diff --git a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.cpp b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.cpp index 9b422a8177..462a4dcced 100644 --- a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.cpp @@ -26,14 +26,6 @@ namespace caf { -template <> -void caf::AppEnum::setUp() -{ - addItem( RimWellEventValve::State::OPEN, "OPEN", "Open" ); - addItem( RimWellEventValve::State::SHUT, "SHUT", "Shut" ); - setDefault( RimWellEventValve::State::OPEN ); -} - template <> void caf::AppEnum::setUp() { diff --git a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.h b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.h index d806113e34..9d74453cbd 100644 --- a/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.h +++ b/ApplicationLibCode/ProjectDataModel/WellEvents/RimWellEventValve.h @@ -18,6 +18,8 @@ #pragma once +#include "RimWellEventEnums.h" + #include "RimWellEvent.h" #include "cafAppEnum.h" @@ -36,11 +38,7 @@ class RimWellEventValve : public RimWellEvent CAF_PDM_HEADER_INIT; public: - enum class State - { - OPEN, - SHUT - }; + using State = RimWellEventEnums::State; enum class ValveType { diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp index d467e9fc38..fd9ef92f75 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmPythonGenerator.cpp @@ -162,7 +162,10 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto std::map enumDefByDataTypeName; std::map enumClassNameByDataTypeName; std::map> inferredEnumNameAndFieldByDataTypeName; + std::map> enumTypeAndFieldByBaseName; std::set ambiguousEnumDataTypesReported; + std::set duplicateEnumClassNamesReported; + bool duplicateEnumClassNameDetected = false; // Seed with names that are already bound at module scope in the generated file (imports // and module-level functions) so a generated enum cannot shadow them. std::set usedEnumClassNames = { "PdmObjectBase", @@ -242,6 +245,27 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto baseName = it->second.first; } + QString fieldName = QString( "%1.%2" ).arg( field->ownerClass() ).arg( scriptability->scriptFieldName() ); + auto [enumNameIt, inserted] = + enumTypeAndFieldByBaseName.emplace( baseName, std::make_pair( dataTypeName, fieldName ) ); + if ( !inserted && enumNameIt->second.first != dataTypeName ) + { + duplicateEnumClassNameDetected = true; + if ( !duplicateEnumClassNamesReported.count( baseName ) ) + { + errorMessages.push_back( QString( "Duplicate Python enum class name '%1' is inferred for distinct enum " + "types used by fields '%2' and '%3'. " + "Register distinct names with caf::PdmScriptEnumNameRegistry, or " + "move the enum to a shared header if both fields " + "represent the same enum." ) + .arg( baseName ) + .arg( enumNameIt->second.second ) + .arg( fieldName ) ); + duplicateEnumClassNamesReported.insert( baseName ); + } + return QString(); + } + auto cached = enumClassNameByDataTypeName.find( dataTypeName ); if ( cached != enumClassNameByDataTypeName.end() ) return cached->second; @@ -783,6 +807,7 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto } } + if ( duplicateEnumClassNameDetected ) return QString(); return generatedCode; } diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp index 7d130afe94..5dda3d6527 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.cpp @@ -23,6 +23,18 @@ void AppEnum::setUp() addItem( MyEnum::T6, "T6", "T6" ); setDefault( MyEnum::T1 ); } + +template <> +void AppEnum::setUp() +{ + addItem( CollisionTestEnum::T1, "T1", "T1" ); + addItem( CollisionTestEnum::T2, "T2", "T2" ); + addItem( CollisionTestEnum::T3, "T3", "T3" ); + addItem( CollisionTestEnum::T4, "T4", "T4" ); + addItem( CollisionTestEnum::T5, "T5", "T5" ); + addItem( CollisionTestEnum::T6, "T6", "T6" ); + setDefault( CollisionTestEnum::T1 ); +} } // namespace caf CAF_PDM_SOURCE_INIT( SimpleObj, "SimpleObj" ); @@ -172,6 +184,24 @@ void InheritedDemoObj::setUseAmbiguousEnumField( bool useAmbiguousEnumField ) s_useAmbiguousEnumField = useAmbiguousEnumField; } +CAF_PDM_SOURCE_INIT( CollisionTestPdmObject, "CollisionTestPdmObject" ); + +bool CollisionTestPdmObject::s_useCollisionEnumField = false; + +CollisionTestPdmObject::CollisionTestPdmObject() +{ + CAF_PDM_InitScriptableObject( "Collision Test Object" ); + if ( s_useCollisionEnumField ) + { + CAF_PDM_InitScriptableFieldNoDefault( &m_enumField, "MyAppEnumValue", "A duplicate enum class name" ); + } +} + +void CollisionTestPdmObject::setUseCollisionEnumField( bool useCollisionEnumField ) +{ + s_useCollisionEnumField = useCollisionEnumField; +} + CAF_PDM_SOURCE_INIT( MyPdmDocument, "MyPdmDocument" ); //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h index ad992477e2..1fd6ab3a18 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafMockObjects.h @@ -33,6 +33,16 @@ enum class MyEnum T6 }; +enum class CollisionTestEnum +{ + T1, + T2, + T3, + T4, + T5, + T6 +}; + // This is a specialized class that can be used to implement custom behavior in configureCapabilities // It is required to have a specialization of PdmFieldScriptingCapability for this class, as the new class // MyAppEnumField is not known to the template @@ -135,6 +145,20 @@ private: static bool s_useAmbiguousEnumField; }; +class CollisionTestPdmObject : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + CollisionTestPdmObject(); + static void setUseCollisionEnumField( bool useCollisionEnumField ); + + caf::PdmField> m_enumField; + +private: + static bool s_useCollisionEnumField; +}; + class MyPdmDocument : public caf::PdmDocument { CAF_PDM_HEADER_INIT; diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafPdmPythonGeneratorTest.cpp b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafPdmPythonGeneratorTest.cpp index 27ddb21ba3..fa842fb582 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafPdmPythonGeneratorTest.cpp +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/cafPdmPythonGeneratorTest.cpp @@ -213,3 +213,23 @@ TEST( PdmPythonGenerator, ReportsAmbiguousEnumClassNames ) EXPECT_TRUE( errorMessages.front().contains( "AlternativeEnumValue" ) ); EXPECT_TRUE( errorMessages.front().contains( "PdmScriptEnumNameRegistry" ) ); } + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +TEST( PdmPythonGenerator, RejectsDuplicateEnumClassNames ) +{ + CollisionTestPdmObject::setUseCollisionEnumField( true ); + + caf::PdmPythonGenerator generator; + std::vector errorMessages; + QString generatedCode = generator.generate( caf::PdmDefaultObjectFactory::instance(), errorMessages ); + + CollisionTestPdmObject::setUseCollisionEnumField( false ); + + ASSERT_EQ( 1u, errorMessages.size() ); + EXPECT_TRUE( generatedCode.isEmpty() ); + EXPECT_TRUE( errorMessages.front().contains( "Duplicate Python enum class name 'MyAppEnumValue'" ) ); + EXPECT_TRUE( errorMessages.front().contains( "InheritedDemoObj.MyAppEnumValue" ) ); + EXPECT_TRUE( errorMessages.front().contains( "CollisionTestPdmObject.MyAppEnumValue" ) ); + EXPECT_TRUE( errorMessages.front().contains( "shared header" ) ); +}