/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

namespace Magnum {
/** @page coding-style Coding style
@brief Coding style and best practices to preserve maintainability and
consistent style across whole project.

@tableofcontents

Please note that if you have a good excuse to either break the rules or modify
them, feel free to do it (and update this guide accordingly, if appropriate).
Nothing is worse than rule that hurts productivity instead of improving it.

This guide builds upon Corrade's coding style guide and extends it where
needed. You are encouraged to read it first:

 - @ref corrade-coding-style

@section coding-style-cpp C++ code

@subsection coding-style-cpp-headers Headers

Headers shouldn't have `using` declarations inside them (unless there is good
excuse, see Magnum.h).

Headers have `*.h` extension, @ref compilation-speedup-hpp "template implementation headers"
have `*.hpp` extension (hinting that they are something between `*.h` and
`*.cpp` files).

@subsection coding-style-cpp-format Code format

@subsubsection coding-style-cpp-types Builtin types

Use %Magnum's own type aliases for public API (e.g. @ref UnsignedInt, see
@ref types for more information), but use specific types when interacting with
third party libraries and OpenGL (e.g. `GLuint`) and rely only on implicit
conversions when converting between them. This helps avoiding sign, truncation
and other issues, e.g. `%Math::%Vector2<GLsizei>` will implicitly convert to
@ref Vector2i if and only if @ref Int is the same type as `GLsizei`.

@subsubsection coding-style-cpp-naming Naming

When writing wrappers for OpenGL functions and defines, try to match the
original name as closely as possible, although expanding abbrevations (and
removing redundant prefixes) is encouraged.

@subsubsection coding-style-cpp-forward-declarations Forward declarations and forward declaration headers

When a namespace has classes which are commonly forward-declared, consider
making a forward declaration header - it should have the same name as the
namespace itself and contain foward declarations for all classes, enums and
copies of all meaningful typedefs. See @ref compilation-forward-declarations
for more information.

@section coding-style-compatibility Compatibility with various OpenGL editions

If any class, function or part of code depends on particular OpenGL edition
(e.g. only for desktop), use conditional compilation to avoid erors on other
platforms (see @ref portability-target for more information). Put related
documentation also into the conditional compilation block and don't forget to
appropriately mark the class/function
(@ref coding-style-documentation-commands-requires "see below"). Example:
@code
#ifndef MAGNUM_TARGET_GLES
//
// @brief Set polygon mode
//
// @requires_gl Polygon mode is not available in OpenGL ES.
//
void setPolygonMode(PolygonMode mode);
#endif
@endcode

@section coding-style-documentation Doxygen documentation

@subsection coding-style-documentation-commands Special documentation commands

Additionally to @c \@todoc, @c \@debugoperator, @c \@debugoperatorenum,
@c \@debugoperatorclassenum, @c \@configurationvalue and
@c \@configurationvalueref (same as in %Corrade), these are defined:

@subsubsection coding-style-documentation-commands-collisionoperator Shape collision operators

Out-of-class operators for collision and collision occurence in Shapes
namespace should be marked with @c \@collisionoperator and @c \@collisionoccurenceoperator,
e.g.:
@code
// @collisionoccurenceoperator{Point,Sphere}
inline bool operator%(const Point& a, const Sphere& b) { return b % a; }

// @collisionoperator{Point,Sphere}
inline Collision operator/(const Point& a, const Sphere& b) { return (b/a).reverted(); }
@endcode
They will appear as related functions within documentation of class for which
the operator is implemented (not of class in which the operator is
implemented), thus efficiently connecting the two classes together in the
documentation.

@subsubsection coding-style-documentation-commands-extension Links to OpenGL extensions

If an OpenGL extension is referenced in the documentation, it should be done
with @c \@extension command:
@code
@extension{ARB,timer_query}
@endcode
It produces link to the specification of the extension in OpenGL registry:
> @extension{ARB,timer_query}

Similarly for OpenGL ES extensions there is @c \@es_extension command. Some
extensions have slightly different URL, with command @c \@es_extension2 you can
specify extension filename, if the previous command gives 404 error. For example
@code
@es_extension2{NV,read_buffer_front,GL_NV_read_buffer}
@endcode
produces this link:
> @es_extension2{NV,read_buffer_front,GL_NV_read_buffer}

@subsubsection coding-style-documentation-commands-ref_gl Links to related OpenGL functions and definitions

If an function touches OpenGL, related OpenGL functions should be documented
in @c \@see block with @c \@fn_gl command. If only specific definition is used
in the function, document it with @c \@def_gl command. Example usage:
@code
// @see @fn_gl{Enable}/@fn_gl{Disable} with @def_gl{TEXTURE_CUBE_MAP_SEAMLESS}
static void setSeamless(bool enabled) {
    enabled ? glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS) : glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
@endcode
It produces link to the online manual:
> @fn_gl{Enable}/@fn_gl{Disable} with @def_gl{TEXTURE_CUBE_MAP_SEAMLESS}.

For functions which are not part of OpenGL core specification, but only as
extensions, use @c \@fn_gl_extension command, e.g.
@code
@fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access}
@endcode
First parameter is function name without the suffix, the second two parameters
are the same as in @c \@extension command. It produced link to extension
specification, with function name as link text:
> @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access}.

@subsubsection coding-style-documentation-commands-requires Classes and functions requiring specific OpenGL version or extensions

If any class or function requires specific OpenGL version above 2.1, it should
be marked with appropriate command @c \@requires_glXX, where `XX` is version
number (e.g. `42` for OpenGL 4.2) or @c \@requires_extension for specific
extension which is not in any core OpenGL version. It should be used in
conjunction with @c \@extension command, if there is an extension providing
the same functionality. For example:
@code
@requires_GL33 Extension @extension{ARB,timer_query}
@endcode

If class is marked with the command, member and related functions shouldn't be
marked. On the other hand, if the version/extension is needed only by one
function, only the function should be marked. If the extension is needed only
for some functionality (not related to any member function), it should be
noted in the description.

Similarly for OpenGL ES there is command @c \@requires_gl for functionality
not available in OpenGL ES at all, @c \@requires_gles30 for functionality
requiring OpenGL ES 3.0 (i.e. not part of OpenGL 2.0) and
@c \@requires_es_extension for specific extensions not part of OpenGL ES
specification. When there is both required desktop OpenGL version/extension
and OpenGL ES version/extension, first come desktop requirements, then ES
requirements.

All classes and functions using those commands are cross-referenced in page
@ref opengl-required-extensions.

@subsection coding-style-documentation-ordering Section ordering

In detailed documentation the text should be always first, the blocks are then
ordered by their importance. Various @c \@note, @c \@attention and @c \@warning
blocks to highlight some information are always first, then @c \@see block with
links to related stuff, where related %Magnum functions are first and links to
related GL API last, then various support information such as
@c \@requires_glXX, @c \@requires_es_extension etc. (first desktop GL, then ES,
then WebGL), after that @c \@deprecated_gl and @c \@deprecated information and
@c \@todo, @c \@todoc and @c \@bug always last, as they are the least important
and in most cases only for internal use.

@section coding-style-unit-tests Unit tests

All unit tests use Corrade's @ref Corrade::TestSuite "TestSuite".

Don't forget to test all `constexpr` methods -- many compilers don't implicitly
check whether the `constexpr` keyword can be used but then complain when you
force the expression to be constant. It's better not to have given method
marked as `constexpr` than have it marked it errorneously. It's usually not
desirable to have special test case for `constexpr` behaviors, add `constexpr`
keywords to existing test cases to avoid duplicated testing of the same thing.
Example (testing copy constructor):
@code
constexpr Vector3 a(1.5f, 2.0f, 0.4f);
constexpr Vector3 b(a);
CORRADE_COMPARE(b, Vector3(1.5f, 2.0f, 0.4f));
@endcode

Don't forget to test implicit/explicit constructors and conversion operators
where it matters (i.e. all low-level and frequently used types like vectors,
matrices etc.). If the constructor/operator is implicit, test it in the context
where explicit one would fail to compile, if it is explicit, test its
explicitness with `std::is_convertible` (it should return `false`). These tests
might catch various ambiguous call errors which would otherwise be unnoticed:
@code
Vector2 a = {1.5f, 0.5f}; // Explicit constructor would fail to compile here
CORRADE_COMPARE(a, Vector2(1.5f, 0.5f));

Vector2i b(a); // Implicit conversion operator would return true in 2nd check
CORRADE_COMPARE(b, Vector2(1, 0));
CORRADE_VERIFY(!(std::is_convertible<Vector2, Vector2i>::value));
@endcode

If some type should be constructible also from base type (additionaly to copy
constructor), don't forget to test that too. The test is also usually needed
only for low-level frequently used types (vectors, matrices) where such error
would do largest harm. Depending on how copy constructor is implemented, you
probably don't need to test classic copy construction, as it would be handled
by the already tested one. Example (copy construction from base type):
@code
Vector<3, Float> a(1.5f, 2.0f, 0.4f);
Vector3 b(a);
CORRADE_COMPARE(b, Vector3(1.5f, 2.0f, 0.4f));
@endcode

*/
}
