Skip to content

Commit

Permalink
Document syntax highlighting (#637)
Browse files Browse the repository at this point in the history
* copy code for StringSyntaxAttribute from original source

* document syntax highlighting

* add note on usage of GraphQLHttpClient

* add note on response type

* fix wording
  • Loading branch information
rose-a authored Apr 22, 2024
1 parent 79b0161 commit fd2cf06
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 10 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ The Library will try to follow the following standards and documents:
var graphQLClient = new GraphQLHttpClient("https://api.example.com/graphql", new NewtonsoftJsonSerializer());
```

> [!NOTE]
> *GraphQLHttpClient* is meant to be used as a single longlived instance per endpoint (i.e. register as singleton in a DI system), which should be reused for multiple requests.
### Create a GraphQLRequest:
#### Simple Request:
```csharp
Expand Down Expand Up @@ -64,7 +67,10 @@ var personAndFilmsRequest = new GraphQLRequest {
};
```

Be careful when using `byte[]` in your variables object, as most JSON serializers will treat that as binary data! If you really need to send a *list of bytes* with a `byte[]` as a source, then convert it to a `List<byte>` first, which will tell the serializer to output a list of numbers instead of a base64-encoded string.
> [!WARNING]
> Be careful when using `byte[]` in your variables object, as most JSON serializers will treat that as binary data.
>
> If you really need to send a *list of bytes* with a `byte[]` as a source, then convert it to a `List<byte>` first, which will tell the serializer to output a list of numbers instead of a base64-encoded string.
### Execute Query/Mutation:

Expand Down Expand Up @@ -100,6 +106,11 @@ var graphQLResponse = await graphQLClient.SendQueryAsync(personAndFilmsRequest,
var personName = graphQLResponse.Data.person.Name;
```

> [!IMPORTANT]
> Note that the field in the GraphQL response which gets deserialized into the response object is the `data` field.
>
> A common mistake is to try to directly use the `PersonType` class as response type (because thats the *thing* you actually want to query), but the returned response object contains a property `person` containing a `PersonType` object (like the `ResponseType` modelled above).
### Use Subscriptions

```csharp
Expand Down Expand Up @@ -141,6 +152,16 @@ var subscription = subscriptionStream.Subscribe(response =>
subscription.Dispose();
```

## Syntax Highlighting for GraphQL strings in IDEs

.NET 7.0 introduced the [StringSyntaxAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.stringsyntaxattribute?view=net-8.0) to have a unified way of telling what data is expected in a given `string` or `ReadOnlySpan<char>`. IDEs like Visual Studio and Rider can then use this to provide syntax highlighting and checking.

From v6.0.4 on all GraphQL string parameters in this library are decorated with the `[StringSyntax("GraphQL")]` attribute.

Currently, there is no native support for GraphQL formatting and syntax highlighting in Visual Studio, but the [GraphQLTools Extension](https://marketplace.visualstudio.com/items?itemName=codearchitects-research.GraphQLTools) provides that for you.

For Rider, JetBrains provides a [Plugin](https://plugins.jetbrains.com/plugin/8097-graphql), too.

## Useful Links:

* [StarWars Example Server (GitHub)](https://github.com/graphql/swapi-graphql)
Expand Down
69 changes: 60 additions & 9 deletions src/GraphQL.Primitives/StringSyntaxAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,72 @@
#if !NET7_0_OR_GREATER

// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace System.Diagnostics.CodeAnalysis;

/// <summary>
/// Stub
/// </summary>
/// <summary>Stub version of the StringSyntaxAttribute, which was introduced in .NET 7</summary>
public sealed class StringSyntaxAttribute : Attribute
{
// ReSharper disable once InconsistentNaming
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
/// <param name="syntax">The syntax identifier.</param>
public StringSyntaxAttribute(string syntax)
{
Syntax = syntax;
Arguments = Array.Empty<object?>();
}

/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
/// <param name="syntax">The syntax identifier.</param>
/// <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
public StringSyntaxAttribute(string syntax, params object?[] arguments)
{
Syntax = syntax;
Arguments = arguments;
}

/// <summary>Gets the identifier of the syntax used.</summary>
public string Syntax { get; }

/// <summary>Optional arguments associated with the specific syntax employed.</summary>
public object?[] Arguments { get; }

/// <summary>The syntax identifier for strings containing composite formats for string formatting.</summary>
#pragma warning disable IDE1006
public const string CompositeFormat = nameof(CompositeFormat);
#pragma warning restore IDE1006

#pragma warning disable IDE0060
public StringSyntaxAttribute(string syntax)
{ }
#pragma warning restore IDE0060
/// <summary>The syntax identifier for strings containing date format specifiers.</summary>
public const string DateOnlyFormat = nameof(DateOnlyFormat);

/// <summary>The syntax identifier for strings containing date and time format specifiers.</summary>
public const string DateTimeFormat = nameof(DateTimeFormat);

/// <summary>The syntax identifier for strings containing <see cref="Enum"/> format specifiers.</summary>
public const string EnumFormat = nameof(EnumFormat);

/// <summary>The syntax identifier for strings containing <see cref="Guid"/> format specifiers.</summary>
public const string GuidFormat = nameof(GuidFormat);

/// <summary>The syntax identifier for strings containing JavaScript Object Notation (JSON).</summary>
public const string Json = nameof(Json);

/// <summary>The syntax identifier for strings containing numeric format specifiers.</summary>
public const string NumericFormat = nameof(NumericFormat);

/// <summary>The syntax identifier for strings containing regular expressions.</summary>
public const string Regex = nameof(Regex);

/// <summary>The syntax identifier for strings containing time format specifiers.</summary>
public const string TimeOnlyFormat = nameof(TimeOnlyFormat);

/// <summary>The syntax identifier for strings containing <see cref="TimeSpan"/> format specifiers.</summary>
public const string TimeSpanFormat = nameof(TimeSpanFormat);

/// <summary>The syntax identifier for strings containing URIs.</summary>
public const string Uri = nameof(Uri);

/// <summary>The syntax identifier for strings containing XML.</summary>
public const string Xml = nameof(Xml);
#pragma warning restore IDE1006
}

#endif

0 comments on commit fd2cf06

Please sign in to comment.