# Azure SDK for C++ Snippet Generation

One of the most important tools for ensuring a consistent and high-quality developer experience is the code snippets that are provided to developers. These snippets are used in documentation, quickstarts, and tutorials. They are also used in the interactive documentation (Try It) and in the VS Code extension.

It is critical that code snippets remain up-to-date and accurate. A snippet which represents out-of-date code is in many ways worse than no snippet at all.

To ensure that all snippets are up-to-date, we have created a tool that generates snippets from the source code of a package. A developer can run this tool before checking in changes to the snippets to update the snippets in documentation. 
This tool is also run as part of the CI process to verify that the checked in documentation matches the generated snippets. This ensures that the snippets are always up-to-date.

## About Snippets

There are two concepts that need to be considered when generating snippets: the snippet itself and the snippet source.

The snippet is the code that is inserted into the documentation. It is the code that the developer will copy and paste into their application. The snippet source is the code that is used to generate the snippet. The snippet source is typically a function call or a class method call.

For example, consider the following snippet source:

```cpp
auto client = Azure::Service::CreateFromConnectionString(connectionString);
```

This snippet source is a function call.

When a developer wants to include this snippet in a documentation page, they insert the snippet into existing markdown:

~~~markdown

This is an example of how to use the CreateFromConnectionString API to create a client:

```cpp
auto client = Azure::Service::CreateFromConnectionString(connectionString);
```
~~~

The problem with this of course is that if the signature of the `CreateFromConnectionString` function changes, the snippet will no 
longer be accurate. To solve this problem, we use the snippet source to generate the snippet.

## Creating Snippets for the Azure SDK for C++

There are two steps to generating snippets for the Azure SDK for C++. The first is annotating the source code, 
the second is running the snippet generation tool to update the snippets in the documentation.

### Snippet Source

Snippet Sources are marked using two special markers:

```cpp
// @begin_snippet: snippet_name
```

and

```cpp
// @end_snippet
```

These markers are used to identify the snippet source. The snippet source is then used to generate the snippet. The snippet is generated by removing the markers and the leading indentation.

For the example above, the snippet source would be:

```cpp
// @begin_snippet: CreateServiceFromConnectionString
auto client = Azure::Service::CreateFromConnectionString(connectionString);
// @end_snippet
```

The "name" of a snippet can be any string of "word" characters as defined by [.Net Regular 
Expressions](https://learn.microsoft.com/dotnet/standard/base-types/character-classes-in-regular-expressions#WordCharacter).

Note that it is critically important that the snippet source be valid code. 
The snippet generation tool does not compile the snippet source, instead the snippet source should be included in the source code built with the project.
That ensures that all snippets are valid code reflecting the current state of the service implementation.

Snippet sources can be located in any source file, including header files.

### Snippet use in documentation

The snippet source is then used in the documentation:

~~~markdown
This is an example of how to use the CreateFromConnectionString API to create a client:

<!-- @insert_snippet: CreateServiceFromConnectionString -->
```cpp
auto client = Azure::Service::CreateFromConnectionString(connectionString);
```
~~~

For C++ code, snippets similarly inserted into doxygen comments:

```cpp
/**
 * @brief This is an example of how to use the CreateFromConnectionString API to create a client:
 *
 * <!-- @insert_snippet: CreateServiceFromConnectionString -->
 * \code{cpp}
 * auto client = Azure::Service::CreateFromConnectionString(connectionString);
 * ```
 */
```

*** NOTE: AS OF 11/30/2023, DOXYGEN SNIPPET INSERTION IS NOT YET SUPPORTED. ***


The snippet source is identified by the word following the `@insert_snippet` marker.

### Snippet Generation

The snippet generation tool, located in `eng\scripts\Generate-Snippets.ps1`, is a powershell script used to generate snippets from the source code. The tool is run from the root of the repository:

```bash
pwsh -f eng\scripts\Generate-Snippets.ps1 -source_dir <path to source code containing snippets> -output_dir <path to directory containing output files>
```

For example, you can run the snippet generation tool for all the packages in the repo, as follows:

```bash
pwsh -f .\eng\scripts\Generate-Snippets.ps1 -source_dir sdk -output_dir sdk
 ```

The tool will recursively search the source directory for snippet sources and parse the snippet sources in each 
source file.

It then recursively walks the output directory and for each file that contains a snippet, it will replace the
snippet with the corresponding parsed snippet.


## Snippet Generation in CI

The snippet generation tool is also run as part of the CI process. The CI process will run the snippet generation tool
and then compare the generated snippets with the checked in snippets. If there are any differences, the CI process will
fail.

This ensures that the checked in snippets are always up-to-date.

## Snippet tool documentation.

The Generate-Snippets.ps1 script has 3 parameters:

* -source_dir: The directory containing the source code to be parsed for snippets.
* -output_dir: The directory containing the files to be updated with the generated snippets.
* -verify: If specified, the script will verify that the generated snippets match the checked in snippets.

The script runs in two passes: The first pass parses the source code and identifies the snippets. The second pass
updates the output files with the generated snippets.

If two snippets have the same name, the snippet generation tool will fail. Similarly, if an output file 
references a snippet which cannot be found, the tool will fail.
