mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add VTKM_DEPRECATED macro
The `VTKM_DEPRECATED` macro allows us to remove (and usually replace) features from VTK-m in minor releases while still following the conventions of semantic versioning. The idea is that when we want to remove or replace a feature, we first mark the old feature as deprecated. The old feature will continue to work, but compilers that support it will start to issue a warning that the use is deprecated and should stop being used. The deprecated features should remain viable until at least the next major version. At the next major version, deprecated features from the previous version may be removed.
This commit is contained in:
parent
05917e11a1
commit
ed4d0d50c3
70
docs/changelog/deprecation.md
Normal file
70
docs/changelog/deprecation.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Add VTKM_DEPRECATED macro
|
||||
|
||||
The `VTKM_DEPRECATED` macro allows us to remove (and usually replace)
|
||||
features from VTK-m in minor releases while still following the conventions
|
||||
of semantic versioning. The idea is that when we want to remove or replace
|
||||
a feature, we first mark the old feature as deprecated. The old feature
|
||||
will continue to work, but compilers that support it will start to issue a
|
||||
warning that the use is deprecated and should stop being used. The
|
||||
deprecated features should remain viable until at least the next major
|
||||
version. At the next major version, deprecated features from the previous
|
||||
version may be removed.
|
||||
|
||||
Classes and methods are marked deprecated using the `VTKM_DEPRECATED`
|
||||
macro. The first argument of `VTKM_DEPRECATED` should be set to the first
|
||||
version in which the feature is deprecated. For example, if the last
|
||||
released version of VTK-m was 1.5, and on the master branch a developer
|
||||
wants to deprecate a class foo, then the `VTKM_DEPRECATED` release version
|
||||
should be given as 1.6, which will be the next minor release of VTK-m. The
|
||||
second argument of `VTKM_DEPRECATED`, which is optional but highly
|
||||
encouraged, is a short message that should clue developers on how to update
|
||||
their code to the new changes. For example, it could point to the
|
||||
replacement class or method for the changed feature.
|
||||
|
||||
`VTKM_DEPRECATED` can be used to deprecate a class by adding it between the
|
||||
`struct` or `class` keyword and the class name.
|
||||
|
||||
``` cpp
|
||||
struct VTKM_DEPRECATED(1.6, "OldClass replaced with NewClass.") OldClass
|
||||
{
|
||||
};
|
||||
```
|
||||
|
||||
Aliases can similarly be depreciated, except the `VTKM_DEPRECATED` macro
|
||||
goes after the name in this case.
|
||||
|
||||
``` cpp
|
||||
using OldAlias VTKM_DEPRECATED(1.6, "Use NewClass instead.") = NewClass;
|
||||
```
|
||||
|
||||
Functions and methods are marked as deprecated by adding `VTKM_DEPRECATED`
|
||||
as a modifier before the return value.
|
||||
|
||||
``` cpp
|
||||
VTKM_EXEC_CONT
|
||||
VTKM_DEPRECATED(1.6, "You must now specify a tolerance.") void ImportantMethod(double x)
|
||||
{
|
||||
this->ImportantMethod(x, 1e-6);
|
||||
}
|
||||
```
|
||||
|
||||
`enum`s can be deprecated like classes using similar syntax.
|
||||
|
||||
``` cpp
|
||||
enum struct VTKM_DEPRECATED(1.7, "Use NewEnum instead.") OldEnum
|
||||
{
|
||||
OLD_VALUE
|
||||
};
|
||||
```
|
||||
|
||||
Individual items in an `enum` can also be marked as deprecated and
|
||||
intermixed with regular items.
|
||||
|
||||
``` cpp
|
||||
enum struct NewEnum
|
||||
{
|
||||
OLD_VALUE1 VTKM_DEPRECATED(1.7, "Use NEW_VALUE instead."),
|
||||
NEW_VALUE,
|
||||
OLD_VALUE2 VTKM_DEPRECATED(1.7) = 42
|
||||
};
|
||||
```
|
@ -25,6 +25,7 @@ set(headers
|
||||
CellClassification.h
|
||||
CellShape.h
|
||||
CellTraits.h
|
||||
Deprecated.h
|
||||
Flags.h
|
||||
Geometry.h
|
||||
Hash.h
|
||||
|
38
vtkm/Deprecated.h
Normal file
38
vtkm/Deprecated.h
Normal file
@ -0,0 +1,38 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_Deprecated_h
|
||||
#define vtk_m_Deprecated_h
|
||||
|
||||
#include <vtkm/internal/CompilerFeatures.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#define VTK_M_DEPRECATED_MAKE_MESSAGE(...) \
|
||||
VTKM_EXPAND(VTK_M_DEPRECATED_MAKE_MESSAGE_IMPL(__VA_ARGS__, "", vtkm::internal::NullType{}))
|
||||
#define VTK_M_DEPRECATED_MAKE_MESSAGE_IMPL(version, message, ...) \
|
||||
message " Deprecated in version " #version "."
|
||||
|
||||
/// \def VTKM_DEPRECATED(version, message)
|
||||
///
|
||||
/// Classes and methods are marked deprecated using the `VTKM_DEPRECATED`
|
||||
/// macro. The first argument of `VTKM_DEPRECATED` should be set to the first
|
||||
/// version in which the feature is deprecated. For example, if the last
|
||||
/// released version of VTK-m was 1.5, and on the master branch a developer
|
||||
/// wants to deprecate a class foo, then the `VTKM_DEPRECATED` release version
|
||||
/// should be given as 1.6, which will be the next minor release of VTK-m. The
|
||||
/// second argument of `VTKM_DEPRECATED`, which is optional but highly
|
||||
/// encouraged, is a short message that should clue developers on how to update
|
||||
/// their code to the new changes. For example, it could point to the
|
||||
/// replacement class or method for the changed feature.
|
||||
///
|
||||
#define VTKM_DEPRECATED(...) VTK_M_DEPRECATED_MSG(VTK_M_DEPRECATED_MAKE_MESSAGE(__VA_ARGS__))
|
||||
|
||||
#endif // vtk_m_Deprecated_h
|
@ -33,8 +33,18 @@ vtkm_get_kit_name(kit_name kit_dir)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Configure.h.in
|
||||
${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/Configure.h
|
||||
@ONLY)
|
||||
vtkm_install_headers(
|
||||
vtkm/internal ${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/Configure.h)
|
||||
include(WriteCompilerDetectionHeader)
|
||||
write_compiler_detection_header(
|
||||
FILE ${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/CompilerFeatures.h
|
||||
PREFIX VTK_M
|
||||
COMPILERS ${CMAKE_CXX_COMPILER_ID} GNU Clang AppleClang MSVC SunPro Intel
|
||||
FEATURES cxx_attribute_deprecated
|
||||
ALLOW_UNKNOWN_COMPILERS
|
||||
)
|
||||
vtkm_install_headers(vtkm/internal
|
||||
${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/Configure.h
|
||||
${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/CompilerFeatures.h
|
||||
)
|
||||
|
||||
unset(VTKM_ENABLE_MPI)
|
||||
unset(VTKM_ENABLE_TBB)
|
||||
|
@ -278,11 +278,44 @@
|
||||
while (false)
|
||||
#endif
|
||||
|
||||
// Use a trick to pass arguments containing commas through a macro. This is
|
||||
// helpful for mixing template code with macros.
|
||||
// See https://stackoverflow.com/questions/13842468
|
||||
/// \def VTKM_PASS_COMMAS(...)
|
||||
///
|
||||
/// A trick to pass arguments containing commas through a macro. This is
|
||||
/// helpful for mixing template code with macros.
|
||||
///
|
||||
/// See https://stackoverflow.com/questions/13842468
|
||||
#define VTKM_PASS_COMMAS(...) __VA_ARGS__
|
||||
|
||||
/// \def VTKM_EXPAND(expr)
|
||||
///
|
||||
/// A utility macro to expand the arguments of macro before invoking it in the
|
||||
/// preprocessor. This is mostly used to handle the `__VA_ARGS__` created for
|
||||
/// variadic preprocessor macros. Often you will have to pass `__VA_ARGS__` to
|
||||
/// another macro to tease out particular parameters. For example, to get the
|
||||
/// first argument, you might make something like this.
|
||||
///
|
||||
/// ```cpp
|
||||
/// #define GET_FIRST_ARGUMENT(...) GET_FIRST_ARGUMENT_IMPL(__VA_ARGS__, no_arg)
|
||||
/// #define GET_FIRST_ARGUMENT_IMPL(first, ...) first
|
||||
/// ```
|
||||
///
|
||||
/// You would expect this pair of macros to give you the first argument or the
|
||||
/// token `no_arg` if no arguments were given, and for most compilers that
|
||||
/// is what you would get. But Visual Studio in particular has a weird
|
||||
/// interpretation of the standard that causes `__VA_ARGS__` to be treated
|
||||
/// as a single argument when passed to another macro. Consequently, for the
|
||||
/// example above, Visual Studio actually returns all args passed instead of
|
||||
/// the first. To get around the problem, you can wrap the entire call to
|
||||
/// the secondary macro in VTKM_EXPAND to get Visual Studio (and all other
|
||||
/// compilers) to properly treat `__VA_ARGS__` as separate arguments.
|
||||
///
|
||||
/// ```cpp
|
||||
/// #define GET_FIRST_ARGUMENT(...) VTKM_EXPAND(GET_FIRST_ARGUMENT_IMPL(__VA_ARGS__, no_arg))
|
||||
/// #define GET_FIRST_ARGUMENT_IMPL(first, ...) first
|
||||
/// ```
|
||||
///
|
||||
#define VTKM_EXPAND(expr) expr
|
||||
|
||||
#ifdef VTKM_MSVC
|
||||
//With MSVC the types that we generate cause warning C4503 (long symbol names)
|
||||
//this doesn't affect the resulting binary so we just suppress that warning
|
||||
|
@ -22,6 +22,7 @@ set(unit_tests
|
||||
UnitTestBinaryOperators.cxx
|
||||
UnitTestBounds.cxx
|
||||
UnitTestCellShape.cxx
|
||||
UnitTestDeprecated.cxx
|
||||
UnitTestExceptions.cxx
|
||||
UnitTestHash.cxx
|
||||
UnitTestListTag.cxx
|
||||
|
@ -50,7 +50,6 @@
|
||||
|
||||
#define VTKM_STRINGIFY_FIRST(...) VTKM_EXPAND(VTK_M_STRINGIFY_FIRST_IMPL(__VA_ARGS__, dummy))
|
||||
#define VTK_M_STRINGIFY_FIRST_IMPL(first, ...) #first
|
||||
#define VTKM_EXPAND(x) x
|
||||
|
||||
/// \def VTKM_TEST_ASSERT(condition, messages..)
|
||||
///
|
||||
@ -570,6 +569,30 @@ struct TestEqualImpl<std::string, std::string>
|
||||
return string1 == string2;
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct TestEqualImpl<const char*, T>
|
||||
{
|
||||
VTKM_CONT bool operator()(const char* string1, T value2, vtkm::Float64 tolerance) const
|
||||
{
|
||||
return TestEqualImpl<std::string, T>()(string1, value2, tolerance);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct TestEqualImpl<T, const char*>
|
||||
{
|
||||
VTKM_CONT bool operator()(T value1, const char* string2, vtkm::Float64 tolerance) const
|
||||
{
|
||||
return TestEqualImpl<T, std::string>()(value1, string2, tolerance);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct TestEqualImpl<const char*, const char*>
|
||||
{
|
||||
VTKM_CONT bool operator()(const char* string1, const char* string2, vtkm::Float64 tolerance) const
|
||||
{
|
||||
return TestEqualImpl<std::string, std::string>()(string1, string2, tolerance);
|
||||
}
|
||||
};
|
||||
|
||||
/// Special implementation of test_equal for Pairs, which are a bit different
|
||||
/// than a vector of numbers of the same type.
|
||||
|
97
vtkm/testing/UnitTestDeprecated.cxx
Normal file
97
vtkm/testing/UnitTestDeprecated.cxx
Normal file
@ -0,0 +1,97 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/Deprecated.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct NewClass
|
||||
{
|
||||
VTKM_EXEC_CONT
|
||||
void ImportantMethod(double x, double tolerance)
|
||||
{
|
||||
std::cout << "Using " << x << " with tolerance " << tolerance << std::endl;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
VTKM_DEPRECATED(1.6, "You must now specify a tolerance.") void ImportantMethod(double x)
|
||||
{
|
||||
this->ImportantMethod(x, 1e-6);
|
||||
}
|
||||
};
|
||||
|
||||
struct VTKM_DEPRECATED(1.6, "OldClass replaced with NewClass.") OldClass
|
||||
{
|
||||
};
|
||||
|
||||
using OldAlias VTKM_DEPRECATED(1.6, "Use NewClass instead.") = NewClass;
|
||||
|
||||
//// Should be OK for one deprecated alias to use another deprecated thing (you would think).
|
||||
//using OlderAlias VTKM_DEPRECATED(1.6, "Use NewClass instead.") = OldAlias;
|
||||
|
||||
enum struct VTKM_DEPRECATED(1.7, "Use NewEnum instead.") OldEnum
|
||||
{
|
||||
OLD_VALUE
|
||||
};
|
||||
|
||||
enum struct NewEnum
|
||||
{
|
||||
OLD_VALUE1 VTKM_DEPRECATED(1.7, "Use NEW_VALUE instead."),
|
||||
NEW_VALUE,
|
||||
OLD_VALUE2 VTKM_DEPRECATED(1.7) = 42
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void DoSomethingWithObject(T)
|
||||
{
|
||||
std::cout << "Looking at " << typeid(T).name() << std::endl;
|
||||
}
|
||||
|
||||
static void DoTest()
|
||||
{
|
||||
std::cout << "C++14 deprecated supported: " << VTK_M_COMPILER_CXX_ATTRIBUTE_DEPRECATED
|
||||
<< std::endl;
|
||||
std::cout << "Deprecation is: " << VTKM_STRINGIFY_FIRST(VTKM_DEPRECATED(X.Y, "Message."))
|
||||
<< std::endl;
|
||||
|
||||
VTKM_TEST_ASSERT(test_equal(VTK_M_DEPRECATED_MAKE_MESSAGE(X.Y), " Deprecated in version X.Y."));
|
||||
VTKM_TEST_ASSERT(test_equal(VTK_M_DEPRECATED_MAKE_MESSAGE(X.Y.Z, "Use feature foo instead."),
|
||||
"Use feature foo instead. Deprecated in version X.Y.Z."));
|
||||
|
||||
// Using valid classes with unused deprecated parts should be fine.
|
||||
NewClass useIt;
|
||||
DoSomethingWithObject(useIt);
|
||||
useIt.ImportantMethod(1.1, 1e-8);
|
||||
DoSomethingWithObject(NewEnum::NEW_VALUE);
|
||||
|
||||
// These should each give compiler warnings.
|
||||
#if 0
|
||||
OldClass useOldClass;
|
||||
DoSomethingWithObject(useOldClass);
|
||||
OldAlias useOldAlias;
|
||||
DoSomethingWithObject(useOldAlias);
|
||||
//OlderAlias useOlderAlias;
|
||||
//DoSomethingWithObject(useOlderAlias);
|
||||
useIt.ImportantMethod(1.1);
|
||||
DoSomethingWithObject(OldEnum::OLD_VALUE);
|
||||
DoSomethingWithObject(NewEnum::OLD_VALUE1);
|
||||
DoSomethingWithObject(NewEnum::OLD_VALUE2);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestDeprecated(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::testing::Testing::Run(DoTest, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user