Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Docker.DotNet/JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public string Serialize<T>(T value)
return System.Text.Json.JsonSerializer.Serialize(value, JsonTypeInfoCache<T>.Value);
}

public string Serialize(object? value, Type type)
{
return System.Text.Json.JsonSerializer.Serialize(value, _options.GetTypeInfo(type));
}

public byte[] SerializeToUtf8Bytes<T>(T value)
{
return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(value, JsonTypeInfoCache<T>.Value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ContainerEventsParameters // (main.ContainerEventsParameters)
[QueryStringParameter("until", false)]
public string? Until { get; set; }

[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class ContainersListParameters // (main.ContainersListParameters)
[QueryStringBoolParameter("size", false)]
public bool? Size { get; set; }

[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class ContainersPruneParameters // (main.ContainersPruneParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
4 changes: 2 additions & 2 deletions src/Docker.DotNet/Models/ImageBuildParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ public class ImageBuildParameters // (main.ImageBuildParameters)
[QueryStringParameter("dockerfile", false)]
public string? Dockerfile { get; set; }

[QueryStringMapParameter<IDictionary<string, string>>("buildargs", false)]
[QueryStringMapParameter(typeof(IDictionary<string, string>), "buildargs", false)]
public IDictionary<string, string>? BuildArgs { get; set; }

[QueryStringMapParameter<IDictionary<string, string>>("labels", false)]
[QueryStringMapParameter(typeof(IDictionary<string, string>), "labels", false)]
public IDictionary<string, string>? Labels { get; set; }

[QueryStringBoolParameter("squash", false)]
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet/Models/ImagesListParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class ImagesListParameters // (main.ImagesListParameters)
[QueryStringBoolParameter("all", false)]
public bool? All { get; set; }

[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }

[QueryStringBoolParameter("shared-size", false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class ImagesPruneParameters // (main.ImagesPruneParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ImagesSearchParameters // (main.ImagesSearchParameters)
[QueryStringParameter("limit", false)]
public long? Limit { get; set; }

[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class NetworksDeleteUnusedParameters // (main.NetworksDeleteUnusedParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class NetworksListParameters // (main.NetworksListParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Docker.DotNet/Models/PluginListParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class PluginListParameters // (main.PluginListParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class ServiceListParameters // (main.ServiceListParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }

[QueryStringBoolParameter("status", false)]
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet/Models/TasksListParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class TasksListParameters // (main.TasksListParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class VolumesListParameters // (main.VolumesListParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class VolumesPruneParameters // (main.VolumesPruneParameters)
{
[QueryStringMapParameter<IDictionary<string, IDictionary<string, bool>>>("filters", false)]
[QueryStringMapParameter(typeof(IDictionary<string, IDictionary<string, bool>>), "filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
10 changes: 5 additions & 5 deletions src/Docker.DotNet/QueryStringMapParameterAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
namespace Docker.DotNet;

internal sealed class QueryStringMapParameterAttribute<T>(string name, bool required) : QueryStringParameterAttribute(name, required)
internal sealed class QueryStringMapParameterAttribute(Type type, string name, bool required) : QueryStringParameterAttribute(name, required)
{
public override IEnumerable<string> Convert(object value)
{
Debug.Assert(value != null);
Debug.Assert(value is T);
Debug.Assert(type.IsInstanceOfType(value));

if (value is not T typedValue)
if (!type.IsInstanceOfType(value))
{
throw new ArgumentException($"Expected value of type '{typeof(T)}'.", nameof(value));
throw new ArgumentException($"Expected value of type '{type}'.", nameof(value));
}

return [JsonSerializer.Instance.Serialize(typedValue)];
return [JsonSerializer.Instance.Serialize(value, type)];
}
}
22 changes: 19 additions & 3 deletions tools/Docker.DotNet.SourceAnalyzers/JsonSerializerAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override void Initialize(AnalysisContext context)
// Handle new JsonRequestContent<T>.
context.RegisterSyntaxNodeAction(AnalyzeObjectCreation, SyntaxKind.ObjectCreationExpression);

// Handle [QueryStringMapParameter<T>(...)].
// Handle [QueryStringMapParameter(typeof(T), ...)].
context.RegisterSyntaxNodeAction(AnalyzeAttribute, SyntaxKind.Attribute);
}

Expand Down Expand Up @@ -89,9 +89,25 @@ private static void AnalyzeAttribute(SyntaxNodeAnalysisContext context)
typeSymbol.Name == "QueryStringMapParameterAttribute" &&
typeSymbol.ContainingNamespace.ToDisplayString() == "Docker.DotNet";

if (isStjEntryPoint && typeSymbol.TypeArguments.Length > 0)
if (!isStjEntryPoint)
{
return;
}

// The mapped type is the first constructor argument: typeof(T).
var typeOfArgument = attribute.ArgumentList?.Arguments
.Select(arg => arg.Expression)
.OfType<TypeOfExpressionSyntax>()
.FirstOrDefault();

if (typeOfArgument == null)
{
return;
}

if (context.SemanticModel.GetTypeInfo(typeOfArgument.Type).Type is { } mappedType)
{
CheckAndReportType(context, typeSymbol.TypeArguments[0], attribute.GetLocation(), typeSymbol.Name);
CheckAndReportType(context, mappedType, attribute.GetLocation(), typeSymbol.Name);
}
}

Expand Down
5 changes: 4 additions & 1 deletion tools/specgen/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,17 +850,20 @@ func reflectTypeMembers(t reflect.Type, m *CSModelType) {
}

queryStringParameter := "QueryStringParameter"
var leadingArgs []CSArgument

switch f.Type.Kind() {
case reflect.Bool:
queryStringParameter = "QueryStringBoolParameter"
case reflect.Slice, reflect.Array:
queryStringParameter = "QueryStringListParameter"
case reflect.Map:
queryStringParameter = "QueryStringMapParameter<" + csProp.Type.Name + ">"
queryStringParameter = "QueryStringMapParameter"
leadingArgs = append(leadingArgs, CSArgument{Value: "typeof(" + csProp.Type.Name + ")"})
}

a := CSAttribute{Type: CSType{"", queryStringParameter}}
a.Arguments = append(a.Arguments, leadingArgs...)
a.Arguments = append(
a.Arguments,
CSArgument{
Expand Down