..
  *******************************************************************************
  Copyright (c) 2023-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)

  This program and the accompanying materials are made available under the
  terms of the Eclipse Public License 2.0 which is available at
  http://www.eclipse.org/legal/epl-2.0.

  SPDX-License-Identifier: EPL-2.0
  *******************************************************************************

.. _coding_conventions:

Coding Guidelines
=================

General
-------

|Op_oss| is based on modern C++ (currently C++17). For coding guidelines, please refer to `ISO C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines>`_.

**Headers/Sources**

 - Use ``*.h`` as file extension for header files
 - Use ``*.cpp`` as file extension for source files

Naming Conventions
------------------
Concise summarized Naming Conventions

.. literalinclude:: _static/custom_doc/NamingConventions.txt

**Namespaces**

 #. Use lowercase for namespaces
 #. Use singular form for namespaces where appropriate
 #. Use base namespace ``openpass``
 #. Core uses ``openpass::core::*``
 #. Components use ``openpass::component::*``
 #. Use the appropriate namespace for the type your component
    * ``openpass::component::algorithm``
    * ``openpass::component::sensor``
    * ``openpass::component::dynamics``
    * ``openpass::component::driver``
    * ...
 #. Code with shared scope (e.g. ``common``) namespaces are separated in

    * For everyone ``openpass::common`` e.g. ``openpass::common::XmlParser``
    * Common for components ``openpass::component::common`` e.g. ``openpass::components::Ports``
    * For the core only ``openpass::core::common`` e.g. ``openpass::core::common::Parameters``

 #. Discussion: ``openpass::type::*``

    Example: ``openpass::type::Vector2D, openpass::type::OpenDriveId``

**Interfaces**

 #. Interfaces should be named descriptively according to the functionality they outline with an ``UpperCamelCase`` name

    Example: Interface for the **world** = ``class WorldInterface``
 #. Interfaces are abstract classes, and as such provide pure virtual functions only, withtout any default implementation. For example:

      ``virtual double GetDistance() const = 0;``

 #. Interface methods **do not** exibit default parameters.
 #. We excessively use **gmock**, so for every interface a fake interface should be provided

    Example: ``class FakeWorld : public WorldInterface {...};``

    Note: Following ***Roy Osherove***, we use Fake instead of Mock, whick allows to distinguish Mocks and
    Stubs more easily in the code

**Classes**

 #. Classes should be named descriptively according to the functionality they implement with an ``UpperCamelCase`` name
 #. A Class implementing an Interface should have the Interfaces name (see below), with the Interface portion removed. For example:
    .. code-block::

      class AgentBlueprint : public AgentBlueprintInterface {...};

**Methods**

 #. Methods should be descriptively named in ``UpperCamelCase``

    Example: Method for retrieving the time of day should be named ``GetTimeOfDay()``

**Member Variables**

 #. Member variables should be descriptively named in ``lowerCamelCase``
 #. Normally, it is sufficient to use the classes name directly.

    Example: The member variable containing the AgentNetwork should be named ``agentNetwork``

**Input / Output Signal Naming**

 #. Components use a special form of signal transmission. For easier use, the following abstraction is recommended:
    .. code-block::

      std::map<int, ComponentPort *> outputPorts;
      bool success = outputPorts.at(localLinkId)->SetSignalValue(data);

    .. code-block::

      std::map<int, ComponentPort *> inputPorts;
      bool success = inputPorts.at(localLinkId)->GetSignalValue(data);
 #. Discussion: Wrap in ``openpass::components::common::Port`` and further
    ``openpass::components::common::Ports``

**Additional Information**

 #. Use ``UpperCamelCase`` for abbreviations used in files, classes, methods, or variables
 #. This does not apply if the abbreviation is the entire name or the beginning of the name - in such a case the name is written with the rules for the appropriate type

    * int ID→int id
    * class AgentID→ class AgentId
    * ADASDriver.cpp→adasDriver.cpp
 #. Avoid public class data members. If unavoidable, use ``lowerCamelCase``
 #. Enums should be preferably defined as enum class; as such, enum names should be in ``UpperCamelCase``
 #. Decorate container by type aliases and use UpperCamelCase. For example:

  .. code-block::

    using FooParts = std::vector<FooPart>;

**Avoid**

 #. Do **not** use Hungarian notation for variables names (iCounter → counter)
 #. Do **not** specify the type of the underlying implementation (partMap→ parts)
 #. Do **not** use magic numbers in the code; explicitly define constants instead
 #. Do **not** use global variables

**Exceptions**

 #. Autogenerated code does not need to follow the coding conventions

    Example:: osi3: ``::osi3::DetectedEntityHeader* mutable_moving_object_header()``

**Documentation**

 #. The following should be documented
    * Public functions and class methods
    * Classes
    * File headers
    * Constants
    * Private functions or methods with more than 3 arguments and/or complex functionality??

 #. Language

    * Document "what" it does rather than describing "why"
    * Third-person singular verbs should be used to describe what it does

 #. Use the below methods to comment in source code. The below 2 syntaxes must be placed just above an entity.

    Multi line comments

    .. code-block::

      //! … comments…
      //! … comments…
      //! … comments…

    Single line comments

    .. code-block::

      /// Comments.

 #. Use the following structural commands

    .. list-table::
       :widths: 25 50
       :header-rows: 1

       * - Syntax
         - Definition
       * - @file
         - The file name must be present in the file header
       * - @param[in/out]
         - Parameter documentation for functions
       * - @page
         - Markdown page name

 #. Use the following syntax for parameter description

    .. code-block::

      @param[in/out] <variable name> <variable description>
 #. All parameters description should be aligned as shown below to make them more readable.

    .. code-block::

     @param[in]  shortName    Description.
     @param[in]  longerName   Description.
     @param[out] veryLongName Description.
 #. Example

    .. literalinclude:: _static/custom_doc/InlineDocumentation.txt

 #. Do not comment on polymorph methods (virtual base → override), unless there is a severe change

**End Of Line**

 #. Native end of line (EOL) should be used in the working directory
 #. The ``.gitattributes`` configuration file provides correct EOL handling for ``git`` related commands and actions
 #. When editing files

    * Trim trailing whitespaces
    * Single EOL at end of files
    * Use spaces for tabs (use tab size according to coding guidelines or existing file contents)

See :ref:`Example VSCode user settings <vscode_user_settings>`.

ClangFormat
-----------

To ensure consistent and readable code across the project, **ClangFormat** is recommended.

.. note::

   The following guidelines are based on ClangFormat version 15.0.7

**Installing ClangFormat**

To install **ClangFormat 15.0.7**, execute the following command depending on the operating system.

.. tabs::

   .. tab:: Windows

      .. code-block::

         pacman -S mingw-w64-x86_64-clang

   .. tab:: Linux (Debian Bookworm or Ubuntu 22.04)

      .. code-block::

         apt -y install clang-format

**Configuring ClangFormat**

To configure ClangFormat, create a `.clang-format` file in the root directory of your project. Below is the configuration used in |op_oss|:

   .. literalinclude:: /../../../repo/.clang-format

**Running ClangFormat**

To format the code using ClangFormat, run the following command in the terminal:

.. code-block:: bash

   clang-format -i [source_file(s)]

Replace `[source_file(s)]` with the path(s) to the file(s) to format. The `-i` option tells ClangFormat to modify the files in-place.

ClangTidy
-----------

Supported Version: 14.0.6

To ensure code quality and adherence to coding standards, ClangTidy is recommended.

The used checks are located in the :download:`.clang-tidy </../../../repo/.clang-tidy>` file, where lines starting with ``-`` are checks that have been deactivated.
For more details, visit the `ClangTidy official page <https://clang.llvm.org/extra/clang-tidy/#using-clang-tidy>`_.

Commit Message Guidelines
-------------------------

**Overview**

This section outlines the guidelines for writing commit messages in openPASS repository. Following these guidelines ensures that commit messages are clear, descriptive, and help facilitate collaboration among team members.
This section uses excerpts from `Conventional Commits <https://www.conventionalcommits.org/en/v1.0.0/>`_ licensed under `CC BY 3.0 <https://creativecommons.org/licenses/by/3.0/>`_ by it's authors.

**Commit Message Format**

Each commit message should consist of a single short summary line (recommended, up to 50 characters) followed by a more detailed description (if necessary).
The message should adhere to the following format:

   .. code-block::

    <type>[optional scope]: <description>

    [optional body]

    [optional footer(s)]

 #. The ``<type>`` part represents the type of the commit, which helps in categorizing the nature of the changes. The following types are allowed:

    * ``feat``: A new feature or enhancement.
    * ``fix``: A bug fix.
    * ``docs``: Documentation-related changes.
    * ``style``: Code style changes (e.g., formatting, spacing).
    * ``refactor``: Code refactoring without adding new features or fixing bugs.
    * ``test``: Adding or improving tests.
    * ``chore``: Maintenance tasks, build changes, or other non-functional modifications.
    * ``ci``: Changes related to CI.
    * ``build``: Modifications related to build step.
    * ``perf``: Modifications related to performance improvements.
    * ``revert``: Revert any code changes.

 #. The ``<optional scope>`` section is optional but is used to provide additional contextual information and is contained within parenthesis.

 #. The ``<description>`` is a brief description of the changes made in the commit. It should be concise yet informative and is recommended to not exceed 50 characters.

 #. The ``<optional body>`` section is optional but recommended, especially for complex changes or when further explanation is needed. This section should provide additional context, justification, and details about the changes made. Use bullet points for better readability when necessary.

 #. The ``<optional footer>`` section is also optional but can be used to provide supplementary information related to the commit.

Header File Inclusion
---------------------

**Overview**

When working on a C/C++ project, it's essential to include header files correctly. This documentation explains the various ways to include header files, depending on their source.

**System Libraries**

Header files from system libraries should be enclosed in angular brackets (`< >`). This syntax informs the compiler to search for the headers in the system's standard include directories.

   .. code-block::

      #include <stdio.h>
      #include <stdlib.h>

**Dependencies in CMAKE_PREFIX_PATH**

If the header files are from dependencies that are part of the `CMAKE_PREFIX_PATH`, use angular brackets (`< >`) as well. This indicates to the compiler that the headers are part of external dependencies.

   .. code-block::

      #include <dependency/header.h>

**Repository Header Files**

If the header files are from project's repository then, use double quotes (`" ""`).

   .. code-block::

      #include "my_component/header.h"
