mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 23:01:44 +01:00
commit
7d4aefe37e
@ -1,9 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp2.1;netcoreapp3.0</TargetFrameworks>
|
||||
<RootNamespace>Capnp</RootNamespace>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>Enable</Nullable>
|
||||
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
|
||||
<AssemblyName>Capnp.Net.Runtime</AssemblyName>
|
||||
<PackageId>Capnp.Net.Runtime</PackageId>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
|
@ -10,15 +10,15 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public static class CapnpSerializable
|
||||
{
|
||||
interface IConstructibleFromDeserializerState<out T>
|
||||
interface IConstructibleFromDeserializerState
|
||||
{
|
||||
T Create(DeserializerState state);
|
||||
object? Create(DeserializerState state);
|
||||
}
|
||||
|
||||
class FromStruct<T>: IConstructibleFromDeserializerState<T>
|
||||
class FromStruct<T>: IConstructibleFromDeserializerState
|
||||
where T : ICapnpSerializable, new()
|
||||
{
|
||||
public T Create(DeserializerState state)
|
||||
public object Create(DeserializerState state)
|
||||
{
|
||||
var result = new T();
|
||||
if (state.Kind != ObjectKind.Nil)
|
||||
@ -29,7 +29,7 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
|
||||
class FromList<T>: IConstructibleFromDeserializerState<IReadOnlyList<T>>
|
||||
class FromList<T>: IConstructibleFromDeserializerState
|
||||
where T: class
|
||||
{
|
||||
readonly Func<DeserializerState, T> _elementSerializer;
|
||||
@ -39,23 +39,23 @@ namespace Capnp
|
||||
_elementSerializer = (Func<DeserializerState, T>)GetSerializer(typeof(T));
|
||||
|
||||
}
|
||||
public IReadOnlyList<T> Create(DeserializerState state)
|
||||
public object Create(DeserializerState state)
|
||||
{
|
||||
return state.RequireList().Cast(_elementSerializer);
|
||||
}
|
||||
}
|
||||
|
||||
class FromCapability<T>: IConstructibleFromDeserializerState<T>
|
||||
class FromCapability<T>: IConstructibleFromDeserializerState
|
||||
where T: class
|
||||
{
|
||||
public T Create(DeserializerState state)
|
||||
public object? Create(DeserializerState state)
|
||||
{
|
||||
return state.RequireCap<T>();
|
||||
}
|
||||
}
|
||||
|
||||
static readonly ConditionalWeakTable<Type, Func<DeserializerState, object>> _typeMap =
|
||||
new ConditionalWeakTable<Type, Func<DeserializerState, object>>();
|
||||
static readonly ConditionalWeakTable<Type, Func<DeserializerState, object?>> _typeMap =
|
||||
new ConditionalWeakTable<Type, Func<DeserializerState, object?>>();
|
||||
|
||||
static CapnpSerializable()
|
||||
{
|
||||
@ -73,14 +73,14 @@ namespace Capnp
|
||||
_typeMap.Add(typeof(IReadOnlyList<double>), d => d.RequireList().CastDouble());
|
||||
}
|
||||
|
||||
static Func<DeserializerState, object> CreateSerializer(Type type)
|
||||
static Func<DeserializerState, object?> CreateSerializer(Type type)
|
||||
{
|
||||
if (typeof(ICapnpSerializable).IsAssignableFrom(type))
|
||||
{
|
||||
try
|
||||
{
|
||||
return ((IConstructibleFromDeserializerState<object>)
|
||||
Activator.CreateInstance(typeof(FromStruct<>).MakeGenericType(type))).Create;
|
||||
return ((IConstructibleFromDeserializerState)
|
||||
Activator.CreateInstance(typeof(FromStruct<>).MakeGenericType(type))!).Create;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -94,12 +94,12 @@ namespace Capnp
|
||||
try
|
||||
{
|
||||
var elementType = type.GetGenericArguments()[0];
|
||||
return ((IConstructibleFromDeserializerState<object>)
|
||||
Activator.CreateInstance(typeof(FromList<>).MakeGenericType(elementType))).Create;
|
||||
return ((IConstructibleFromDeserializerState)
|
||||
Activator.CreateInstance(typeof(FromList<>).MakeGenericType(elementType))!).Create;
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
throw ex.InnerException;
|
||||
throw ex.InnerException!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -123,8 +123,8 @@ namespace Capnp
|
||||
|
||||
try
|
||||
{
|
||||
return ((IConstructibleFromDeserializerState<object>)
|
||||
Activator.CreateInstance(typeof(FromCapability<>).MakeGenericType(type))).Create;
|
||||
return ((IConstructibleFromDeserializerState)
|
||||
Activator.CreateInstance(typeof(FromCapability<>).MakeGenericType(type))!).Create;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -135,7 +135,7 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
|
||||
static Func<DeserializerState, object> GetSerializer(Type type)
|
||||
static Func<DeserializerState, object?> GetSerializer(Type type)
|
||||
{
|
||||
return _typeMap.GetValue(type, CreateSerializer);
|
||||
}
|
||||
@ -148,26 +148,28 @@ namespace Capnp
|
||||
/// <item><description>Type implementing <see cref="ICapnpSerializable"/>. The type must must have a public parameterless constructor.</description></item>
|
||||
/// <item><description>A capability interface (<seealso cref="Rpc.InvalidCapabilityInterfaceException"/> for further explanation)</description></item>
|
||||
/// <item><description><see cref="String"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Boolean}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{SByte}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Byte}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Int16}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{UInt16}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Int32}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{UInt32}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Int64}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{UInt64}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Single}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{Double}"/></description></item>
|
||||
/// <item><description><see cref="IReadOnlyList{T}"/> whereby T is one of the things listed here.</description></item>
|
||||
/// <item><description><code>IReadOnlyList{Boolean}</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{SByte}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Byte}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Int16}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{UInt16}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Int32}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{UInt32}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Int64}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{UInt64}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Single}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{Double}"</code></description></item>
|
||||
/// <item><description><code>IReadOnlyList{T}</code> whereby T is one of the things listed here.</description></item>
|
||||
/// </list>
|
||||
/// </typeparam>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public static T Create<T>(DeserializerState state)
|
||||
/// <param name="state">deserializer state to construct from</param>
|
||||
/// <returns>The domain object instance. Nullability note: The returned reference will be null if (and only if) <typeparamref name="T"/> is a capability interface and
|
||||
/// <paramref name="state"/> represents the nil object (obtained from a null pointer). For all other types, when the state is nil,
|
||||
/// the method still constructs a valid but "empty" object instance (such as domain object without any properties set, empty string, empty list etc.)</returns>
|
||||
public static T? Create<T>(DeserializerState state)
|
||||
where T: class
|
||||
{
|
||||
return (T)GetSerializer(typeof(T))(state);
|
||||
return (T?)GetSerializer(typeof(T))(state);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -47,7 +48,7 @@ namespace Capnp
|
||||
/// <summary>
|
||||
/// The capabilities imported from the capability table. Only valid in RPC context.
|
||||
/// </summary>
|
||||
public IList<Rpc.ConsumedCapability> Caps { get; set; }
|
||||
public IList<Rpc.ConsumedCapability?>? Caps { get; set; }
|
||||
/// <summary>
|
||||
/// Current segment (essentially Segments[CurrentSegmentIndex]
|
||||
/// </summary>
|
||||
@ -83,11 +84,16 @@ namespace Capnp
|
||||
/// The conversion is cheap, since it does not involve copying any payload.
|
||||
/// </summary>
|
||||
/// <param name="state">The serializer state to be converted</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="state"/> is null</exception>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="state"/> is not bound to a MessageBuilder</exception>
|
||||
public static implicit operator DeserializerState(SerializerState state)
|
||||
{
|
||||
if (state == null)
|
||||
throw new ArgumentNullException(nameof(state));
|
||||
|
||||
if (state.MsgBuilder == null)
|
||||
throw new InvalidOperationException("state is not bound to a MessageBuilder");
|
||||
|
||||
switch (state.Kind)
|
||||
{
|
||||
case ObjectKind.ListOfBits:
|
||||
@ -100,7 +106,7 @@ namespace Capnp
|
||||
case ObjectKind.ListOfStructs:
|
||||
case ObjectKind.Nil:
|
||||
case ObjectKind.Struct:
|
||||
return new DeserializerState(state.Allocator.Segments)
|
||||
return new DeserializerState(state.Allocator!.Segments)
|
||||
{
|
||||
CurrentSegmentIndex = state.SegmentIndex,
|
||||
Offset = state.Offset,
|
||||
@ -112,7 +118,7 @@ namespace Capnp
|
||||
};
|
||||
|
||||
case ObjectKind.Capability:
|
||||
return new DeserializerState(state.Allocator.Segments)
|
||||
return new DeserializerState(state.Allocator!.Segments)
|
||||
{
|
||||
Kind = ObjectKind.Capability,
|
||||
Caps = state.Caps,
|
||||
@ -376,11 +382,11 @@ namespace Capnp
|
||||
/// the capability table. Does not mutate this state.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset relative to this.Offset within current segment</param>
|
||||
/// <returns>the low-level capability object</returns>
|
||||
/// <returns>the low-level capability object, or null if it is a null pointer</returns>
|
||||
/// <exception cref="IndexOutOfRangeException">offset negative or out of range</exception>
|
||||
/// <exception cref="InvalidOperationException">capability table not set</exception>
|
||||
/// <exception cref="Rpc.RpcException">not a capability pointer or invalid capability index</exception>
|
||||
internal Rpc.ConsumedCapability DecodeCapPointer(int offset)
|
||||
internal Rpc.ConsumedCapability? DecodeCapPointer(int offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
@ -490,7 +496,7 @@ namespace Capnp
|
||||
return state;
|
||||
}
|
||||
|
||||
internal Rpc.ConsumedCapability StructReadRawCap(int index)
|
||||
internal Rpc.ConsumedCapability? StructReadRawCap(int index)
|
||||
{
|
||||
if (Kind != ObjectKind.Struct && Kind != ObjectKind.Nil)
|
||||
throw new InvalidOperationException("Allowed on structs only");
|
||||
@ -567,7 +573,8 @@ namespace Capnp
|
||||
/// <exception cref="IndexOutOfRangeException">negative index</exception>
|
||||
/// <exception cref="DeserializationException">state does not represent a struct, invalid pointer,
|
||||
/// non-list-of-bytes pointer, traversal limit exceeded</exception>
|
||||
public string ReadText(int index, string defaultText = null)
|
||||
[return: NotNullIfNotNull("defaultText")]
|
||||
public string? ReadText(int index, string? defaultText = null)
|
||||
{
|
||||
return StructReadPointer(index).RequireList().CastText() ?? defaultText;
|
||||
}
|
||||
@ -646,7 +653,7 @@ namespace Capnp
|
||||
/// <exception cref="IndexOutOfRangeException">negative index</exception>
|
||||
/// <exception cref="DeserializationException">state does not represent a struct, invalid pointer,
|
||||
/// non-capability pointer, traversal limit exceeded</exception>
|
||||
public T ReadCap<T>(int index,
|
||||
public T? ReadCap<T>(int index,
|
||||
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
|
||||
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
|
||||
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) where T: class
|
||||
@ -677,7 +684,7 @@ namespace Capnp
|
||||
/// <returns>capability instance or null if pointer was null</returns>
|
||||
/// <exception cref="IndexOutOfRangeException">negative index</exception>
|
||||
/// <exception cref="DeserializationException">state does not represent a capability</exception>
|
||||
public T RequireCap<T>() where T: class
|
||||
public T? RequireCap<T>() where T: class
|
||||
{
|
||||
if (Kind == ObjectKind.Nil)
|
||||
return null;
|
||||
@ -685,7 +692,10 @@ namespace Capnp
|
||||
if (Kind != ObjectKind.Capability)
|
||||
throw new DeserializationException("Expected a capability");
|
||||
|
||||
return Rpc.CapabilityReflection.CreateProxy<T>(Caps[(int)CapabilityIndex]) as T;
|
||||
if (Caps == null)
|
||||
throw new InvalidOperationException("Capability table not set. This is a bug.");
|
||||
|
||||
return (Rpc.CapabilityReflection.CreateProxy<T>(Caps[(int)CapabilityIndex]) as T)!;
|
||||
}
|
||||
}
|
||||
}
|
@ -144,7 +144,7 @@ namespace Capnp
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<object>]]></code> whereby each list item is one of the things listed here.</description></item>
|
||||
/// </list>
|
||||
/// </param>
|
||||
public void SetObject(object obj)
|
||||
public void SetObject(object? obj)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
|
@ -2,9 +2,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@ -22,7 +20,7 @@ namespace Capnp
|
||||
|
||||
int _disposing;
|
||||
readonly Stream _stream;
|
||||
readonly BinaryWriter _writer;
|
||||
readonly BinaryWriter? _writer;
|
||||
readonly object _writeLock = new object();
|
||||
readonly List<IFrameTracer> _tracers = new List<IFrameTracer>();
|
||||
|
||||
@ -62,7 +60,7 @@ namespace Capnp
|
||||
/// <summary>
|
||||
/// Event handler for frame reception.
|
||||
/// </summary>
|
||||
public event Action<WireFrame> FrameReceived;
|
||||
public event Action<WireFrame>? FrameReceived;
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message over the stream.
|
||||
|
@ -10,7 +10,7 @@ namespace Capnp
|
||||
{
|
||||
static class GenericCasts<T>
|
||||
{
|
||||
public static Func<ListDeserializer, T> CastFunc;
|
||||
public static Func<ListDeserializer, T>? CastFunc;
|
||||
}
|
||||
|
||||
static ListDeserializer()
|
||||
|
@ -73,7 +73,7 @@ namespace Capnp
|
||||
/// <param name="items">List content. Can be null in which case the list is simply not initialized.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items.</exception>
|
||||
public void Init(IReadOnlyList<bool> items)
|
||||
public void Init(IReadOnlyList<bool>? items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -29,7 +28,7 @@ namespace Capnp
|
||||
if (index < 0 || index >= Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return Rpc.CapabilityReflection.CreateProxy<T>(State.DecodeCapPointer(index)) as T;
|
||||
return (Rpc.CapabilityReflection.CreateProxy<T>(State.DecodeCapPointer(index)) as T)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -11,7 +11,7 @@ namespace Capnp
|
||||
/// <typeparam name="T">Capability interface</typeparam>
|
||||
public class ListOfCapsSerializer<T> :
|
||||
SerializerState,
|
||||
IReadOnlyList<T>
|
||||
IReadOnlyList<T?>
|
||||
where T : class
|
||||
{
|
||||
/// <summary>
|
||||
@ -32,9 +32,10 @@ namespace Capnp
|
||||
/// <returns>Proxy object of capability at given element index</returns>
|
||||
/// <exception cref="InvalidOperationException">List was not initialized, or attempting to overwrite an already set element.</exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||
[AllowNull]
|
||||
public T this[int index]
|
||||
{
|
||||
get => Rpc.CapabilityReflection.CreateProxy<T>(DecodeCapPointer(index)) as T;
|
||||
get => (Rpc.CapabilityReflection.CreateProxy<T>(DecodeCapPointer(index)) as T)!;
|
||||
set
|
||||
{
|
||||
if (!IsAllocated)
|
||||
@ -43,10 +44,7 @@ namespace Capnp
|
||||
if (index < 0 || index >= RawData.Length)
|
||||
throw new IndexOutOfRangeException("index out of range");
|
||||
|
||||
uint id = ProvideCapability(value);
|
||||
WirePointer ptr = default;
|
||||
ptr.SetCapability(id);
|
||||
RawData[index] = id;
|
||||
RawData[index] = ProvideCapability(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +65,7 @@ namespace Capnp
|
||||
/// <param name="caps">List content. Can be null in which case the list is simply not initialized.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items.</exception>
|
||||
public void Init(IReadOnlyList<T> caps)
|
||||
public void Init(IReadOnlyList<T?>? caps)
|
||||
{
|
||||
if (caps == null)
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -12,7 +10,7 @@ namespace Capnp
|
||||
/// <typeparam name="TS">SerializerState which represents the element type</typeparam>
|
||||
public class ListOfPointersSerializer<TS>:
|
||||
SerializerState,
|
||||
IReadOnlyList<TS>
|
||||
IReadOnlyList<TS?>
|
||||
where TS: SerializerState, new()
|
||||
{
|
||||
/// <summary>
|
||||
@ -51,7 +49,7 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public int Count => ListElementCount;
|
||||
|
||||
IEnumerable<TS> Enumerate()
|
||||
IEnumerable<TS?> Enumerate()
|
||||
{
|
||||
int count = Count;
|
||||
|
||||
@ -64,7 +62,7 @@ namespace Capnp
|
||||
/// <summary>
|
||||
/// Implements <see cref="IEnumerable{TS}"/>.
|
||||
/// </summary>
|
||||
public IEnumerator<TS> GetEnumerator()
|
||||
public IEnumerator<TS?> GetEnumerator()
|
||||
{
|
||||
return Enumerate().GetEnumerator();
|
||||
}
|
||||
@ -94,7 +92,7 @@ namespace Capnp
|
||||
/// <param name="init">Serialization action to transfer a particular item into the serializer state.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items.</exception>
|
||||
public void Init<T>(IReadOnlyList<T> items, Action<TS, T> init)
|
||||
public void Init<T>(IReadOnlyList<T>? items, Action<TS, T> init)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
@ -115,4 +113,3 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -70,7 +69,7 @@ namespace Capnp
|
||||
/// <param name="items">List content. Can be null in which case the list is simply not initialized.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items.</exception>
|
||||
public void Init(IReadOnlyList<T> items)
|
||||
public void Init(IReadOnlyList<T>? items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ namespace Capnp
|
||||
/// <param name="init">Serialization action to transfer a particular item into the serializer state.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items.</exception>
|
||||
public void Init<T>(IReadOnlyList<T> items, Action<TS, T> init)
|
||||
public void Init<T>(IReadOnlyList<T>? items, Action<TS, T> init)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public class ListOfTextSerializer :
|
||||
SerializerState,
|
||||
IReadOnlyList<string>
|
||||
IReadOnlyList<string?>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text at given index. Once an element is set, it cannot be overwritten.
|
||||
@ -18,7 +18,7 @@ namespace Capnp
|
||||
/// <exception cref="InvalidOperationException">List is not initialized</exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">UTF-8 encoding exceeds 2^29-2 bytes</exception>
|
||||
public string this[int index]
|
||||
public string? this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -47,7 +47,7 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public int Count => ListElementCount;
|
||||
|
||||
IEnumerable<string> Enumerate()
|
||||
IEnumerable<string?> Enumerate()
|
||||
{
|
||||
int count = Count;
|
||||
|
||||
@ -60,7 +60,7 @@ namespace Capnp
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IEnumerable{String}"/>/>
|
||||
/// </summary>
|
||||
public IEnumerator<string> GetEnumerator()
|
||||
public IEnumerator<string?> GetEnumerator()
|
||||
{
|
||||
return Enumerate().GetEnumerator();
|
||||
}
|
||||
@ -88,7 +88,7 @@ namespace Capnp
|
||||
/// <param name="items">List content. Can be null in which case the list is simply not initialized.</param>
|
||||
/// <exception cref="InvalidOperationException">The list was already initialized</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">More than 2^29-1 items, or the UTF-8 encoding of an individual string requires more than 2^29-2 bytes.</exception>
|
||||
public void Init(IReadOnlyList<string> items)
|
||||
public void Init(IReadOnlyList<string?>? items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
@ -109,4 +109,3 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -12,7 +10,7 @@ namespace Capnp
|
||||
{
|
||||
readonly ISegmentAllocator _allocator;
|
||||
readonly DynamicSerializerState _rootPtrBuilder;
|
||||
List<Rpc.ConsumedCapability> _capTable;
|
||||
List<Rpc.ConsumedCapability?>? _capTable;
|
||||
|
||||
MessageBuilder(ISegmentAllocator allocator)
|
||||
{
|
||||
@ -56,10 +54,11 @@ namespace Capnp
|
||||
/// Gets or sets the root object. The root object must be set exactly once per message.
|
||||
/// Setting it manually is only required (and allowed) when it was created with <see cref="CreateObject{TS}"/>.
|
||||
/// </summary>
|
||||
public SerializerState Root
|
||||
/// <exception cref="ArgumentNullException">Attempt to set null reference</exception>
|
||||
public SerializerState? Root
|
||||
{
|
||||
get => _rootPtrBuilder.TryGetPointer(0);
|
||||
set => _rootPtrBuilder.Link(0, value);
|
||||
set => _rootPtrBuilder.Link(0, value ?? throw new ArgumentNullException(nameof(value)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -90,13 +89,13 @@ namespace Capnp
|
||||
if (_capTable != null)
|
||||
throw new InvalidOperationException("Capability table was already initialized");
|
||||
|
||||
_capTable = new List<Rpc.ConsumedCapability>();
|
||||
_capTable = new List<Rpc.ConsumedCapability?>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this message builder's segment allocator.
|
||||
/// </summary>
|
||||
public ISegmentAllocator Allocator => _allocator;
|
||||
internal List<Rpc.ConsumedCapability> Caps => _capTable;
|
||||
internal List<Rpc.ConsumedCapability?>? Caps => _capTable;
|
||||
}
|
||||
}
|
140
Capnp.Net.Runtime/NullableAttributes.cs
Normal file
140
Capnp.Net.Runtime/NullableAttributes.cs
Normal file
@ -0,0 +1,140 @@
|
||||
#pragma warning disable MA0048 // File name must match type name
|
||||
#define INTERNAL_NULLABLE_ATTRIBUTES
|
||||
#if NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NET45 || NET451 || NET452 || NET6 || NET461 || NET462 || NET47 || NET471 || NET472 || NET48
|
||||
|
||||
// https://github.com/dotnet/corefx/blob/48363ac826ccf66fbe31a5dcb1dc2aab9a7dd768/src/Common/src/CoreLib/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class AllowNullAttribute : Attribute
|
||||
{ }
|
||||
|
||||
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class DisallowNullAttribute : Attribute
|
||||
{ }
|
||||
|
||||
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class MaybeNullAttribute : Attribute
|
||||
{ }
|
||||
|
||||
/// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class NotNullAttribute : Attribute
|
||||
{ }
|
||||
|
||||
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class MaybeNullWhenAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the specified return value condition.</summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value, the associated parameter may be null.
|
||||
/// </param>
|
||||
public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
|
||||
|
||||
/// <summary>Gets the return value condition.</summary>
|
||||
public bool ReturnValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class NotNullWhenAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the specified return value condition.</summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value, the associated parameter will not be null.
|
||||
/// </param>
|
||||
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
|
||||
|
||||
/// <summary>Gets the return value condition.</summary>
|
||||
public bool ReturnValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class NotNullIfNotNullAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the associated parameter name.</summary>
|
||||
/// <param name="parameterName">
|
||||
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
|
||||
/// </param>
|
||||
public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
|
||||
|
||||
/// <summary>Gets the associated parameter name.</summary>
|
||||
public string ParameterName { get; }
|
||||
}
|
||||
|
||||
/// <summary>Applied to a method that will never return under any circumstance.</summary>
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class DoesNotReturnAttribute : Attribute
|
||||
{ }
|
||||
|
||||
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if INTERNAL_NULLABLE_ATTRIBUTES
|
||||
internal
|
||||
#else
|
||||
public
|
||||
#endif
|
||||
sealed class DoesNotReturnIfAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the specified parameter value.</summary>
|
||||
/// <param name="parameterValue">
|
||||
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
|
||||
/// the associated parameter matches this value.
|
||||
/// </param>
|
||||
public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
|
||||
|
||||
/// <summary>Gets the condition parameter value.</summary>
|
||||
public bool ParameterValue { get; }
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
@ -8,7 +6,7 @@ namespace Capnp
|
||||
{
|
||||
class Coder<T>
|
||||
{
|
||||
public static Func<T, T, T> Fn { get; set; }
|
||||
public static Func<T, T, T>? Fn { get; set; }
|
||||
}
|
||||
|
||||
static PrimitiveCoder()
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -33,11 +33,11 @@
|
||||
/// <summary>
|
||||
/// SerializerState, if applicable
|
||||
/// </summary>
|
||||
public SerializerState Answer => _obj as SerializerState;
|
||||
public SerializerState? Answer => _obj as SerializerState;
|
||||
|
||||
/// <summary>
|
||||
/// PendingQuestion, if applicable
|
||||
/// </summary>
|
||||
public PendingQuestion Counterquestion => _obj as PendingQuestion;
|
||||
public PendingQuestion? Counterquestion => _obj as PendingQuestion;
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
/// Constructs an instance and binds it to the given low-level capability.
|
||||
/// </summary>
|
||||
/// <param name="cap">low-level capability</param>
|
||||
public BareProxy(ConsumedCapability cap): base(cap)
|
||||
public BareProxy(ConsumedCapability? cap): base(cap)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@ -110,7 +109,7 @@ namespace Capnp.Rpc
|
||||
|
||||
return (SkeletonFactory)Activator.CreateInstance(
|
||||
typeof(SkeletonFactory<>)
|
||||
.MakeGenericType(skeletonClass));
|
||||
.MakeGenericType(skeletonClass))!;
|
||||
}
|
||||
|
||||
static SkeletonFactory GetSkeletonFactory(Type type)
|
||||
@ -190,7 +189,7 @@ namespace Capnp.Rpc
|
||||
|
||||
return (ProxyFactory)Activator.CreateInstance(
|
||||
typeof(ProxyFactory<>)
|
||||
.MakeGenericType(proxyClass));
|
||||
.MakeGenericType(proxyClass))!;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -263,7 +262,7 @@ namespace Capnp.Rpc
|
||||
/// <exception cref="System.Reflection.TargetInvocationException">Problem with instatiating the Proxy (constructor threw exception).</exception>
|
||||
/// <exception cref="MemberAccessException">Caller does not have permission to invoke the Proxy constructor.</exception>
|
||||
/// <exception cref="TypeLoadException">Problem with building the Proxy type, or problem with loading some dependent class.</exception>
|
||||
public static Proxy CreateProxy<TInterface>(ConsumedCapability cap,
|
||||
public static Proxy CreateProxy<TInterface>(ConsumedCapability? cap,
|
||||
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
|
||||
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
|
||||
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
namespace Capnp.Rpc
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for a low-level capability at consumer side. It is created by the <see cref="RpcEngine"/>. An application does not directly interact with it
|
||||
@ -18,7 +14,7 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
protected abstract void ReleaseRemotely();
|
||||
internal abstract void Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer);
|
||||
internal abstract void Freeze(out IRpcEndpoint boundEndpoint);
|
||||
internal abstract void Freeze(out IRpcEndpoint? boundEndpoint);
|
||||
internal abstract void Unfreeze();
|
||||
|
||||
internal abstract void AddRef();
|
||||
|
@ -22,6 +22,6 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
/// <param name="access">Path to the desired capability inside the result struct.</param>
|
||||
/// <returns>Pipelined low-level capability</returns>
|
||||
ConsumedCapability Access(MemberAccessPath access);
|
||||
ConsumedCapability? Access(MemberAccessPath access);
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
|
@ -11,7 +11,7 @@ namespace Capnp.Rpc
|
||||
public static class Impatient
|
||||
{
|
||||
static readonly ConditionalWeakTable<Task, IPromisedAnswer> _taskTable = new ConditionalWeakTable<Task, IPromisedAnswer>();
|
||||
static readonly ThreadLocal<IRpcEndpoint> _askingEndpoint = new ThreadLocal<IRpcEndpoint>();
|
||||
static readonly ThreadLocal<IRpcEndpoint?> _askingEndpoint = new ThreadLocal<IRpcEndpoint?>();
|
||||
|
||||
/// <summary>
|
||||
/// Attaches a continuation to the given promise and registers the resulting task for pipelining.
|
||||
@ -51,7 +51,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
else if (rtask.IsFaulted)
|
||||
{
|
||||
rtask = Task.FromException<T>(rtask.Exception.InnerException);
|
||||
rtask = Task.FromException<T>(rtask.Exception!.InnerException!);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -86,7 +86,7 @@ namespace Capnp.Rpc
|
||||
return answer;
|
||||
}
|
||||
|
||||
internal static IPromisedAnswer TryGetAnswer(Task task)
|
||||
internal static IPromisedAnswer? TryGetAnswer(Task task)
|
||||
{
|
||||
_taskTable.TryGetValue(task, out var answer);
|
||||
return answer;
|
||||
@ -102,10 +102,10 @@ namespace Capnp.Rpc
|
||||
return proxy;
|
||||
|
||||
case null:
|
||||
return null;
|
||||
return CapabilityReflection.CreateProxy<T>(null);
|
||||
}
|
||||
|
||||
var skel = Skeleton.GetOrCreateSkeleton(item, false);
|
||||
var skel = Skeleton.GetOrCreateSkeleton(item!, false);
|
||||
var localCap = LocalCapability.Create(skel);
|
||||
return CapabilityReflection.CreateProxy<T>(localCap);
|
||||
}
|
||||
@ -131,7 +131,7 @@ namespace Capnp.Rpc
|
||||
where TInterface : class
|
||||
{
|
||||
var lazyCap = new LazyCapability(AwaitProxy(task));
|
||||
return CapabilityReflection.CreateProxy<TInterface>(lazyCap, memberName, sourceFilePath, sourceLineNumber) as TInterface;
|
||||
return (CapabilityReflection.CreateProxy<TInterface>(lazyCap, memberName, sourceFilePath, sourceLineNumber) as TInterface)!;
|
||||
}
|
||||
|
||||
static readonly MemberAccessPath Path_OneAndOnly = new MemberAccessPath(0U);
|
||||
@ -168,15 +168,15 @@ namespace Capnp.Rpc
|
||||
}
|
||||
|
||||
var lazyCap = new LazyCapability(AwaitProxy(task));
|
||||
return CapabilityReflection.CreateProxy<TInterface>(lazyCap) as TInterface;
|
||||
return (CapabilityReflection.CreateProxy<TInterface>(lazyCap) as TInterface)!;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CapabilityReflection.CreateProxy<TInterface>(answer.Access(Path_OneAndOnly)) as TInterface;
|
||||
return (CapabilityReflection.CreateProxy<TInterface>(answer.Access(Path_OneAndOnly)) as TInterface)!;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IRpcEndpoint AskingEndpoint
|
||||
internal static IRpcEndpoint? AskingEndpoint
|
||||
{
|
||||
get => _askingEndpoint.Value;
|
||||
set { _askingEndpoint.Value = value; }
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
namespace Capnp.Rpc
|
||||
{
|
||||
/// <summary>
|
||||
/// Low-level capability which as imported from a remote peer.
|
||||
|
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -34,7 +31,7 @@ namespace Capnp.Rpc.Interception
|
||||
return new Proxy(Access(access));
|
||||
}
|
||||
|
||||
public ConsumedCapability Access(MemberAccessPath access)
|
||||
public ConsumedCapability? Access(MemberAccessPath access)
|
||||
{
|
||||
if (_futureResult.Task.IsCompleted)
|
||||
{
|
||||
@ -44,7 +41,7 @@ namespace Capnp.Rpc.Interception
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -107,7 +104,7 @@ namespace Capnp.Rpc.Interception
|
||||
/// <summary>
|
||||
/// Input arguments
|
||||
/// </summary>
|
||||
public SerializerState InArgs { get; set; }
|
||||
public SerializerState? InArgs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output arguments ("return value")
|
||||
@ -117,7 +114,7 @@ namespace Capnp.Rpc.Interception
|
||||
/// <summary>
|
||||
/// Exception text, or null if there is no exception
|
||||
/// </summary>
|
||||
public string Exception { get; set; }
|
||||
public string? Exception { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the call should return in canceled state to Alice (the original caller).
|
||||
@ -156,7 +153,7 @@ namespace Capnp.Rpc.Interception
|
||||
/// <item><description>null</description></item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public object Bob
|
||||
public object? Bob
|
||||
{
|
||||
get => _bob;
|
||||
set
|
||||
@ -196,11 +193,11 @@ namespace Capnp.Rpc.Interception
|
||||
}
|
||||
}
|
||||
|
||||
internal Proxy BobProxy { get; private set; }
|
||||
internal Proxy? BobProxy { get; private set; }
|
||||
|
||||
readonly CensorCapability _censorCapability;
|
||||
PromisedAnswer _promisedAnswer;
|
||||
object _bob;
|
||||
object? _bob;
|
||||
|
||||
internal IPromisedAnswer Answer => _promisedAnswer;
|
||||
|
||||
@ -224,8 +221,13 @@ namespace Capnp.Rpc.Interception
|
||||
{
|
||||
for (int i = 0; i < state.Caps.Count; i++)
|
||||
{
|
||||
state.Caps[i] = policy.Attach(state.Caps[i]);
|
||||
state.Caps[i].AddRef();
|
||||
var cap = state.Caps[i];
|
||||
if (cap != null)
|
||||
{
|
||||
cap = policy.Attach(cap);
|
||||
state.Caps[i] = cap;
|
||||
cap.AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -236,8 +238,13 @@ namespace Capnp.Rpc.Interception
|
||||
{
|
||||
for (int i = 0; i < state.Caps.Count; i++)
|
||||
{
|
||||
state.Caps[i] = policy.Detach(state.Caps[i]);
|
||||
state.Caps[i].AddRef();
|
||||
var cap = state.Caps[i];
|
||||
if (cap != null)
|
||||
{
|
||||
cap = policy.Detach(cap);
|
||||
state.Caps[i] = cap;
|
||||
cap.AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,8 +253,12 @@ namespace Capnp.Rpc.Interception
|
||||
/// Intercepts all capabilies inside the input arguments
|
||||
/// </summary>
|
||||
/// <param name="policyOverride">Policy to use, or null to further use present policy</param>
|
||||
public void InterceptInCaps(IInterceptionPolicy policyOverride = null)
|
||||
/// <exception cref="InvalidOperationException">InArgs not set</exception>
|
||||
public void InterceptInCaps(IInterceptionPolicy? policyOverride = null)
|
||||
{
|
||||
if (InArgs == null)
|
||||
throw new InvalidOperationException("InArgs not set");
|
||||
|
||||
InterceptCaps(InArgs, policyOverride ?? _censorCapability.Policy);
|
||||
}
|
||||
|
||||
@ -255,7 +266,7 @@ namespace Capnp.Rpc.Interception
|
||||
/// Intercepts all capabilies inside the output arguments
|
||||
/// </summary>
|
||||
/// <param name="policyOverride">Policy to use, or null to further use present policy</param>
|
||||
public void InterceptOutCaps(IInterceptionPolicy policyOverride = null)
|
||||
public void InterceptOutCaps(IInterceptionPolicy? policyOverride = null)
|
||||
{
|
||||
InterceptCaps(OutArgs, policyOverride ?? _censorCapability.Policy);
|
||||
}
|
||||
@ -264,8 +275,12 @@ namespace Capnp.Rpc.Interception
|
||||
/// Unintercepts all capabilies inside the input arguments
|
||||
/// </summary>
|
||||
/// <param name="policyOverride">Policy to remove, or null to remove present policy</param>
|
||||
public void UninterceptInCaps(IInterceptionPolicy policyOverride = null)
|
||||
/// <exception cref="InvalidOperationException">InArgs not set</exception>
|
||||
public void UninterceptInCaps(IInterceptionPolicy? policyOverride = null)
|
||||
{
|
||||
if (InArgs == null)
|
||||
throw new InvalidOperationException("InArgs not set");
|
||||
|
||||
UninterceptCaps(InArgs, policyOverride ?? _censorCapability.Policy);
|
||||
}
|
||||
|
||||
@ -273,7 +288,7 @@ namespace Capnp.Rpc.Interception
|
||||
/// Unintercepts all capabilies inside the output arguments
|
||||
/// </summary>
|
||||
/// <param name="policyOverride">Policy to remove, or null to remove present policy</param>
|
||||
public void UninterceptOutCaps(IInterceptionPolicy policyOverride = null)
|
||||
public void UninterceptOutCaps(IInterceptionPolicy? policyOverride = null)
|
||||
{
|
||||
UninterceptCaps(OutArgs, policyOverride ?? _censorCapability.Policy);
|
||||
}
|
||||
@ -281,14 +296,16 @@ namespace Capnp.Rpc.Interception
|
||||
/// <summary>
|
||||
/// Forwards this intercepted call to the target capability ("Bob").
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">Bob/InArgs not set</exception>
|
||||
public void ForwardToBob()
|
||||
{
|
||||
if (Bob == null)
|
||||
{
|
||||
throw new InvalidOperationException("Bob is null");
|
||||
}
|
||||
|
||||
var answer = BobProxy.Call(InterfaceId, MethodId, InArgs.Rewrap<DynamicSerializerState>(), default, CancelToBob);
|
||||
if (InArgs == null)
|
||||
throw new InvalidOperationException("InArgs not set");
|
||||
|
||||
var answer = BobProxy!.Call(InterfaceId, MethodId, InArgs.Rewrap<DynamicSerializerState>(), default, CancelToBob);
|
||||
|
||||
State = InterceptionState.ForwardedToBob;
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
writer.SenderHosted = endpoint.AllocateExport(MyVine, out bool _);
|
||||
}
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
boundEndpoint = null;
|
||||
}
|
||||
|
@ -45,16 +45,16 @@ namespace Capnp.Rpc.Interception
|
||||
switch (cap)
|
||||
{
|
||||
case Proxy proxy:
|
||||
return CapabilityReflection.CreateProxy<TCap>(Attach(policy, proxy.ConsumedCap)) as TCap;
|
||||
return (CapabilityReflection.CreateProxy<TCap>(Attach(policy, proxy.ConsumedCap!)) as TCap)!;
|
||||
|
||||
case ConsumedCapability ccap:
|
||||
return new CensorCapability(ccap, policy) as TCap;
|
||||
return (new CensorCapability(ccap, policy) as TCap)!;
|
||||
|
||||
default:
|
||||
return Attach(policy,
|
||||
CapabilityReflection.CreateProxy<TCap>(
|
||||
return (Attach(policy,
|
||||
(CapabilityReflection.CreateProxy<TCap>(
|
||||
LocalCapability.Create(
|
||||
Skeleton.GetOrCreateSkeleton(cap, false))) as TCap);
|
||||
Skeleton.GetOrCreateSkeleton(cap, false))) as TCap)!));
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,11 +79,11 @@ namespace Capnp.Rpc.Interception
|
||||
switch (cap)
|
||||
{
|
||||
case Proxy proxy:
|
||||
return CapabilityReflection.CreateProxy<TCap>(Detach(policy, proxy.ConsumedCap)) as TCap;
|
||||
return (CapabilityReflection.CreateProxy<TCap>(Detach(policy, proxy.ConsumedCap!)) as TCap)!;
|
||||
|
||||
case CensorCapability ccap:
|
||||
{
|
||||
var cur = ccap;
|
||||
CensorCapability? cur = ccap;
|
||||
var stk = new Stack<IInterceptionPolicy>();
|
||||
|
||||
do
|
||||
@ -96,7 +96,7 @@ namespace Capnp.Rpc.Interception
|
||||
{
|
||||
cur2 = p.Attach(cur2);
|
||||
}
|
||||
return cur2 as TCap;
|
||||
return (cur2 as TCap)!;
|
||||
}
|
||||
|
||||
stk.Push(cur.Policy);
|
||||
@ -104,7 +104,7 @@ namespace Capnp.Rpc.Interception
|
||||
}
|
||||
while (cur != null);
|
||||
|
||||
return ccap as TCap;
|
||||
return (ccap as TCap)!;
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -27,7 +27,7 @@ namespace Capnp.Rpc
|
||||
WhenResolved = capabilityTask;
|
||||
}
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
if (WhenResolved.IsCompleted)
|
||||
{
|
||||
@ -37,7 +37,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -15,7 +15,7 @@ namespace Capnp.Rpc
|
||||
_access = access;
|
||||
}
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
boundEndpoint = null;
|
||||
}
|
||||
@ -43,7 +43,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
|
||||
using (var proxy = new Proxy(_access.Eval(result)))
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -14,7 +13,7 @@ namespace Capnp.Rpc
|
||||
public static ConsumedCapability Create(Skeleton skeleton)
|
||||
{
|
||||
if (skeleton is Vine vine)
|
||||
return vine.Proxy.ConsumedCap;
|
||||
return vine.Proxy.ConsumedCap!;
|
||||
else
|
||||
return _localCaps.GetValue(skeleton, _ => new LocalCapability(_));
|
||||
}
|
||||
@ -22,7 +21,7 @@ namespace Capnp.Rpc
|
||||
static async Task<DeserializerState> AwaitAnswer(Task<AnswerOrCounterquestion> call)
|
||||
{
|
||||
var aorcq = await call;
|
||||
return aorcq.Answer ?? await aorcq.Counterquestion.WhenReturned;
|
||||
return aorcq.Answer ?? await aorcq.Counterquestion!.WhenReturned;
|
||||
}
|
||||
|
||||
public Skeleton ProvidedCap { get; }
|
||||
@ -55,7 +54,7 @@ namespace Capnp.Rpc
|
||||
capDesc.SenderHosted = endpoint.AllocateExport(ProvidedCap, out bool _);
|
||||
}
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
boundEndpoint = null;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ namespace Capnp.Rpc
|
||||
/// <param name="rpcState">The object (usually "params struct") on which to evaluate this path.</param>
|
||||
/// <returns>Resulting low-level capability</returns>
|
||||
/// <exception cref="DeserializationException">Evaluation of this path did not give a capability</exception>
|
||||
public ConsumedCapability Eval(DeserializerState rpcState)
|
||||
public ConsumedCapability? Eval(DeserializerState rpcState)
|
||||
{
|
||||
var cur = rpcState;
|
||||
|
||||
@ -184,7 +184,7 @@ namespace Capnp.Rpc
|
||||
return null;
|
||||
|
||||
case ObjectKind.Capability:
|
||||
return rpcState.Caps[(int)cur.CapabilityIndex];
|
||||
return rpcState.Caps![(int)cur.CapabilityIndex];
|
||||
|
||||
default:
|
||||
throw new DeserializationException("Access path did not result in a capability");
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -8,14 +7,14 @@ namespace Capnp.Rpc
|
||||
class PendingAnswer: IDisposable
|
||||
{
|
||||
readonly object _reentrancyBlocker = new object();
|
||||
readonly CancellationTokenSource _cts;
|
||||
readonly CancellationTokenSource? _cts;
|
||||
readonly TaskCompletionSource<int> _whenCanceled;
|
||||
Task<AnswerOrCounterquestion> _callTask;
|
||||
Task _initialTask;
|
||||
Task _chainedTask;
|
||||
Task? _initialTask;
|
||||
Task? _chainedTask;
|
||||
bool _disposed;
|
||||
|
||||
public PendingAnswer(Task<AnswerOrCounterquestion> callTask, CancellationTokenSource cts)
|
||||
public PendingAnswer(Task<AnswerOrCounterquestion> callTask, CancellationTokenSource? cts)
|
||||
{
|
||||
_cts = cts;
|
||||
_callTask = callTask ?? throw new ArgumentNullException(nameof(callTask));
|
||||
@ -138,7 +137,7 @@ namespace Capnp.Rpc
|
||||
case ObjectKind.Capability:
|
||||
try
|
||||
{
|
||||
var cap = aorcq.Answer.Caps[(int)cur.CapabilityIndex];
|
||||
var cap = aorcq.Answer.Caps![(int)cur.CapabilityIndex];
|
||||
proxy = new Proxy(cap ?? LazyCapability.Null);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
@ -154,7 +153,7 @@ namespace Capnp.Rpc
|
||||
else
|
||||
{
|
||||
var path = MemberAccessPath.Deserialize(rd);
|
||||
var cap = new RemoteAnswerCapability(aorcq.Counterquestion, path);
|
||||
var cap = new RemoteAnswerCapability(aorcq.Counterquestion!, path);
|
||||
return new Proxy(cap);
|
||||
}
|
||||
}
|
||||
@ -169,7 +168,7 @@ namespace Capnp.Rpc
|
||||
{
|
||||
if (_cts != null)
|
||||
{
|
||||
Task chainedTask;
|
||||
Task? chainedTask;
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
@ -61,11 +59,11 @@ namespace Capnp.Rpc
|
||||
|
||||
readonly TaskCompletionSource<DeserializerState> _tcs = new TaskCompletionSource<DeserializerState>();
|
||||
readonly uint _questionId;
|
||||
ConsumedCapability _target;
|
||||
SerializerState _inParams;
|
||||
ConsumedCapability? _target;
|
||||
SerializerState? _inParams;
|
||||
int _inhibitFinishCounter;
|
||||
|
||||
internal PendingQuestion(IRpcEndpoint ep, uint id, ConsumedCapability target, SerializerState inParams)
|
||||
internal PendingQuestion(IRpcEndpoint ep, uint id, ConsumedCapability? target, SerializerState? inParams)
|
||||
{
|
||||
RpcEndpoint = ep ?? throw new ArgumentNullException(nameof(ep));
|
||||
_questionId = id;
|
||||
@ -75,7 +73,7 @@ namespace Capnp.Rpc
|
||||
|
||||
if (inParams != null)
|
||||
{
|
||||
foreach (var cap in inParams.Caps)
|
||||
foreach (var cap in inParams.Caps!)
|
||||
{
|
||||
cap?.AddRef();
|
||||
}
|
||||
@ -236,7 +234,7 @@ namespace Capnp.Rpc
|
||||
/// <param name="access">Access path</param>
|
||||
/// <returns>Low-level capability</returns>
|
||||
/// <exception cref="DeserializationException">The referenced member does not exist or does not resolve to a capability pointer.</exception>
|
||||
public ConsumedCapability Access(MemberAccessPath access)
|
||||
public ConsumedCapability? Access(MemberAccessPath access)
|
||||
{
|
||||
lock (ReentrancyBlocker)
|
||||
{
|
||||
@ -249,7 +247,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -259,11 +257,11 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
static void ReleaseCaps(ConsumedCapability target, SerializerState inParams)
|
||||
static void ReleaseCaps(ConsumedCapability? target, SerializerState? inParams)
|
||||
{
|
||||
if (inParams != null)
|
||||
{
|
||||
foreach (var cap in inParams.Caps)
|
||||
foreach (var cap in inParams.Caps!)
|
||||
{
|
||||
cap?.Release();
|
||||
}
|
||||
@ -277,7 +275,7 @@ namespace Capnp.Rpc
|
||||
|
||||
static void ReleaseOutCaps(DeserializerState outParams)
|
||||
{
|
||||
foreach (var cap in outParams.Caps)
|
||||
foreach (var cap in outParams.Caps!)
|
||||
{
|
||||
cap?.Release();
|
||||
}
|
||||
@ -285,12 +283,13 @@ namespace Capnp.Rpc
|
||||
|
||||
internal void Send()
|
||||
{
|
||||
SerializerState inParams;
|
||||
ConsumedCapability target;
|
||||
SerializerState? inParams;
|
||||
ConsumedCapability? target;
|
||||
|
||||
lock (ReentrancyBlocker)
|
||||
{
|
||||
Debug.Assert(!StateFlags.HasFlag(State.Sent));
|
||||
if (StateFlags.HasFlag(State.Sent))
|
||||
throw new InvalidOperationException("Already sent");
|
||||
|
||||
inParams = _inParams;
|
||||
_inParams = null;
|
||||
@ -299,7 +298,7 @@ namespace Capnp.Rpc
|
||||
StateFlags |= State.Sent;
|
||||
}
|
||||
|
||||
var msg = (Message.WRITER)inParams.MsgBuilder.Root;
|
||||
var msg = (Message.WRITER)inParams!.MsgBuilder!.Root!;
|
||||
Debug.Assert(msg.Call.Target.which != MessageTarget.WHICH.undefined);
|
||||
var call = msg.Call;
|
||||
call.QuestionId = QuestionId;
|
||||
@ -316,15 +315,15 @@ namespace Capnp.Rpc
|
||||
OnException(exception);
|
||||
}
|
||||
|
||||
ReleaseCaps(target, inParams);
|
||||
ReleaseCaps(target!, inParams);
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
SerializerState inParams;
|
||||
ConsumedCapability target;
|
||||
SerializerState? inParams;
|
||||
ConsumedCapability? target;
|
||||
bool justDisposed = false;
|
||||
|
||||
lock (ReentrancyBlocker)
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
@ -19,7 +18,7 @@ namespace Capnp.Rpc
|
||||
|
||||
public override Task<Proxy> WhenResolved => _resolvedCap.Task;
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -31,7 +30,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -148,7 +147,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
protected override Proxy ResolvedCap
|
||||
protected override Proxy? ResolvedCap
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -158,7 +157,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -38,7 +37,7 @@ namespace Capnp.Rpc
|
||||
/// <summary>
|
||||
/// Underlying low-level capability
|
||||
/// </summary>
|
||||
protected internal ConsumedCapability ConsumedCap { get; private set; }
|
||||
protected internal ConsumedCapability? ConsumedCap { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether is this a broken capability.
|
||||
@ -99,12 +98,12 @@ namespace Capnp.Rpc
|
||||
{
|
||||
}
|
||||
|
||||
internal Proxy(ConsumedCapability cap)
|
||||
internal Proxy(ConsumedCapability? cap)
|
||||
{
|
||||
Bind(cap);
|
||||
}
|
||||
|
||||
internal void Bind(ConsumedCapability cap)
|
||||
internal void Bind(ConsumedCapability? cap)
|
||||
{
|
||||
if (ConsumedCap != null)
|
||||
throw new InvalidOperationException("Proxy was already bound");
|
||||
@ -116,7 +115,7 @@ namespace Capnp.Rpc
|
||||
cap.AddRef();
|
||||
}
|
||||
|
||||
internal IProvidedCapability GetProvider()
|
||||
internal IProvidedCapability? GetProvider()
|
||||
{
|
||||
switch (ConsumedCap)
|
||||
{
|
||||
@ -200,7 +199,7 @@ namespace Capnp.Rpc
|
||||
|
||||
using (disposeThis ? this : null)
|
||||
{
|
||||
return CapabilityReflection.CreateProxy<T>(ConsumedCap) as T;
|
||||
return (CapabilityReflection.CreateProxy<T>(ConsumedCap) as T)!;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +214,7 @@ namespace Capnp.Rpc
|
||||
ConsumedCap.Export(endpoint, writer);
|
||||
}
|
||||
|
||||
internal void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
if (_disposedValue)
|
||||
throw new ObjectDisposedException(nameof(Proxy));
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
|
@ -1,6 +1,4 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
@ -18,7 +16,7 @@ namespace Capnp.Rpc
|
||||
|
||||
readonly PendingQuestion _question;
|
||||
readonly MemberAccessPath _access;
|
||||
Proxy _resolvedCap;
|
||||
Proxy? _resolvedCap;
|
||||
|
||||
public RemoteAnswerCapability(PendingQuestion question, MemberAccessPath access): base(question.RpcEndpoint)
|
||||
{
|
||||
@ -59,7 +57,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
protected override Proxy ResolvedCap
|
||||
protected override Proxy? ResolvedCap
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -74,7 +72,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (AggregateException exception)
|
||||
{
|
||||
throw exception.InnerException;
|
||||
throw exception.InnerException!;
|
||||
}
|
||||
|
||||
_resolvedCap = new Proxy(_access.Eval(result));
|
||||
@ -87,7 +85,11 @@ namespace Capnp.Rpc
|
||||
async Task<Proxy> AwaitWhenResolved()
|
||||
{
|
||||
await _question.WhenReturned;
|
||||
return ResolvedCap;
|
||||
|
||||
if (_question.IsTailCall)
|
||||
throw new InvalidOperationException("Question is a tail call, so won't resolve back.");
|
||||
|
||||
return ResolvedCap!;
|
||||
}
|
||||
|
||||
public override Task<Proxy> WhenResolved => AwaitWhenResolved();
|
||||
@ -168,7 +170,7 @@ namespace Capnp.Rpc
|
||||
return call;
|
||||
}
|
||||
|
||||
internal override void Freeze(out IRpcEndpoint boundEndpoint)
|
||||
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
|
||||
{
|
||||
lock (_question.ReentrancyBlocker)
|
||||
{
|
||||
@ -216,7 +218,7 @@ namespace Capnp.Rpc
|
||||
|
||||
if (_question.StateFlags.HasFlag(PendingQuestion.State.Returned))
|
||||
{
|
||||
ResolvedCap.Export(endpoint, writer);
|
||||
ResolvedCap?.Export(endpoint, writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp.Rpc
|
||||
{
|
||||
@ -24,6 +22,9 @@ namespace Capnp.Rpc
|
||||
|
||||
protected virtual Call.WRITER SetupMessage(DynamicSerializerState args, ulong interfaceId, ushort methodId)
|
||||
{
|
||||
if (args.MsgBuilder == null)
|
||||
throw new ArgumentException("Unbound serializer state", nameof(args));
|
||||
|
||||
var callMsg = args.MsgBuilder.BuildRoot<Message.WRITER>();
|
||||
|
||||
callMsg.which = Message.WHICH.Call;
|
||||
|
@ -23,14 +23,17 @@ namespace Capnp.Rpc
|
||||
}
|
||||
|
||||
protected int _pendingCallsOnPromise;
|
||||
Task _disembargo;
|
||||
Task? _disembargo;
|
||||
|
||||
protected abstract Proxy ResolvedCap { get; }
|
||||
protected abstract Proxy? ResolvedCap { get; }
|
||||
|
||||
protected abstract void GetMessageTarget(MessageTarget.WRITER wr);
|
||||
|
||||
protected IPromisedAnswer CallOnResolution(ulong interfaceId, ushort methodId, DynamicSerializerState args)
|
||||
{
|
||||
if (ResolvedCap == null)
|
||||
throw new InvalidOperationException("Capability not yet resolved, calling on resolution not possible");
|
||||
|
||||
try
|
||||
{
|
||||
ResolvedCap.Freeze(out var resolvedCapEndpoint);
|
||||
|
@ -19,7 +19,7 @@
|
||||
{
|
||||
var resolvedCap = await cap.WhenResolved;
|
||||
|
||||
endpoint.Resolve(preliminaryId, vine, () => resolvedCap.ConsumedCap);
|
||||
endpoint.Resolve(preliminaryId, vine, () => resolvedCap.ConsumedCap!);
|
||||
}
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
|
@ -4,9 +4,6 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -65,8 +62,8 @@ namespace Capnp.Rpc
|
||||
|
||||
internal class RpcEndpoint : IEndpoint, IRpcEndpoint
|
||||
{
|
||||
static readonly ThreadLocal<Action> _exportCapTablePostActions = new ThreadLocal<Action>();
|
||||
static readonly ThreadLocal<PendingQuestion> _tailCall = new ThreadLocal<PendingQuestion>();
|
||||
static readonly ThreadLocal<Action?> _exportCapTablePostActions = new ThreadLocal<Action?>();
|
||||
static readonly ThreadLocal<PendingQuestion?> _tailCall = new ThreadLocal<PendingQuestion?>();
|
||||
static readonly ThreadLocal<bool> _canDeferCalls = new ThreadLocal<bool>();
|
||||
|
||||
ILogger Logger { get; } = Logging.CreateLogger<RpcEndpoint>();
|
||||
@ -145,8 +142,7 @@ namespace Capnp.Rpc
|
||||
Tx(mb.Frame);
|
||||
}
|
||||
|
||||
void IRpcEndpoint.Resolve(uint preliminaryId, Skeleton preliminaryCap,
|
||||
Func<ConsumedCapability> resolvedCapGetter)
|
||||
void IRpcEndpoint.Resolve(uint preliminaryId, Skeleton preliminaryCap, Func<ConsumedCapability> resolvedCapGetter)
|
||||
{
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -232,7 +228,7 @@ namespace Capnp.Rpc
|
||||
return AllocateExport(providedCapability, out first);
|
||||
}
|
||||
|
||||
PendingQuestion AllocateQuestion(ConsumedCapability target, SerializerState inParams)
|
||||
PendingQuestion AllocateQuestion(ConsumedCapability? target, SerializerState? inParams)
|
||||
{
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -293,7 +289,7 @@ namespace Capnp.Rpc
|
||||
uint q = req.QuestionId;
|
||||
|
||||
var bootstrap = DynamicSerializerState.CreateForRpc();
|
||||
var ans = bootstrap.MsgBuilder.BuildRoot<Message.WRITER>();
|
||||
var ans = bootstrap.MsgBuilder!.BuildRoot<Message.WRITER>();
|
||||
|
||||
ans.which = Message.WHICH.Return;
|
||||
var ret = ans.Return;
|
||||
@ -305,7 +301,7 @@ namespace Capnp.Rpc
|
||||
if (bootstrapCap != null)
|
||||
{
|
||||
ret.which = Return.WHICH.Results;
|
||||
bootstrap.SetCapability(bootstrap.ProvideCapability(LocalCapability.Create(_host.BootstrapCap)));
|
||||
bootstrap.SetCapability(bootstrap.ProvideCapability(LocalCapability.Create(bootstrapCap)));
|
||||
ret.Results.Content = bootstrap;
|
||||
|
||||
bootstrapTask = Task.FromResult<AnswerOrCounterquestion>(bootstrap);
|
||||
@ -371,12 +367,12 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (RpcException exception)
|
||||
{
|
||||
Logger.LogWarning($"Unable to return call: {exception.InnerException.Message}");
|
||||
Logger.LogWarning($"Unable to return call: {exception.InnerException?.Message ?? exception.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
IProvidedCapability cap;
|
||||
PendingAnswer pendingAnswer = null;
|
||||
IProvidedCapability? cap;
|
||||
PendingAnswer pendingAnswer;
|
||||
bool releaseParamCaps = false;
|
||||
|
||||
void AwaitAnswerAndReply()
|
||||
@ -414,8 +410,8 @@ namespace Capnp.Rpc
|
||||
}
|
||||
else if (aorcq.Answer != null || aorcq.Counterquestion != _tailCall.Value)
|
||||
{
|
||||
var results = aorcq.Answer ?? (DynamicSerializerState)(await aorcq.Counterquestion.WhenReturned);
|
||||
var ret = SetupReturn(results.MsgBuilder);
|
||||
var results = aorcq.Answer ?? (DynamicSerializerState)(await aorcq.Counterquestion!.WhenReturned);
|
||||
var ret = SetupReturn(results.MsgBuilder!);
|
||||
|
||||
switch (req.SendResultsTo.which)
|
||||
{
|
||||
@ -569,7 +565,7 @@ namespace Capnp.Rpc
|
||||
case MessageTarget.WHICH.PromisedAnswer:
|
||||
{
|
||||
bool exists;
|
||||
PendingAnswer previousAnswer;
|
||||
PendingAnswer? previousAnswer;
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -578,7 +574,7 @@ namespace Capnp.Rpc
|
||||
|
||||
if (exists)
|
||||
{
|
||||
previousAnswer.Chain(
|
||||
previousAnswer!.Chain(
|
||||
false,
|
||||
req.Target.PromisedAnswer,
|
||||
async t =>
|
||||
@ -633,7 +629,7 @@ namespace Capnp.Rpc
|
||||
|
||||
void ProcessReturn(Return.READER req)
|
||||
{
|
||||
PendingQuestion question;
|
||||
PendingQuestion? question;
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -674,7 +670,7 @@ namespace Capnp.Rpc
|
||||
case Return.WHICH.TakeFromOtherQuestion:
|
||||
{
|
||||
bool exists;
|
||||
PendingAnswer pendingAnswer;
|
||||
PendingAnswer? pendingAnswer;
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -683,7 +679,7 @@ namespace Capnp.Rpc
|
||||
|
||||
if (exists)
|
||||
{
|
||||
pendingAnswer.Chain(false, async t =>
|
||||
pendingAnswer!.Chain(false, async t =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -747,6 +743,8 @@ namespace Capnp.Rpc
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
var resolvedCap = ImportCap(resolve.Cap);
|
||||
if (resolvedCap == null)
|
||||
resolvedCap = LazyCapability.CreateBrokenCap("Failed to resolve this capability");
|
||||
resolvableCap.ResolveTo(resolvedCap);
|
||||
}
|
||||
break;
|
||||
@ -935,7 +933,7 @@ namespace Capnp.Rpc
|
||||
{
|
||||
foreach (var cap in results.Caps)
|
||||
{
|
||||
cap.Release();
|
||||
cap?.Release();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -984,8 +982,8 @@ namespace Capnp.Rpc
|
||||
try
|
||||
{
|
||||
int icount = checked((int)count);
|
||||
rc.Release(icount);
|
||||
rc.Cap.Relinquish(icount);
|
||||
rc!.Release(icount);
|
||||
rc!.Cap.Relinquish(icount);
|
||||
|
||||
if (rc.RefCount == 0)
|
||||
{
|
||||
@ -1171,7 +1169,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
ConsumedCapability ImportCap(CapDescriptor.READER capDesc)
|
||||
ConsumedCapability? ImportCap(CapDescriptor.READER capDesc)
|
||||
{
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
@ -1192,8 +1190,7 @@ namespace Capnp.Rpc
|
||||
rcw.Cap.SetTarget(impCap);
|
||||
}
|
||||
|
||||
Debug.Assert(impCap != null);
|
||||
return impCap;
|
||||
return impCap!;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1236,7 +1233,6 @@ namespace Capnp.Rpc
|
||||
case CapDescriptor.WHICH.ReceiverHosted:
|
||||
if (_exportTable.TryGetValue(capDesc.ReceiverHosted, out var rc))
|
||||
{
|
||||
Debug.Assert(rc.Cap != null);
|
||||
return LocalCapability.Create(rc.Cap);
|
||||
}
|
||||
else
|
||||
@ -1311,9 +1307,9 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ConsumedCapability> ImportCapTable(Payload.READER payload)
|
||||
public IList<ConsumedCapability?> ImportCapTable(Payload.READER payload)
|
||||
{
|
||||
var list = new List<ConsumedCapability>();
|
||||
var list = new List<ConsumedCapability?>();
|
||||
|
||||
if (payload.CapTable != null)
|
||||
{
|
||||
@ -1341,7 +1337,7 @@ namespace Capnp.Rpc
|
||||
Debug.Assert(_exportCapTablePostActions.Value == null);
|
||||
_exportCapTablePostActions.Value = null;
|
||||
|
||||
payload.CapTable.Init(state.MsgBuilder.Caps.Count);
|
||||
payload.CapTable.Init(state.MsgBuilder!.Caps!.Count);
|
||||
|
||||
int i = 0;
|
||||
foreach (var cap in state.MsgBuilder.Caps)
|
||||
@ -1454,7 +1450,7 @@ namespace Capnp.Rpc
|
||||
}
|
||||
catch (RpcException exception)
|
||||
{
|
||||
Logger.LogWarning($"Unable to release import: {exception.InnerException.Message}");
|
||||
Logger.LogWarning($"Unable to release import: {exception.InnerException?.Message ?? exception.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1492,12 +1488,12 @@ namespace Capnp.Rpc
|
||||
return inboundEndpoint;
|
||||
}
|
||||
|
||||
Skeleton _bootstrapCap;
|
||||
Skeleton? _bootstrapCap;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bootstrap capability.
|
||||
/// </summary>
|
||||
public Skeleton BootstrapCap
|
||||
public Skeleton? BootstrapCap
|
||||
{
|
||||
get => _bootstrapCap;
|
||||
set
|
||||
|
@ -1,8 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -179,8 +176,8 @@ namespace Capnp.Rpc
|
||||
ILogger Logger { get; } = Logging.CreateLogger<Skeleton<T>>();
|
||||
#endif
|
||||
|
||||
Func<DeserializerState, CancellationToken, Task<AnswerOrCounterquestion>>[] _methods;
|
||||
CancellationTokenSource _disposed = new CancellationTokenSource();
|
||||
Func<DeserializerState, CancellationToken, Task<AnswerOrCounterquestion>>[] _methods = null!;
|
||||
CancellationTokenSource? _disposed = new CancellationTokenSource();
|
||||
readonly object _reentrancyBlocker = new object();
|
||||
int _pendingCalls;
|
||||
|
||||
@ -204,7 +201,7 @@ namespace Capnp.Rpc
|
||||
/// <summary>
|
||||
/// Gets the underlying capability implementation.
|
||||
/// </summary>
|
||||
protected T Impl { get; private set; }
|
||||
protected T Impl { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the implemented interface.
|
||||
|
@ -1,13 +1,9 @@
|
||||
using Capnp.FrameTracing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -46,17 +42,17 @@ namespace Capnp.Rpc
|
||||
readonly RpcEngine _rpcEngine;
|
||||
readonly TcpClient _client;
|
||||
Func<Stream, Stream> _createLayers = _ => _;
|
||||
RpcEngine.RpcEndpoint _inboundEndpoint;
|
||||
OutboundTcpEndpoint _outboundEndpoint;
|
||||
FramePump _pump;
|
||||
Thread _pumpThread;
|
||||
Action _attachTracerAction;
|
||||
RpcEngine.RpcEndpoint? _inboundEndpoint;
|
||||
OutboundTcpEndpoint? _outboundEndpoint;
|
||||
FramePump? _pump;
|
||||
Thread? _pumpThread;
|
||||
Action? _attachTracerAction;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Task which completes when TCP is connected. Will be
|
||||
/// null until connection is actually requested (either by calling Connect or using appropriate constructor).
|
||||
/// </summary>
|
||||
public Task WhenConnected { get; private set; }
|
||||
public Task? WhenConnected { get; private set; }
|
||||
|
||||
async Task ConnectAsync(string host, int port)
|
||||
{
|
||||
@ -156,8 +152,14 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
/// <typeparam name="TProxy">Bootstrap capability interface</typeparam>
|
||||
/// <returns>A proxy for the bootstrap capability</returns>
|
||||
/// <exception cref="InvalidOperationException">Not connected</exception>
|
||||
public TProxy GetMain<TProxy>() where TProxy: class
|
||||
{
|
||||
if (WhenConnected == null)
|
||||
{
|
||||
throw new InvalidOperationException("Not connecting");
|
||||
}
|
||||
|
||||
if (!WhenConnected.IsCompleted)
|
||||
{
|
||||
throw new InvalidOperationException("Connection not yet established");
|
||||
@ -168,9 +170,7 @@ namespace Capnp.Rpc
|
||||
throw new InvalidOperationException("Connection not successfully established");
|
||||
}
|
||||
|
||||
Debug.Assert(_inboundEndpoint != null);
|
||||
|
||||
return CapabilityReflection.CreateProxy<TProxy>(_inboundEndpoint.QueryMain()) as TProxy;
|
||||
return (CapabilityReflection.CreateProxy<TProxy>(_inboundEndpoint!.QueryMain()) as TProxy)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -182,7 +182,7 @@ namespace Capnp.Rpc
|
||||
|
||||
try
|
||||
{
|
||||
if (!WhenConnected.Wait(500))
|
||||
if (WhenConnected != null && !WhenConnected.Wait(500))
|
||||
{
|
||||
Logger.LogError("Unable to join connection task within timeout");
|
||||
}
|
||||
@ -218,7 +218,7 @@ namespace Capnp.Rpc
|
||||
|
||||
_attachTracerAction += () =>
|
||||
{
|
||||
_pump.AttachTracer(tracer);
|
||||
_pump?.AttachTracer(tracer);
|
||||
};
|
||||
}
|
||||
|
||||
@ -257,33 +257,33 @@ namespace Capnp.Rpc
|
||||
/// <summary>
|
||||
/// Gets the number of RPC protocol messages sent by this client so far.
|
||||
/// </summary>
|
||||
public long SendCount => _inboundEndpoint.SendCount;
|
||||
public long SendCount => _inboundEndpoint?.SendCount ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of RPC protocol messages received by this client so far.
|
||||
/// </summary>
|
||||
public long RecvCount => _inboundEndpoint.RecvCount;
|
||||
public long RecvCount => _inboundEndpoint?.RecvCount ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the remote port number which this client is connected to,
|
||||
/// or null if the connection is not yet established.
|
||||
/// </summary>
|
||||
public int? RemotePort => ((IPEndPoint)_client.Client?.RemoteEndPoint)?.Port;
|
||||
public int? RemotePort => ((IPEndPoint)_client.Client.RemoteEndPoint)?.Port;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local port number which this client using,
|
||||
/// or null if the connection is not yet established.
|
||||
/// </summary>
|
||||
public int? LocalPort => ((IPEndPoint)_client.Client?.LocalEndPoint)?.Port;
|
||||
public int? LocalPort => ((IPEndPoint)_client.Client.LocalEndPoint)?.Port;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the I/O thread is currently running
|
||||
/// </summary>
|
||||
public bool IsComputing => _pumpThread.ThreadState == System.Threading.ThreadState.Running;
|
||||
public bool IsComputing => _pumpThread?.ThreadState == System.Threading.ThreadState.Running;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the I/O thread is waiting for data to receive
|
||||
/// </summary>
|
||||
public bool IsWaitingForData => _pump.IsWaitingForData;
|
||||
public bool IsWaitingForData => _pump?.IsWaitingForData ?? false;
|
||||
}
|
||||
}
|
@ -109,12 +109,12 @@ namespace Capnp.Rpc
|
||||
public FramePump Pump { get; private set; }
|
||||
public OutboundTcpEndpoint OutboundEp { get; private set; }
|
||||
public RpcEngine.RpcEndpoint InboundEp { get; private set; }
|
||||
public Thread PumpRunner { get; private set; }
|
||||
public Thread? PumpRunner { get; private set; }
|
||||
public int? LocalPort => ((IPEndPoint)Client.Client.LocalEndPoint)?.Port;
|
||||
public int? RemotePort => ((IPEndPoint)Client.Client.RemoteEndPoint)?.Port;
|
||||
public long RecvCount => InboundEp.RecvCount;
|
||||
public long SendCount => InboundEp.SendCount;
|
||||
public bool IsComputing => PumpRunner.ThreadState == ThreadState.Running;
|
||||
public bool IsComputing => PumpRunner?.ThreadState == ThreadState.Running;
|
||||
public bool IsWaitingForData => Pump.IsWaitingForData;
|
||||
|
||||
public void AttachTracer(IFrameTracer tracer)
|
||||
@ -184,7 +184,7 @@ namespace Capnp.Rpc
|
||||
connection.Start();
|
||||
}
|
||||
|
||||
connection.PumpRunner.Start();
|
||||
connection.PumpRunner!.Start();
|
||||
}
|
||||
}
|
||||
catch (SocketException)
|
||||
@ -199,8 +199,13 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
void SafeJoin(Thread thread)
|
||||
void SafeJoin(Thread? thread)
|
||||
{
|
||||
if (thread == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int retry = 0; retry < 5; ++retry)
|
||||
{
|
||||
try
|
||||
@ -332,6 +337,6 @@ namespace Capnp.Rpc
|
||||
/// <summary>
|
||||
/// Fires when a new incoming connection was accepted, or when an active connection is closed.
|
||||
/// </summary>
|
||||
public event Action<object, ConnectionEventArgs> OnConnectionChanged;
|
||||
public event Action<object, ConnectionEventArgs>? OnConnectionChanged;
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
#nullable disable
|
||||
|
||||
using Capnp;
|
||||
using Capnp.Rpc;
|
||||
@ -2641,3 +2642,5 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#nullable restore
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace Capnp
|
||||
namespace Capnp
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper struct to represent the tuple (segment index, offset)
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
@ -29,10 +28,10 @@ namespace Capnp
|
||||
return s;
|
||||
}
|
||||
|
||||
internal MessageBuilder MsgBuilder { get; set; }
|
||||
internal ISegmentAllocator Allocator => MsgBuilder?.Allocator;
|
||||
internal List<Rpc.ConsumedCapability> Caps => MsgBuilder?.Caps;
|
||||
internal SerializerState Owner { get; set; }
|
||||
internal MessageBuilder? MsgBuilder { get; set; }
|
||||
internal ISegmentAllocator? Allocator => MsgBuilder?.Allocator;
|
||||
internal List<Rpc.ConsumedCapability?>? Caps => MsgBuilder?.Caps;
|
||||
internal SerializerState? Owner { get; set; }
|
||||
internal int OwnerSlot { get; set; }
|
||||
internal uint SegmentIndex { get; set; }
|
||||
internal int Offset { get; set; }
|
||||
@ -43,7 +42,7 @@ namespace Capnp
|
||||
internal ObjectKind Kind { get; set; }
|
||||
internal uint CapabilityIndex { get; set; }
|
||||
|
||||
SerializerState[] _linkedStates;
|
||||
SerializerState[]? _linkedStates;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an unbound serializer state.
|
||||
@ -129,7 +128,7 @@ namespace Capnp
|
||||
if (Owner != null)
|
||||
ts.Bind(Owner, OwnerSlot);
|
||||
else
|
||||
ts.Bind(MsgBuilder);
|
||||
ts.Bind(MsgBuilder ?? throw Unbound());
|
||||
|
||||
return ts;
|
||||
}
|
||||
@ -152,8 +151,8 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public bool IsAllocated => Offset >= 0;
|
||||
|
||||
Span<ulong> SegmentSpan => IsAllocated ? Allocator.Segments[(int)SegmentIndex].Span : Span<ulong>.Empty;
|
||||
Span<ulong> FarSpan(uint index) => Allocator.Segments[(int)index].Span;
|
||||
Span<ulong> SegmentSpan => IsAllocated && Allocator != null ? Allocator.Segments[(int)SegmentIndex].Span : Span<ulong>.Empty;
|
||||
Span<ulong> FarSpan(uint index) => Allocator!.Segments[(int)index].Span;
|
||||
|
||||
/// <summary>
|
||||
/// Given this state describes a struct and is allocated, returns the struct's data section.
|
||||
@ -181,6 +180,9 @@ namespace Capnp
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Allocator == null)
|
||||
throw Unbound();
|
||||
|
||||
SegmentIndex = Owner?.SegmentIndex ?? SegmentIndex;
|
||||
Allocator.Allocate(count, SegmentIndex, out var slice, false);
|
||||
SegmentIndex = slice.SegmentIndex;
|
||||
@ -191,7 +193,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates storage for the underlying object. Does nothing if it is already allocated. From the point the object is allocated, its type cannot by changed
|
||||
/// Allocates storage for the underlying object. Does nothing if it is already allocated. From the point the object is allocated, its type cannot be changed
|
||||
/// anymore (e.g. changing from struct to list, or modifying the struct's section sizes).
|
||||
/// </summary>
|
||||
public void Allocate()
|
||||
@ -250,6 +252,9 @@ namespace Capnp
|
||||
if (!target.IsAllocated)
|
||||
throw new InvalidOperationException("Target must be allocated before a pointer can be built");
|
||||
|
||||
if (MsgBuilder == null)
|
||||
throw Unbound();
|
||||
|
||||
try
|
||||
{
|
||||
if (SegmentSpan[offset] != 0)
|
||||
@ -345,7 +350,7 @@ namespace Capnp
|
||||
{
|
||||
WirePointer farPtr = default;
|
||||
|
||||
if (Allocator.Allocate(1, target.SegmentIndex, out var landingPadSlice, true))
|
||||
if (Allocator!.Allocate(1, target.SegmentIndex, out var landingPadSlice, true))
|
||||
{
|
||||
farPtr.SetFarPointer(target.SegmentIndex, landingPadSlice.Offset, false);
|
||||
SegmentSpan[offset] = farPtr;
|
||||
@ -372,7 +377,7 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
|
||||
internal Rpc.ConsumedCapability DecodeCapPointer(int offset)
|
||||
internal Rpc.ConsumedCapability? DecodeCapPointer(int offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
throw new IndexOutOfRangeException(nameof(offset));
|
||||
@ -455,7 +460,7 @@ namespace Capnp
|
||||
throw new InvalidOperationException("This object cannot own pointers to sub-objects");
|
||||
}
|
||||
|
||||
_linkedStates[slot] = target;
|
||||
_linkedStates![slot] = target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -476,6 +481,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
static InvalidOperationException AlreadySet() => new InvalidOperationException("The object type was already set");
|
||||
static InvalidOperationException Unbound() => new InvalidOperationException("This state is not bound to a MessageBuilder");
|
||||
|
||||
void VerifyNotYetAllocated()
|
||||
{
|
||||
@ -654,7 +660,13 @@ namespace Capnp
|
||||
/// <exception cref="EncoderFallbackException">Trying to obtain the UTF-8 encoding might throw this exception.</exception>
|
||||
/// <exception cref="InvalidOperationException">The object type was already set to something different</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">UTF-8 encoding exceeds 2^29-2 bytes</exception>
|
||||
protected void WriteText(string text)
|
||||
protected void WriteText(string? text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
VerifyNotYetAllocated();
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] srcBytes = Encoding.UTF8.GetBytes(text);
|
||||
SetListOfValues(8, srcBytes.Length + 1);
|
||||
@ -663,6 +675,7 @@ namespace Capnp
|
||||
dstSpan = dstSpan.Slice(0, dstSpan.Length - 1);
|
||||
srcSpan.CopyTo(dstSpan);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data (up to 64 bits) into the underlying struct's data section.
|
||||
@ -761,7 +774,7 @@ namespace Capnp
|
||||
if (Kind != ObjectKind.Struct && Kind != ObjectKind.ListOfPointers)
|
||||
throw new InvalidOperationException("This is not a struct or list of pointers");
|
||||
|
||||
ref var state = ref _linkedStates[index];
|
||||
ref var state = ref _linkedStates![index];
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
@ -784,12 +797,12 @@ namespace Capnp
|
||||
/// <item><description>Object at given position is not compatible with the desired target serializer type.</description></item>
|
||||
/// </list></exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public TS TryGetPointer<TS>(int index) where TS : SerializerState, new()
|
||||
public TS? TryGetPointer<TS>(int index) where TS : SerializerState, new()
|
||||
{
|
||||
if (Kind != ObjectKind.Struct && Kind != ObjectKind.ListOfPointers)
|
||||
throw new InvalidOperationException("This is not a struct or list of pointers");
|
||||
|
||||
var state = _linkedStates[index];
|
||||
var state = _linkedStates![index];
|
||||
|
||||
if (state == null) return null;
|
||||
|
||||
@ -820,7 +833,7 @@ namespace Capnp
|
||||
/// <item><description>Object at given position is not compatible with the desired target serializer type.</description></item>
|
||||
/// </list></exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public SerializerState TryGetPointer(int index) => TryGetPointer<SerializerState>(index);
|
||||
public SerializerState? TryGetPointer(int index) => TryGetPointer<SerializerState>(index);
|
||||
|
||||
/// <summary>
|
||||
/// Reads text from a struct field or list element.
|
||||
@ -829,7 +842,7 @@ namespace Capnp
|
||||
/// If the underlying object is a list of pointers: Element index</param>
|
||||
/// <param name="defaultText">String to return in case of null</param>
|
||||
/// <returns>The decoded text</returns>
|
||||
public string ReadText(int index, string defaultText = null)
|
||||
public string? ReadText(int index, string? defaultText = null)
|
||||
{
|
||||
var b = BuildPointer(index);
|
||||
|
||||
@ -851,7 +864,7 @@ namespace Capnp
|
||||
/// <item><description>Object at given position was already set.</description></item>
|
||||
/// </list></exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public void WriteText(int index, string text)
|
||||
public void WriteText(int index, string? text)
|
||||
{
|
||||
BuildPointer(index).WriteText(text);
|
||||
}
|
||||
@ -869,7 +882,7 @@ namespace Capnp
|
||||
/// <item><description>Object at given position was already set.</description></item>
|
||||
/// </list></exception>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public void WriteText(int index, string text, string defaultText)
|
||||
public void WriteText(int index, string? text, string defaultText)
|
||||
{
|
||||
BuildPointer(index).WriteText(text ?? defaultText);
|
||||
}
|
||||
@ -886,11 +899,11 @@ namespace Capnp
|
||||
if (Kind != ObjectKind.ListOfStructs)
|
||||
throw new InvalidOperationException("This is not a list of structs");
|
||||
|
||||
ref var state = ref _linkedStates[index];
|
||||
ref var state = ref _linkedStates![index];
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
state = new SerializerState(MsgBuilder);
|
||||
state = new SerializerState(MsgBuilder!);
|
||||
state.SetStruct(StructDataCount, StructPtrCount);
|
||||
state.SegmentIndex = SegmentIndex;
|
||||
state.Offset = Offset + 1 + index * (StructDataCount + StructPtrCount);
|
||||
@ -913,12 +926,12 @@ namespace Capnp
|
||||
if (Kind != ObjectKind.ListOfStructs)
|
||||
throw new InvalidOperationException("This is not a list of structs");
|
||||
|
||||
ref var state = ref _linkedStates[index];
|
||||
ref var state = ref _linkedStates![index];
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
state = new TS();
|
||||
state.Bind(MsgBuilder);
|
||||
state.Bind(MsgBuilder!);
|
||||
state.SetStruct(StructDataCount, StructPtrCount);
|
||||
state.SegmentIndex = SegmentIndex;
|
||||
int stride = StructDataCount + StructPtrCount;
|
||||
@ -942,19 +955,19 @@ namespace Capnp
|
||||
|
||||
for (int offset = minOffset; offset < maxOffset; offset++)
|
||||
{
|
||||
ref var state = ref _linkedStates[offset - minOffset];
|
||||
ref var state = ref _linkedStates![offset - minOffset];
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
state = new TS();
|
||||
state.Bind(MsgBuilder);
|
||||
state.Bind(MsgBuilder!);
|
||||
state.SetStruct(StructDataCount, StructPtrCount);
|
||||
state.SegmentIndex = SegmentIndex;
|
||||
state.Offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return _linkedStates.LazyListSelect(ts => (TS)ts);
|
||||
return _linkedStates!.LazyListSelect(ts => (TS)ts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1240,7 +1253,7 @@ namespace Capnp
|
||||
/// <param name="capability">The low-level capability object to provide.</param>
|
||||
/// <returns>Index of the given capability in the capability table</returns>
|
||||
/// <exception cref="InvalidOperationException">The underlying message builder was not configured for capability table support.</exception>
|
||||
public uint ProvideCapability(Rpc.ConsumedCapability capability)
|
||||
public uint ProvideCapability(Rpc.ConsumedCapability? capability)
|
||||
{
|
||||
if (Caps == null)
|
||||
throw new InvalidOperationException("Underlying MessageBuilder was not enabled to support capabilities");
|
||||
@ -1279,7 +1292,7 @@ namespace Capnp
|
||||
/// </list></param>
|
||||
/// <returns>Index of the given capability in the capability table</returns>
|
||||
/// <exception cref="InvalidOperationException">The underlying message builder was not configured for capability table support.</exception>
|
||||
public uint ProvideCapability(object obj)
|
||||
public uint ProvideCapability(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return ProvideCapability(default(Rpc.ConsumedCapability));
|
||||
@ -1352,7 +1365,7 @@ namespace Capnp
|
||||
}
|
||||
}
|
||||
|
||||
internal Rpc.ConsumedCapability StructReadRawCap(int index)
|
||||
internal Rpc.ConsumedCapability? StructReadRawCap(int index)
|
||||
{
|
||||
if (Kind != ObjectKind.Struct && Kind != ObjectKind.Nil)
|
||||
throw new InvalidOperationException("Allowed on structs only");
|
||||
@ -1372,7 +1385,7 @@ namespace Capnp
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="slot"/> is out of range.</exception>
|
||||
/// <exception cref="ArgumentException">The desired interface does not qualify as capability interface (<see cref="Rpc.ProxyAttribute"/>)</exception>
|
||||
/// <exception cref="InvalidOperationException">This state does not represent a struct.</exception>
|
||||
public T ReadCap<T>(int slot) where T : class
|
||||
public T? ReadCap<T>(int slot) where T : class
|
||||
{
|
||||
var cap = StructReadRawCap(slot);
|
||||
return Rpc.CapabilityReflection.CreateProxy<T>(cap) as T;
|
||||
|
@ -23,7 +23,7 @@ namespace Capnp
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
public static bool ReplacementTryAdd<K, V>(this Dictionary<K, V> thisDict, K key, V value) => thisDict.TryAdd(key, value);
|
||||
public static bool ReplacementTryAdd<K, V>(this Dictionary<K, V> thisDict, K key, V value) where K: struct => thisDict.TryAdd(key, value);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@ -40,14 +40,16 @@ namespace Capnp
|
||||
{
|
||||
if (!thisDict.ContainsKey(key))
|
||||
{
|
||||
value = default;
|
||||
value = default!; // OK here since .NET Standard 2.0 does not support (non-)nullability anyway.
|
||||
return false;
|
||||
}
|
||||
value = thisDict[key];
|
||||
return thisDict.Remove(key);
|
||||
}
|
||||
#else
|
||||
#pragma warning disable CS8714
|
||||
public static bool ReplacementTryRemove<K, V>(this Dictionary<K, V> thisDict, K key, out V value) => thisDict.Remove(key, out value);
|
||||
#pragma warning restore CS8714
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<RootNamespace>CapnpC.CSharp.Generator.Tests</RootNamespace>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
@ -10,15 +10,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
|
||||
<PackageReference Include="SpecFlow" Version="3.0.225" />
|
||||
<PackageReference Include="SpecFlow.MsTest" Version="3.0.225" />
|
||||
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.0.225" />
|
||||
<PackageReference Include="SpecFlow" Version="3.1.78" />
|
||||
<PackageReference Include="SpecFlow.MsTest" Version="3.1.78" />
|
||||
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.1.78" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -49,11 +49,25 @@ Scenario: Multiple errors
|
||||
|
||||
Scenario Outline: Valid generator output
|
||||
Given I have a binary code generator request <bin>
|
||||
And I enable generation of nullable reference types according to <nullablegen>
|
||||
And I enable the compiler support of nullable reference types according to <nullablesupp>
|
||||
When I invoke capnpc-csharp
|
||||
Then the invocation must succeed and the generated code must compile
|
||||
Then the invocation must succeed and attempting to compile the generated code gives <outcome>
|
||||
|
||||
Examples:
|
||||
| bin |
|
||||
| Issue19.capnp.bin |
|
||||
| Issue21.capnp.bin |
|
||||
| Issue22.capnp.bin |
|
||||
| bin | nullablegen | nullablesupp | outcome |
|
||||
| test.capnp.bin | false | false | success |
|
||||
| test.capnp.bin | true | false | errors |
|
||||
| test.capnp.bin | false | true | warnings |
|
||||
| test.capnp.bin | true | true | success |
|
||||
| Issue19.capnp.bin | false | false | success |
|
||||
| Issue21.capnp.bin | false | false | success |
|
||||
| Issue22.capnp.bin | false | false | success |
|
||||
| NullableDisable.capnp.bin | true | false | success |
|
||||
| NullableDisable.capnp.bin | true | true | warnings |
|
||||
| NullableEnable.capnp.bin | false | true | success |
|
||||
| NullableEnable.capnp.bin | false | false | errors |
|
||||
| NullableDisable2.capnp.bin | false | false | errors |
|
||||
| NullableDisable2.capnp.bin | false | true | success |
|
||||
| NullableEnable2.capnp.bin | false | false | errors |
|
||||
| NullableEnable2.capnp.bin | false | true | success |
|
398
CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
generated
398
CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
generated
@ -1,8 +1,8 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by SpecFlow (http://www.specflow.org/).
|
||||
// SpecFlow Version:3.0.0.0
|
||||
// SpecFlow Generator Version:3.0.0.0
|
||||
// SpecFlow Version:3.1.0.0
|
||||
// SpecFlow Generator Version:3.1.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@ -13,9 +13,11 @@
|
||||
namespace CapnpC.CSharp.Generator.Tests
|
||||
{
|
||||
using TechTalk.SpecFlow;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.0.0.0")]
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.1.0.0")]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute()]
|
||||
public partial class CodeGeneratorFeature
|
||||
@ -25,6 +27,8 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
|
||||
private Microsoft.VisualStudio.TestTools.UnitTesting.TestContext _testContext;
|
||||
|
||||
private string[] _featureTags = ((string[])(null));
|
||||
|
||||
#line 1 "CodeGenerator.feature"
|
||||
#line hidden
|
||||
|
||||
@ -68,7 +72,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute()]
|
||||
public virtual void ScenarioTearDown()
|
||||
public virtual void TestTearDown()
|
||||
{
|
||||
testRunner.OnScenarioEnd();
|
||||
}
|
||||
@ -94,35 +98,78 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
public virtual void ComparingBackendOutputWithReference()
|
||||
{
|
||||
string[] tagsOfScenario = ((string[])(null));
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Comparing backend output with reference", null, ((string[])(null)));
|
||||
#line 6
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 7
|
||||
testRunner.Given("I have a binary code generator request \"test.capnp.bin\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 8
|
||||
testRunner.And("my reference output is \"test.cs\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 9
|
||||
testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 10
|
||||
testRunner.Then("the generated output must match the reference", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
public virtual void InvalidBinaryCodeGeneratorRequests(string bin, string[] exampleTags)
|
||||
{
|
||||
string[] tagsOfScenario = exampleTags;
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Invalid binary code generator requests", null, exampleTags);
|
||||
#line 12
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 13
|
||||
testRunner.Given(string.Format("I have a binary code generator request {0}", bin), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 14
|
||||
testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 15
|
||||
testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
@ -155,19 +202,41 @@ this.InvalidBinaryCodeGeneratorRequests("test.cs", ((string[])(null)));
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
public virtual void CombiningFrontendAndBackend()
|
||||
{
|
||||
string[] tagsOfScenario = ((string[])(null));
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Combining frontend and backend", null, ((string[])(null)));
|
||||
#line 22
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 23
|
||||
testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 24
|
||||
testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 25
|
||||
testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 26
|
||||
testRunner.Then("code generation must succeed", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
@ -176,19 +245,41 @@ this.ScenarioInitialize(scenarioInfo);
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
public virtual void MissingFrontend()
|
||||
{
|
||||
string[] tagsOfScenario = ((string[])(null));
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Missing frontend", null, ((string[])(null)));
|
||||
#line 28
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 29
|
||||
testRunner.Given("capnp.exe is not installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 30
|
||||
testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 31
|
||||
testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 32
|
||||
testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
@ -197,23 +288,47 @@ this.ScenarioInitialize(scenarioInfo);
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
public virtual void SchemaWithoutID()
|
||||
{
|
||||
string[] tagsOfScenario = ((string[])(null));
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Schema without ID", null, ((string[])(null)));
|
||||
#line 34
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 35
|
||||
testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 36
|
||||
testRunner.And("I have a schema \"Empty1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 37
|
||||
testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 38
|
||||
testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
#line 39
|
||||
testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 40
|
||||
testRunner.And("the error output must contain \"File does not declare an ID\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
@ -222,75 +337,316 @@ this.ScenarioInitialize(scenarioInfo);
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
public virtual void MultipleErrors()
|
||||
{
|
||||
string[] tagsOfScenario = ((string[])(null));
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Multiple errors", null, ((string[])(null)));
|
||||
#line 42
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 43
|
||||
testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line hidden
|
||||
#line 44
|
||||
testRunner.And("I have a schema \"invalid.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 45
|
||||
testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 46
|
||||
testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
#line 47
|
||||
testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 48
|
||||
testRunner.And("the error output must contain multiple messages", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
public virtual void ValidGeneratorOutput(string bin, string[] exampleTags)
|
||||
public virtual void ValidGeneratorOutput(string bin, string nullablegen, string nullablesupp, string outcome, string[] exampleTags)
|
||||
{
|
||||
string[] tagsOfScenario = exampleTags;
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Valid generator output", null, exampleTags);
|
||||
#line 50
|
||||
this.ScenarioInitialize(scenarioInfo);
|
||||
#line hidden
|
||||
bool isScenarioIgnored = default(bool);
|
||||
bool isFeatureIgnored = default(bool);
|
||||
if ((tagsOfScenario != null))
|
||||
{
|
||||
isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((this._featureTags != null))
|
||||
{
|
||||
isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any();
|
||||
}
|
||||
if ((isScenarioIgnored || isFeatureIgnored))
|
||||
{
|
||||
testRunner.SkipScenario();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScenarioStart();
|
||||
#line 51
|
||||
testRunner.Given(string.Format("I have a binary code generator request {0}", bin), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
|
||||
#line 52
|
||||
testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line 53
|
||||
testRunner.Then("the invocation must succeed and the generated code must compile", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
#line 52
|
||||
testRunner.And(string.Format("I enable generation of nullable reference types according to {0}", nullablegen), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 53
|
||||
testRunner.And(string.Format("I enable the compiler support of nullable reference types according to {0}", nullablesupp), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
|
||||
#line hidden
|
||||
#line 54
|
||||
testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
|
||||
#line hidden
|
||||
#line 55
|
||||
testRunner.Then(string.Format("the invocation must succeed and attempting to compile the generated code gives {0" +
|
||||
"}", outcome), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
|
||||
#line hidden
|
||||
}
|
||||
this.ScenarioCleanup();
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue19.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 0")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue19.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 0")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant0()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("test.capnp.bin", "false", "false", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 1")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 1")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")]
|
||||
public virtual void ValidGeneratorOutput_Variant1()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("test.capnp.bin", "true", "false", "errors", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 2")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 2")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "warnings")]
|
||||
public virtual void ValidGeneratorOutput_Variant2()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("test.capnp.bin", "false", "true", "warnings", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 3")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 3")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant3()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("test.capnp.bin", "true", "true", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 4")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 4")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue19.capnp.bin")]
|
||||
public virtual void ValidGeneratorOutput_Issue19_Capnp_Bin()
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant4()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("Issue19.capnp.bin", ((string[])(null)));
|
||||
this.ValidGeneratorOutput("Issue19.capnp.bin", "false", "false", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue21.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 5")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue21.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 5")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue21.capnp.bin")]
|
||||
public virtual void ValidGeneratorOutput_Issue21_Capnp_Bin()
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant5()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("Issue21.capnp.bin", ((string[])(null)));
|
||||
this.ValidGeneratorOutput("Issue21.capnp.bin", "false", "false", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue22.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 6")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue22.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 6")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue22.capnp.bin")]
|
||||
public virtual void ValidGeneratorOutput_Issue22_Capnp_Bin()
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant6()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("Issue22.capnp.bin", ((string[])(null)));
|
||||
this.ValidGeneratorOutput("Issue22.capnp.bin", "false", "false", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 7")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 7")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant7()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableDisable.capnp.bin", "true", "false", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 8")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 8")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "warnings")]
|
||||
public virtual void ValidGeneratorOutput_Variant8()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableDisable.capnp.bin", "true", "true", "warnings", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 9")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 9")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant9()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "true", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 10")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 10")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")]
|
||||
public virtual void ValidGeneratorOutput_Variant10()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "false", "errors", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 11")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 11")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable2.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")]
|
||||
public virtual void ValidGeneratorOutput_Variant11()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableDisable2.capnp.bin", "false", "false", "errors", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 12")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 12")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable2.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant12()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableDisable2.capnp.bin", "false", "true", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 13")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 13")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable2.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")]
|
||||
public virtual void ValidGeneratorOutput_Variant13()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "false", "errors", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 14")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 14")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable2.capnp.bin")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
|
||||
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||
public virtual void ValidGeneratorOutput_Variant14()
|
||||
{
|
||||
#line 50
|
||||
this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "true", "success", ((string[])(null)));
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
[TestMethod]
|
||||
public void Test01NestedClash()
|
||||
{
|
||||
var (model, codegen) = LoadAndGenerate("UnitTest1.capnp.bin");
|
||||
var (model, codegen, _) = LoadAndGenerate("UnitTest1.capnp.bin");
|
||||
var structFoo = GetTypeDef(0x93db6ba5509bac24, model);
|
||||
var names = codegen.GetNames();
|
||||
var fieldName = names.GetCodeIdentifier(structFoo.Fields[0]).ToString();
|
||||
@ -51,7 +51,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
[TestMethod]
|
||||
public void Test10ImportedNamespaces()
|
||||
{
|
||||
var (model, codegen) = LoadAndGenerate("UnitTest10.capnp.bin");
|
||||
var (model, codegen, _) = LoadAndGenerate("UnitTest10.capnp.bin");
|
||||
var outerTypeDef = GetGeneratedFile("UnitTest10.capnp", model).NestedTypes.First();
|
||||
var outerType = Model.Types.FromDefinition(outerTypeDef);
|
||||
var innerType = outerTypeDef.Fields[0].Type;
|
||||
@ -81,6 +81,60 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
LoadAndGenerate("UnitTest12.capnp.bin");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test13CSharpNamespace()
|
||||
{
|
||||
var (model, _, _) = LoadAndGenerate("UnitTest13.capnp.bin");
|
||||
var outerTypeDef = GetGeneratedFile("UnitTest13.capnp", model).NestedTypes.First();
|
||||
string[] outerNamespace = { "Foo", "Bar", "Baz" };
|
||||
CollectionAssert.AreEqual(outerNamespace, (outerTypeDef.DeclaringElement as Model.GenFile).Namespace);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test14CSharpNamespacePrecedesCxxNamespace()
|
||||
{
|
||||
var (model, _, _) = LoadAndGenerate("UnitTest14.capnp.bin");
|
||||
var outerTypeDef = GetGeneratedFile("UnitTest14.capnp", model).NestedTypes.First();
|
||||
string[] outerNamespace = { "Foo", "Bar", "Baz" };
|
||||
CollectionAssert.AreEqual(outerNamespace, (outerTypeDef.DeclaringElement as Model.GenFile).Namespace);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test15CSharpMemberNames()
|
||||
{
|
||||
var (_, _, code) = LoadAndGenerate("UnitTest15.capnp.bin");
|
||||
try
|
||||
{
|
||||
Assert.IsTrue(code.Contains("CsStruct", StringComparison.Ordinal), "Generated code must contain C# struct name");
|
||||
Assert.IsFalse(code.Contains("SomeStruct", StringComparison.Ordinal), "Generated code must not contain original struct name");
|
||||
Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name");
|
||||
Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name");
|
||||
Assert.IsTrue(code.Contains("CsUnion", StringComparison.Ordinal), "Generated code must contain C# union name");
|
||||
Assert.IsFalse(code.Contains("someUnion", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original union name");
|
||||
Assert.IsTrue(code.Contains("CsGroup", StringComparison.Ordinal), "Generated code must contain C# group name");
|
||||
Assert.IsFalse(code.Contains("someGroup", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original group name");
|
||||
Assert.IsTrue(code.Contains("CsEnum", StringComparison.Ordinal), "Generated code must contain C# enum name");
|
||||
Assert.IsFalse(code.Contains("SomeEnum", StringComparison.Ordinal), "Generated code must not contain original enum name");
|
||||
Assert.IsTrue(code.Contains("CsEnumerant", StringComparison.Ordinal), "Generated code must contain C# enumerant name");
|
||||
Assert.IsFalse(code.Contains("someEnumerant", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original enumerant name");
|
||||
Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name");
|
||||
Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name");
|
||||
Assert.IsTrue(code.Contains("CsInterface", StringComparison.Ordinal), "Generated code must contain C# interface name");
|
||||
Assert.IsFalse(code.Contains("SomeInterface", StringComparison.Ordinal), "Generated code must not contain original interface name");
|
||||
Assert.IsTrue(code.Contains("CsMethod", StringComparison.Ordinal), "Generated code must contain C# method name");
|
||||
Assert.IsFalse(code.Contains("someMethod", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original method name");
|
||||
Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name");
|
||||
Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name");
|
||||
Assert.IsTrue(code.Contains("CsResult", StringComparison.Ordinal), "Generated code must contain C# method parameter name");
|
||||
Assert.IsFalse(code.Contains("someResult", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original method parameter name");
|
||||
}
|
||||
catch (AssertFailedException)
|
||||
{
|
||||
Console.WriteLine(code);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test20AnnotationAndConst()
|
||||
{
|
||||
@ -93,15 +147,20 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
LoadAndGenerate("schema-with-offsets.capnp.bin");
|
||||
}
|
||||
|
||||
static (Model.SchemaModel, CodeGen.CodeGenerator) LoadAndGenerate(string inputName)
|
||||
static (Model.SchemaModel, CodeGen.CodeGenerator, string) LoadAndGenerate(string inputName)
|
||||
{
|
||||
var model = Load(inputName);
|
||||
var codegen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
|
||||
|
||||
var code = model.FilesToGenerate.Select(f => codegen.Transform(f)).ToArray();
|
||||
Assert.IsTrue(Util.InlineAssemblyCompiler.TryCompileCapnp(code), "Compilation was not successful");
|
||||
Assert.AreEqual(
|
||||
Util.InlineAssemblyCompiler.CompileSummary.Success,
|
||||
Util.InlineAssemblyCompiler.TryCompileCapnp(
|
||||
Microsoft.CodeAnalysis.NullableContextOptions.Disable,
|
||||
code),
|
||||
"Compilation was not successful with no warnings");
|
||||
|
||||
return (model, codegen);
|
||||
return (model, codegen, code[0]);
|
||||
}
|
||||
|
||||
static Model.GenFile GetGeneratedFile(string name, Model.SchemaModel model)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
@ -15,6 +16,8 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
string _inputSchemaFileName;
|
||||
string _inputSchema;
|
||||
string _referenceOutputContent;
|
||||
bool _nullableGenEnable;
|
||||
bool _nullableSupportEnable;
|
||||
|
||||
GenerationResult _result;
|
||||
|
||||
@ -56,6 +59,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName)
|
||||
{
|
||||
_inputStream = LoadResource(binaryRequestFileName);
|
||||
_nullableGenEnable = false; // Assume false by default, may be enabled later
|
||||
}
|
||||
|
||||
[Given(@"my reference output is ""(.*)""")]
|
||||
@ -71,9 +75,14 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
[When(@"I invoke capnpc-csharp")]
|
||||
public void WhenIInvokeCapnpc_Csharp()
|
||||
{
|
||||
Console.WriteLine($"Generate nullable reference types? {_nullableGenEnable}");
|
||||
|
||||
using (_inputStream)
|
||||
{
|
||||
_result = CapnpCompilation.GenerateFromStream(_inputStream);
|
||||
_result = CapnpCompilation.GenerateFromStream(_inputStream, new CodeGen.GeneratorOptions()
|
||||
{
|
||||
NullableEnableDefault = _nullableGenEnable
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,13 +122,6 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
Assert.IsNotNull(_result.Exception, "Expected an exception");
|
||||
}
|
||||
|
||||
[Then(@"the invocation must succeed and the generated code must compile")]
|
||||
public void ThenTheInvocationMustSucceedAndTheGeneratedCodeMustCompile()
|
||||
{
|
||||
Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful");
|
||||
Assert.IsTrue(Util.InlineAssemblyCompiler.TryCompileCapnp(_result.GeneratedFiles[0].GeneratedContent), "Compilation was not successful");
|
||||
}
|
||||
|
||||
[Given(@"capnp\.exe is installed on my system")]
|
||||
public void GivenCapnp_ExeIsInstalledOnMySystem()
|
||||
{
|
||||
@ -185,5 +187,69 @@ namespace CapnpC.CSharp.Generator.Tests
|
||||
{
|
||||
Assert.IsTrue(_result.Messages.Count >= 2);
|
||||
}
|
||||
|
||||
[Given(@"I enable generation of nullable reference types according to (.*)")]
|
||||
public void GivenIEnableGenerationOfNullableReferenceTypesAccordingTo(bool enable)
|
||||
{
|
||||
_nullableGenEnable = enable;
|
||||
}
|
||||
|
||||
[Given(@"I enable the compiler support of nullable reference types according to (.*)")]
|
||||
public void GivenIEnableTheCompilerSupportOfNullableReferenceTypesAccordingTo(bool enable)
|
||||
{
|
||||
_nullableSupportEnable = enable;
|
||||
}
|
||||
|
||||
[Then(@"the invocation must succeed and attempting to compile the generated code gives (.*)")]
|
||||
public void ThenTheInvocationMustSucceedAndAttemptingToCompileTheGeneratedCodeGives(string result)
|
||||
{
|
||||
Console.WriteLine($"Compiler supports nullable reference types? {_nullableSupportEnable}");
|
||||
|
||||
Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful");
|
||||
var summary = Util.InlineAssemblyCompiler.TryCompileCapnp(
|
||||
_nullableSupportEnable ? NullableContextOptions.Enable : NullableContextOptions.Disable,
|
||||
_result.GeneratedFiles[0].GeneratedContent);
|
||||
|
||||
try
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case "success":
|
||||
Assert.AreEqual(
|
||||
Util.InlineAssemblyCompiler.CompileSummary.Success,
|
||||
summary,
|
||||
"Compilation was expected to succeed");
|
||||
break;
|
||||
|
||||
case "warnings":
|
||||
Assert.AreEqual(
|
||||
Util.InlineAssemblyCompiler.CompileSummary.SuccessWithWarnings,
|
||||
summary,
|
||||
"Compilation was expected to produce warnings");
|
||||
break;
|
||||
|
||||
case "errors":
|
||||
Assert.AreEqual(
|
||||
Util.InlineAssemblyCompiler.CompileSummary.Error,
|
||||
summary,
|
||||
"Compilation was expected to fail");
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert.Fail("Test case bug: unknown outcome specified");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
catch (AssertFailedException)
|
||||
{
|
||||
string generated = _result.GeneratedFiles.Single().GeneratedContent;
|
||||
string path = Path.ChangeExtension(Path.GetTempFileName(), ".capnp.cs");
|
||||
File.WriteAllText(path, generated);
|
||||
Console.WriteLine($"Generated code was saved to {path}");
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
@0xbbfd48ae4b99d016;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.nullableEnable(false);
|
||||
|
||||
struct SomeStruct {
|
||||
strings @0 : List(Text);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
@0xbbfd48ae4b99d016;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.nullableEnable(false);
|
||||
$CSharp.emitNullableDirective(true);
|
||||
|
||||
struct SomeStruct {
|
||||
strings @0 : List(Text);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
@0xbbfd48ae4b99d016;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.nullableEnable(true);
|
||||
|
||||
struct SomeStruct {
|
||||
strings @0 : List(Text);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
@0xbbfd48ae4b99d016;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.nullableEnable(true);
|
||||
$CSharp.emitNullableDirective(true);
|
||||
|
||||
struct SomeStruct {
|
||||
strings @0 : List(Text);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
@0xbbfd48ae4b99d013;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.namespace("Foo.Bar.Baz");
|
||||
|
||||
struct SomeStruct {
|
||||
}
|
10
CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp
Normal file
10
CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp
Normal file
@ -0,0 +1,10 @@
|
||||
@0xbbfd48ae4b99d014;
|
||||
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
$CSharp.namespace("Foo.Bar.Baz");
|
||||
$Cxx.namespace("X::Y::Z");
|
||||
|
||||
struct SomeStruct {
|
||||
}
|
25
CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp
Normal file
25
CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp
Normal file
@ -0,0 +1,25 @@
|
||||
@0xbbfd48ae4b99d013;
|
||||
|
||||
using CSharp = import "/csharp.capnp";
|
||||
|
||||
struct SomeStruct $CSharp.name("CsStruct") {
|
||||
someField @0 : Int32 $CSharp.name("CsField");
|
||||
|
||||
someUnion : union $CSharp.name("CsUnion") {
|
||||
u0 @1 : Int32;
|
||||
u1 @2 : Int32;
|
||||
}
|
||||
|
||||
someGroup : group $CSharp.name("CsGroup") {
|
||||
g0 @3 : Int32;
|
||||
g1 @4 : Int32;
|
||||
}
|
||||
}
|
||||
|
||||
enum SomeEnum $CSharp.name("CsEnum") {
|
||||
someEnumerant @0 $CSharp.name("CsEnumerant");
|
||||
}
|
||||
|
||||
interface SomeInterface $CSharp.name("CsInterface") {
|
||||
someMethod @0 () -> (someResult :Bool $CSharp.name("CsResult") ) $CSharp.name("CsMethod");
|
||||
}
|
@ -1,25 +1,27 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace CapnpC.CSharp.Generator.Tests.Util
|
||||
{
|
||||
class InlineAssemblyCompiler
|
||||
{
|
||||
public static bool TryCompileCapnp(string code)
|
||||
public enum CompileSummary
|
||||
{
|
||||
return TryCompileCapnp(new[] {code});
|
||||
Success,
|
||||
SuccessWithWarnings,
|
||||
Error
|
||||
}
|
||||
|
||||
public static bool TryCompileCapnp(string[] code)
|
||||
public static CompileSummary TryCompileCapnp(NullableContextOptions nullableContextOptions, params string[] code)
|
||||
{
|
||||
var options = new CSharpCompilationOptions(
|
||||
OutputKind.DynamicallyLinkedLibrary,
|
||||
optimizationLevel: OptimizationLevel.Debug);
|
||||
optimizationLevel: OptimizationLevel.Debug,
|
||||
nullableContextOptions: nullableContextOptions);
|
||||
|
||||
string assemblyRoot = Path.GetDirectoryName(typeof(object).Assembly.Location);
|
||||
|
||||
@ -29,9 +31,13 @@ namespace CapnpC.CSharp.Generator.Tests.Util
|
||||
"Capnp.Net.Runtime",
|
||||
"bin",
|
||||
"Debug",
|
||||
"netcoreapp2.1",
|
||||
"netcoreapp3.0",
|
||||
"Capnp.Net.Runtime.dll"));
|
||||
|
||||
var parseOptions = CSharpParseOptions.Default;
|
||||
if (nullableContextOptions == NullableContextOptions.Disable)
|
||||
parseOptions = parseOptions.WithLanguageVersion(LanguageVersion.CSharp7_1);
|
||||
|
||||
var compilation = CSharpCompilation.Create(
|
||||
"CompilationTestAssembly",
|
||||
options: options,
|
||||
@ -42,7 +48,7 @@ namespace CapnpC.CSharp.Generator.Tests.Util
|
||||
MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Runtime.dll")),
|
||||
MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Private.CoreLib.dll")),
|
||||
MetadataReference.CreateFromFile(capnpRuntimePath) },
|
||||
syntaxTrees: Array.ConvertAll(code, new Converter<string, SyntaxTree>(c => CSharpSyntaxTree.ParseText(c))));
|
||||
syntaxTrees: Array.ConvertAll(code, new Converter<string, SyntaxTree>(c => CSharpSyntaxTree.ParseText(c, parseOptions))));
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
@ -61,7 +67,17 @@ namespace CapnpC.CSharp.Generator.Tests.Util
|
||||
}
|
||||
}
|
||||
|
||||
return emitResult.Success;
|
||||
if (emitResult.Success)
|
||||
{
|
||||
if (emitResult.Diagnostics.Any(diag => diag.Severity == DiagnosticSeverity.Warning))
|
||||
return CompileSummary.SuccessWithWarnings;
|
||||
else
|
||||
return CompileSummary.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CompileSummary.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,10 +27,11 @@ namespace CapnpC.CSharp.Generator
|
||||
/// <summary>
|
||||
/// Generates C# code from given input stream
|
||||
/// </summary>
|
||||
/// <param name="input">input stream containing the binary code generation request, which the frontend capnpc emits</param>
|
||||
/// <param name="input">Input stream containing the binary code generation request, which the frontend capnpc emits</param>
|
||||
/// <param name="options">Configuration options for code generator. If null, default options will be used.</param>
|
||||
/// <returns>generation result</returns>
|
||||
/// <exception cref="ArgumentNullException">if <paramref name="input"/> is null</exception>
|
||||
public static GenerationResult GenerateFromStream(Stream input)
|
||||
public static GenerationResult GenerateFromStream(Stream input, CodeGen.GeneratorOptions options)
|
||||
{
|
||||
if (input == null)
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
@ -41,7 +42,7 @@ namespace CapnpC.CSharp.Generator
|
||||
var dec = DeserializerState.CreateRoot(segments);
|
||||
var reader = Schema.CodeGeneratorRequest.Reader.Create(dec);
|
||||
var model = Model.SchemaModel.Create(reader);
|
||||
var codeGen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
|
||||
var codeGen = new CodeGen.CodeGenerator(model, options ?? new CodeGen.GeneratorOptions());
|
||||
return new GenerationResult(codeGen.Generate());
|
||||
}
|
||||
catch (Exception exception)
|
||||
@ -50,6 +51,14 @@ namespace CapnpC.CSharp.Generator
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates C# code from given input stream
|
||||
/// </summary>
|
||||
/// <param name="input">input stream containing the binary code generation request, which the frontend capnpc emits</param>
|
||||
/// <returns>generation result</returns>
|
||||
/// <exception cref="ArgumentNullException">if <paramref name="input"/> is null</exception>
|
||||
public static GenerationResult GenerateFromStream(Stream input) => GenerateFromStream(input, null);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes "capnp.exe -o-" with given additional arguments and redirects the output to the C# generator backend.
|
||||
/// </summary>
|
||||
|
@ -14,6 +14,7 @@
|
||||
internal class CodeGenerator
|
||||
{
|
||||
readonly SchemaModel _model;
|
||||
readonly GeneratorOptions _options;
|
||||
readonly GenNames _names;
|
||||
readonly CommonSnippetGen _commonGen;
|
||||
readonly DomainClassSnippetGen _domClassGen;
|
||||
@ -24,6 +25,7 @@
|
||||
public CodeGenerator(SchemaModel model, GeneratorOptions options)
|
||||
{
|
||||
_model = model;
|
||||
_options = options;
|
||||
_names = new GenNames(options);
|
||||
_commonGen = new CommonSnippetGen(_names);
|
||||
_domClassGen = new DomainClassSnippetGen(_names);
|
||||
@ -61,7 +63,7 @@
|
||||
{
|
||||
var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier)
|
||||
.AddModifiers(Public)
|
||||
.AddBaseListTypes(SimpleBaseType(Type<Capnp.ICapnpSerializable>()));
|
||||
.AddBaseListTypes(SimpleBaseType(_names.Type<Capnp.ICapnpSerializable>(Nullability.NonNullable)));
|
||||
|
||||
if (def.GenericParameters.Count > 0)
|
||||
{
|
||||
@ -184,10 +186,26 @@
|
||||
|
||||
internal string Transform(GenFile file)
|
||||
{
|
||||
_names.NullableEnable = file.NullableEnable ?? _options.NullableEnableDefault;
|
||||
|
||||
NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace;
|
||||
|
||||
var ns = NamespaceDeclaration(topNamespace);
|
||||
|
||||
if (file.EmitNullableDirective)
|
||||
{
|
||||
ns = ns.WithLeadingTrivia(
|
||||
Trivia(
|
||||
NullableDirectiveTrivia(
|
||||
Token(_names.NullableEnable ? SyntaxKind.EnableKeyword : SyntaxKind.DisableKeyword),
|
||||
true)))
|
||||
.WithTrailingTrivia(
|
||||
Trivia(
|
||||
NullableDirectiveTrivia(
|
||||
Token(SyntaxKind.RestoreKeyword),
|
||||
true)));
|
||||
}
|
||||
|
||||
foreach (var def in file.NestedTypes)
|
||||
{
|
||||
ns = ns.AddMembers(Transform(def).ToArray());
|
||||
@ -204,7 +222,15 @@
|
||||
UsingDirective(ParseName("Capnp")),
|
||||
UsingDirective(ParseName("Capnp.Rpc")),
|
||||
UsingDirective(ParseName("System")),
|
||||
UsingDirective(ParseName("System.Collections.Generic")),
|
||||
UsingDirective(ParseName("System.Collections.Generic")));
|
||||
|
||||
if (_names.NullableEnable)
|
||||
{
|
||||
cu = cu.AddUsings(
|
||||
UsingDirective(ParseName("System.Diagnostics.CodeAnalysis")));
|
||||
}
|
||||
|
||||
cu = cu.AddUsings(
|
||||
UsingDirective(ParseName("System.Threading")),
|
||||
UsingDirective(ParseName("System.Threading.Tasks")));
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
var whichEnum = EnumDeclaration(_names.UnionDiscriminatorEnum.ToString())
|
||||
.AddModifiers(Public)
|
||||
.AddBaseListTypes(SimpleBaseType(Type<ushort>()));
|
||||
.AddBaseListTypes(SimpleBaseType(_names.Type<ushort>(Nullability.NonNullable)));
|
||||
|
||||
var discFields = def.Fields.Where(f => f.DiscValue.HasValue);
|
||||
|
||||
@ -49,14 +49,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
public EnumDeclarationSyntax MakeEnum(TypeDefinition def)
|
||||
{
|
||||
var decl = EnumDeclaration(def.Name)
|
||||
var decl = EnumDeclaration(_names.GetCodeIdentifier(def))
|
||||
.WithAttributeLists(MakeTypeIdAttributeLists(def.Id))
|
||||
.AddModifiers(Public)
|
||||
.AddBaseListTypes(SimpleBaseType(Type<ushort>()));
|
||||
.AddBaseListTypes(SimpleBaseType(_names.Type<ushort>(Nullability.NonNullable)));
|
||||
|
||||
foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder))
|
||||
{
|
||||
var mdecl = EnumMemberDeclaration(enumerant.Literal);
|
||||
var mdecl = EnumMemberDeclaration(enumerant.CsLiteral ?? enumerant.Literal);
|
||||
|
||||
if (enumerant.Ordinal.HasValue)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
|
||||
using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
@ -20,7 +21,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
MemberDeclarationSyntax MakeUnionField(Field field)
|
||||
{
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClassNullable);
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClass, Nullability.NullableRefAndValue);
|
||||
|
||||
switch (field.Type.Tag)
|
||||
{
|
||||
@ -75,7 +76,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
return null;
|
||||
}
|
||||
|
||||
var prop = PropertyDeclaration(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClass),
|
||||
var prop = PropertyDeclaration(
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClass, Nullability.NullableRef),
|
||||
_names.GetCodeIdentifier(field).Identifier)
|
||||
.AddModifiers(Public).AddAccessorListAccessors(
|
||||
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
|
||||
@ -111,7 +113,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
MemberDeclarationSyntax MakeUnionContentField()
|
||||
{
|
||||
return FieldDeclaration(
|
||||
VariableDeclaration(SyntaxHelpers.Type<object>())
|
||||
VariableDeclaration(_names.Type<object>(Nullability.NullableRef))
|
||||
.WithVariables(
|
||||
SingletonSeparatedList<VariableDeclaratorSyntax>(
|
||||
VariableDeclarator(_names.UnionContentField.Identifier))))
|
||||
@ -163,7 +165,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
case TypeTag.Enum:
|
||||
return MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.MakeTypeSyntax(value.Type, scope, TypeUsage.NotRelevant),
|
||||
_names.MakeTypeSyntax(value.Type, scope, TypeUsage.NotRelevant, Nullability.NonNullable),
|
||||
IdentifierName(value.GetEnumerant().Literal));
|
||||
|
||||
case TypeTag.F32:
|
||||
@ -262,7 +264,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
value.Decode();
|
||||
|
||||
return ObjectCreationExpression(
|
||||
_names.MakeTypeSyntax(value.Type, scope, TypeUsage.DomainClass))
|
||||
_names.MakeTypeSyntax(value.Type, scope, TypeUsage.DomainClass, Nullability.NonNullable))
|
||||
.WithArgumentList(ArgumentList())
|
||||
.WithInitializer(
|
||||
InitializerExpression(
|
||||
@ -282,7 +284,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
value.Decode();
|
||||
|
||||
return ArrayCreationExpression(ArrayType(
|
||||
_names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClass))
|
||||
_names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClass, Nullability.NullableRef))
|
||||
.WithRankSpecifiers(
|
||||
SingletonList<ArrayRankSpecifierSyntax>(
|
||||
ArrayRankSpecifier(
|
||||
@ -344,7 +346,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
case TypeTag.Enum:
|
||||
return CastExpression(
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant),
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant, Nullability.NonNullable),
|
||||
LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)));
|
||||
|
||||
case TypeTag.F32:
|
||||
@ -451,13 +453,18 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
Argument(domain),
|
||||
Argument(
|
||||
ParenthesizedLambdaExpression(
|
||||
ParameterList(
|
||||
SeparatedList<ParameterSyntax>(
|
||||
new SyntaxNodeOrToken[]
|
||||
{
|
||||
Parameter(Identifier(s)),
|
||||
Token(SyntaxKind.CommaToken),
|
||||
Parameter(Identifier(v))
|
||||
})),
|
||||
MakeComplexSerializeParticle(
|
||||
type.ElementType,
|
||||
IdentifierName(s),
|
||||
IdentifierName(v)))
|
||||
.AddParameterListParameters(
|
||||
Parameter(Identifier(s)),
|
||||
Parameter(Identifier(v)))));
|
||||
IdentifierName(v)))));
|
||||
|
||||
default:
|
||||
return InvocationExpression(
|
||||
@ -488,6 +495,11 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionSyntax ConditionalSuppressNullableWarning(ExpressionSyntax expression, bool suppress)
|
||||
{
|
||||
return suppress ? _names.SuppressNullableWarning(expression) : expression;
|
||||
}
|
||||
|
||||
StatementSyntax MakeSerializeMethodFieldAssignment(Field field)
|
||||
{
|
||||
var writerProp = MemberAccessExpression(
|
||||
@ -519,7 +531,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
writerProp,
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.GetCodeIdentifier(field).IdentifierName,
|
||||
_names.SuppressNullableWarning(_names.GetCodeIdentifier(field).IdentifierName),
|
||||
IdentifierName(nameof(Nullable<int>.Value)))));
|
||||
}
|
||||
else
|
||||
@ -538,10 +550,11 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
MemberAccessExpression(
|
||||
ConditionalSuppressNullableWarning(MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.WriterParameter.IdentifierName,
|
||||
_names.GetCodeIdentifier(field).IdentifierName),
|
||||
field.DiscValue.HasValue),
|
||||
IdentifierName(nameof(Capnp.DynamicSerializerState.SetObject))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(_names.GetCodeIdentifier(field).IdentifierName)));
|
||||
@ -568,7 +581,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
return ExpressionStatement(
|
||||
MakeComplexSerializeParticle(
|
||||
field.Type,
|
||||
writerProp,
|
||||
field.DiscValue.HasValue ? _names.SuppressNullableWarning(writerProp) : writerProp,
|
||||
_names.GetCodeIdentifier(field).IdentifierName));
|
||||
|
||||
case TypeTag.Void:
|
||||
@ -599,10 +612,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
ExpressionSyntax MakeInnerStructListConversion(ExpressionSyntax context, TypeSyntax elementType)
|
||||
{
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
return ConditionalAccessExpression(
|
||||
context,
|
||||
InvocationExpression(
|
||||
MemberBindingExpression(
|
||||
IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList))))
|
||||
.AddArgumentListArguments(Argument(
|
||||
SimpleLambdaExpression(Parameter(Identifier("_")),
|
||||
@ -611,8 +624,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
IdentifierName(nameof(Capnp.CapnpSerializable)),
|
||||
GenericName(nameof(Capnp.CapnpSerializable.Create))
|
||||
.AddTypeArgumentListArguments(elementType)))
|
||||
.AddArgumentListArguments(Argument(IdentifierName("_"))))));
|
||||
.AddTypeArgumentListArguments(MakeNonNullableType(elementType))))
|
||||
.AddArgumentListArguments(Argument(IdentifierName("_")))))));
|
||||
}
|
||||
|
||||
ExpressionSyntax MakeStructListConversion(ExpressionSyntax context, TypeSyntax elementType, int rank)
|
||||
@ -624,28 +637,28 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
string lambdaVarName = $"_{rank}";
|
||||
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
return ConditionalAccessExpression(
|
||||
context,
|
||||
InvocationExpression(
|
||||
MemberBindingExpression(
|
||||
IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList))))
|
||||
.AddArgumentListArguments(Argument(
|
||||
SimpleLambdaExpression(
|
||||
Parameter(Identifier(lambdaVarName)),
|
||||
MakeStructListConversion(IdentifierName(lambdaVarName), elementType, rank - 1))));
|
||||
MakeStructListConversion(IdentifierName(lambdaVarName), elementType, rank - 1)))));
|
||||
}
|
||||
|
||||
ExpressionSyntax MakeAnyListConversion(ExpressionSyntax context)
|
||||
{
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
return ConditionalAccessExpression(
|
||||
context,
|
||||
InvocationExpression(
|
||||
MemberBindingExpression(
|
||||
IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList))))
|
||||
.AddArgumentListArguments(Argument(
|
||||
SimpleLambdaExpression(
|
||||
Parameter(Identifier("_")),
|
||||
CastExpression(Type<object>(), IdentifierName("_")))));
|
||||
CastExpression(_names.Type<object>(Nullability.NonNullable), IdentifierName("_"))))));
|
||||
}
|
||||
|
||||
ExpressionSyntax MakeDeserializeMethodRightHandSide(Field field)
|
||||
@ -662,10 +675,11 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
IdentifierName(nameof(Capnp.CapnpSerializable)),
|
||||
GenericName(nameof(Capnp.CapnpSerializable.Create))
|
||||
.AddTypeArgumentListArguments(
|
||||
_names.MakeTypeSyntax(
|
||||
MakeNonNullableType(_names.MakeTypeSyntax(
|
||||
field.Type,
|
||||
field.DeclaringType,
|
||||
TypeUsage.DomainClass))))
|
||||
TypeUsage.DomainClass,
|
||||
Nullability.NonNullable)))))
|
||||
.AddArgumentListArguments(Argument(MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.ReaderParameter.IdentifierName,
|
||||
@ -684,7 +698,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.ReaderParameter.IdentifierName,
|
||||
_names.GetCodeIdentifier(field).IdentifierName),
|
||||
_names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClass),
|
||||
_names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClass, Nullability.NullableRef),
|
||||
rank);
|
||||
|
||||
case TypeTag.ListPointer:
|
||||
@ -716,18 +730,6 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
if (unionField.Type.Tag != TypeTag.Void)
|
||||
{
|
||||
ExpressionSyntax right = _names.GetCodeIdentifier(unionField).IdentifierName;
|
||||
|
||||
var syntax = _names.MakeTypeSyntax(unionField.Type, unionField.DeclaringType, TypeUsage.DomainClassNullable);
|
||||
|
||||
if (syntax is NullableTypeSyntax)
|
||||
{
|
||||
right = MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
right,
|
||||
IdentifierName(nameof(Nullable<int>.Value)));
|
||||
}
|
||||
|
||||
section = section.AddStatements(MakeSerializeMethodFieldAssignment(unionField));
|
||||
}
|
||||
|
||||
@ -849,7 +851,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable))))
|
||||
.AddParameterListParameters(
|
||||
Parameter(_names.AnonymousParameter.Identifier)
|
||||
.WithType(Type<Capnp.SerializerState>()))
|
||||
.WithType(_names.Type<Capnp.SerializerState>(Nullability.NonNullable)))
|
||||
.AddBodyStatements(
|
||||
ExpressionStatement(
|
||||
InvocationExpression(_names.SerializeMethod.IdentifierName)
|
||||
@ -933,7 +935,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable))))
|
||||
.AddParameterListParameters(
|
||||
Parameter(_names.AnonymousParameter.Identifier)
|
||||
.WithType(Type<Capnp.DeserializerState>()))
|
||||
.WithType(_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)))
|
||||
.AddBodyStatements(stmts.ToArray());
|
||||
}
|
||||
|
||||
@ -944,7 +946,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
if (def.UnionInfo != null)
|
||||
{
|
||||
yield return MakeUnionDiscriminatorField();
|
||||
if (def.Fields.Any(f => f.DiscValue.HasValue && f.Type.Tag != TypeTag.Void))
|
||||
{
|
||||
yield return MakeUnionContentField();
|
||||
}
|
||||
yield return MakeUnionDiscriminatorProperty(def);
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,17 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
NotRelevant,
|
||||
DomainClass,
|
||||
DomainClassNullable,
|
||||
Reader,
|
||||
Writer
|
||||
}
|
||||
|
||||
enum Nullability
|
||||
{
|
||||
NonNullable,
|
||||
NullableRefAndValue,
|
||||
NullableRef
|
||||
}
|
||||
|
||||
class GenNames
|
||||
{
|
||||
readonly Dictionary<Field, Name> _fieldNameMap = new Dictionary<Field, Name>();
|
||||
@ -66,6 +72,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
public string PipeliningExtensionsClassFormat { get; }
|
||||
public string ProxyClassFormat { get; }
|
||||
public string SkeletonClassFormat { get; }
|
||||
public bool NullableEnable { get; set; }
|
||||
public GenNames(GeneratorOptions options)
|
||||
{
|
||||
TopNamespace = new Name(options.TopNamespaceName).IdentifierName;
|
||||
@ -106,12 +113,6 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
|
||||
public Name MakeTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default)
|
||||
{
|
||||
if (def.Tag == TypeTag.Group)
|
||||
{
|
||||
return new Name(SyntaxHelpers.MakeAllLower(def.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
string name;
|
||||
|
||||
@ -124,7 +125,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
switch (def.SpecialName)
|
||||
{
|
||||
case SpecialName.NothingSpecial:
|
||||
name = def.Name;
|
||||
name = GetCodeIdentifier(def);
|
||||
break;
|
||||
|
||||
case SpecialName.MethodParamsStruct:
|
||||
@ -141,19 +142,19 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
break;
|
||||
|
||||
case NameUsage.Namespace:
|
||||
name = def.Name;
|
||||
name = GetCodeIdentifier(def);
|
||||
break;
|
||||
|
||||
case NameUsage.Interface:
|
||||
name = "I" + def.Name;
|
||||
name = "I" + GetCodeIdentifier(def);
|
||||
break;
|
||||
|
||||
case NameUsage.Proxy:
|
||||
name = string.Format(ProxyClassFormat, def.Name);
|
||||
name = string.Format(ProxyClassFormat, GetCodeIdentifier(def));
|
||||
break;
|
||||
|
||||
case NameUsage.Skeleton:
|
||||
name = string.Format(SkeletonClassFormat, def.Name);
|
||||
name = string.Format(SkeletonClassFormat, GetCodeIdentifier(def));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -162,7 +163,6 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
return new Name(name);
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleNameSyntax MakeGenericTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default)
|
||||
{
|
||||
@ -184,7 +184,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
TypeSyntax ResolveGenericParameter(GenericParameter p, Model.Type boundType, TypeDefinition def)
|
||||
{
|
||||
var type = boundType.ResolveGenericParameter(p);
|
||||
return MakeTypeSyntax(type, def, TypeUsage.DomainClass);
|
||||
return MakeTypeSyntax(type, def, TypeUsage.DomainClass, Nullability.NonNullable);
|
||||
}
|
||||
|
||||
public SimpleNameSyntax MakeGenericTypeName(TypeDefinition def, Model.Type boundType, NameUsage usage = NameUsage.Default)
|
||||
@ -224,10 +224,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
NameSyntax ident = null;
|
||||
if (@namespace != null)
|
||||
{
|
||||
ident = IdentifierName(SyntaxHelpers.MakeCamel(@namespace[0]));
|
||||
ident = IdentifierName(SyntaxHelpers.MakeUpperCamel(@namespace[0]));
|
||||
foreach (string name in @namespace.Skip(1))
|
||||
{
|
||||
var temp = IdentifierName(SyntaxHelpers.MakeCamel(name));
|
||||
var temp = IdentifierName(SyntaxHelpers.MakeUpperCamel(name));
|
||||
ident = QualifiedName(ident, temp);
|
||||
}
|
||||
}
|
||||
@ -288,82 +288,82 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
case TypeTag.AnyPointer:
|
||||
case TypeTag.StructPointer:
|
||||
case TypeTag.ListPointer:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPointersSerializer<Capnp.DynamicSerializerState>>();
|
||||
return Type<Capnp.ListOfPointersSerializer<Capnp.DynamicSerializerState>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.CapabilityPointer:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfCapsSerializer<Capnp.Rpc.BareProxy>>();
|
||||
return Type<Capnp.ListOfCapsSerializer<Capnp.Rpc.BareProxy>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.Data:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPointersSerializer<
|
||||
Capnp.ListOfPrimitivesSerializer<byte>>>();
|
||||
return Type<Capnp.ListOfPointersSerializer<
|
||||
Capnp.ListOfPrimitivesSerializer<byte>>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.Enum:
|
||||
return GenericName("ListOfPrimitivesSerializer")
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer));
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer, Nullability.NonNullable));
|
||||
|
||||
case TypeTag.Group:
|
||||
case TypeTag.Struct:
|
||||
return GenericName("ListOfStructsSerializer")
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer));
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer, Nullability.NonNullable));
|
||||
|
||||
case TypeTag.Interface:
|
||||
return GenericName("ListOfCapsSerializer")
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer));
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer, Nullability.NonNullable));
|
||||
|
||||
case TypeTag.List:
|
||||
return GenericName("ListOfPointersSerializer")
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer));
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer, Nullability.NonNullable));
|
||||
|
||||
case TypeTag.Text:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfTextSerializer>();
|
||||
return Type<Capnp.ListOfTextSerializer>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.Void:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfEmptySerializer>();
|
||||
return Type<Capnp.ListOfEmptySerializer>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.Bool:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfBitsSerializer>();
|
||||
return Type<Capnp.ListOfBitsSerializer>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.F32:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<float>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<float>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.F64:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<double>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<double>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.S8:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<sbyte>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<sbyte>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.U8:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<byte>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<byte>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.S16:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<short>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<short>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.U16:
|
||||
case TypeTag.AnyEnum:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<ushort>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<ushort>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.S32:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<int>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<int>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.U32:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<uint>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<uint>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.S64:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<long>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<long>>(Nullability.NonNullable);
|
||||
|
||||
case TypeTag.U64:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<ulong>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<ulong>>(Nullability.NonNullable);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException("Unexpected type tag, don't know how to deal with this");
|
||||
}
|
||||
}
|
||||
|
||||
TypeSyntax MaybeNullableValueType(TypeSyntax typeSyntax, TypeUsage usage)
|
||||
TypeSyntax MaybeNullableValueType(TypeSyntax typeSyntax, Nullability nullability)
|
||||
{
|
||||
switch (usage)
|
||||
switch (nullability)
|
||||
{
|
||||
case TypeUsage.DomainClassNullable:
|
||||
case Nullability.NullableRefAndValue:
|
||||
return NullableType(typeSyntax);
|
||||
|
||||
default:
|
||||
@ -371,71 +371,80 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
}
|
||||
|
||||
public TypeSyntax MakeTypeSyntax(Model.Type type, TypeDefinition scope, TypeUsage usage)
|
||||
TypeSyntax MaybeNullableRefType(TypeSyntax typeSyntax, Nullability nullability)
|
||||
{
|
||||
if (!NullableEnable)
|
||||
return typeSyntax;
|
||||
|
||||
switch (nullability)
|
||||
{
|
||||
case Nullability.NullableRef:
|
||||
case Nullability.NullableRefAndValue:
|
||||
return NullableType(typeSyntax);
|
||||
|
||||
default:
|
||||
return typeSyntax;
|
||||
}
|
||||
}
|
||||
|
||||
public TypeSyntax MakeTypeSyntax(Model.Type type, TypeDefinition scope, TypeUsage usage, Nullability nullability)
|
||||
{
|
||||
switch (type.Tag)
|
||||
{
|
||||
case TypeTag.AnyEnum:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<ushort>(), usage);
|
||||
return Type<ushort>(nullability);
|
||||
|
||||
case TypeTag.CapabilityPointer:
|
||||
if (type.Parameter != null)
|
||||
{
|
||||
return GetQName(type, scope);
|
||||
}
|
||||
return MaybeNullableRefType(GetQName(type, scope), nullability);
|
||||
else
|
||||
{
|
||||
return SyntaxHelpers.Type<Capnp.Rpc.BareProxy>();
|
||||
}
|
||||
return Type<Capnp.Rpc.BareProxy>(nullability);
|
||||
|
||||
case TypeTag.AnyPointer:
|
||||
case TypeTag.StructPointer:
|
||||
switch (usage)
|
||||
{
|
||||
case TypeUsage.Reader:
|
||||
return SyntaxHelpers.Type<Capnp.DeserializerState>();
|
||||
return Type<Capnp.DeserializerState>(Nullability.NonNullable);
|
||||
|
||||
case TypeUsage.Writer:
|
||||
return SyntaxHelpers.Type<Capnp.DynamicSerializerState>();
|
||||
return Type<Capnp.DynamicSerializerState>(Nullability.NullableRef);
|
||||
|
||||
case TypeUsage.DomainClass when type.Parameter == null:
|
||||
return Type<object>(nullability);
|
||||
|
||||
case TypeUsage.DomainClass when nullability == Nullability.NonNullable:
|
||||
return GetQName(type, scope);
|
||||
|
||||
case TypeUsage.DomainClass:
|
||||
case TypeUsage.DomainClassNullable:
|
||||
if (type.Parameter != null)
|
||||
{
|
||||
return GetQName(type, scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SyntaxHelpers.Type<object>();
|
||||
}
|
||||
return MakeNullableRefType(GetQName(type, scope));
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
case TypeTag.Bool:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<bool>(), usage);
|
||||
return Type<bool>(nullability);
|
||||
|
||||
case TypeTag.Data:
|
||||
switch (usage)
|
||||
{
|
||||
case TypeUsage.Reader:
|
||||
case TypeUsage.DomainClass:
|
||||
case TypeUsage.DomainClassNullable:
|
||||
return SyntaxHelpers.Type<IReadOnlyList<byte>>();
|
||||
return Type<IReadOnlyList<byte>>(nullability);
|
||||
|
||||
case TypeUsage.Writer:
|
||||
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<byte>>();
|
||||
return Type<Capnp.ListOfPrimitivesSerializer<byte>>(nullability);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
case TypeTag.Enum:
|
||||
return MaybeNullableValueType(GetQName(type, scope), usage);
|
||||
return MaybeNullableValueType(GetQName(type, scope), nullability);
|
||||
|
||||
case TypeTag.Interface:
|
||||
return GetQName(type, scope);
|
||||
return MaybeNullableRefType(GetQName(type, scope), nullability);
|
||||
|
||||
case TypeTag.Struct:
|
||||
case TypeTag.Group:
|
||||
@ -447,37 +456,38 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
case TypeUsage.Reader:
|
||||
return QualifiedName(GetQName(type, scope), ReaderStruct.IdentifierName);
|
||||
|
||||
case TypeUsage.DomainClass:
|
||||
case TypeUsage.DomainClassNullable:
|
||||
case TypeUsage.DomainClass when nullability == Nullability.NonNullable:
|
||||
return GetQName(type, scope);
|
||||
|
||||
case TypeUsage.DomainClass:
|
||||
return MakeNullableRefType(GetQName(type, scope));
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
case TypeTag.F32:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<float>(), usage);
|
||||
return Type<float>(nullability);
|
||||
|
||||
case TypeTag.F64:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<double>(), usage);
|
||||
return Type<double>(nullability);
|
||||
|
||||
case TypeTag.List when type.ElementType.Tag == TypeTag.Void && usage != TypeUsage.Writer:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<int>(), usage);
|
||||
return Type<int>(nullability);
|
||||
|
||||
case TypeTag.List:
|
||||
switch (usage)
|
||||
{
|
||||
case TypeUsage.Writer:
|
||||
return MakeListSerializerSyntax(type.ElementType, scope);
|
||||
return MaybeNullableRefType(MakeListSerializerSyntax(type.ElementType, scope), nullability);
|
||||
|
||||
case TypeUsage.Reader:
|
||||
return GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.Reader));
|
||||
return MaybeNullableRefType(GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.Reader, Nullability.NonNullable)), nullability);
|
||||
|
||||
case TypeUsage.DomainClass:
|
||||
case TypeUsage.DomainClassNullable:
|
||||
return GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.DomainClass));
|
||||
return MaybeNullableRefType(GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.DomainClass, Nullability.NullableRef)), nullability);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
@ -487,45 +497,49 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
switch (usage)
|
||||
{
|
||||
case TypeUsage.Writer:
|
||||
return SyntaxHelpers.Type<Capnp.SerializerState>();
|
||||
return Type<Capnp.SerializerState>(Nullability.NonNullable);
|
||||
|
||||
case TypeUsage.Reader:
|
||||
return SyntaxHelpers.Type<IReadOnlyList<Capnp.DeserializerState>>();
|
||||
return Type<IReadOnlyList<Capnp.DeserializerState>>(Nullability.NonNullable);
|
||||
|
||||
case TypeUsage.DomainClass when nullability == Nullability.NonNullable:
|
||||
return GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(Type<object>(Nullability.NullableRef));
|
||||
|
||||
case TypeUsage.DomainClass:
|
||||
case TypeUsage.DomainClassNullable:
|
||||
return SyntaxHelpers.Type<IReadOnlyList<object>>();
|
||||
return MakeNullableRefType(GenericName(Identifier("IReadOnlyList"))
|
||||
.AddTypeArgumentListArguments(Type<object>(Nullability.NullableRef)));
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
case TypeTag.S16:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<short>(), usage);
|
||||
return Type<short>(nullability);
|
||||
|
||||
case TypeTag.S32:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<int>(), usage);
|
||||
return Type<int>(nullability);
|
||||
|
||||
case TypeTag.S64:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<long>(), usage);
|
||||
return Type<long>(nullability);
|
||||
|
||||
case TypeTag.S8:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<sbyte>(), usage);
|
||||
return Type<sbyte>(nullability);
|
||||
|
||||
case TypeTag.Text:
|
||||
return SyntaxHelpers.Type<string>();
|
||||
return Type<string>(nullability);
|
||||
|
||||
case TypeTag.U16:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<ushort>(), usage);
|
||||
return Type<ushort>(nullability);
|
||||
|
||||
case TypeTag.U32:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<uint>(), usage);
|
||||
return Type<uint>(nullability);
|
||||
|
||||
case TypeTag.U64:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<ulong>(), usage);
|
||||
return Type<ulong>(nullability);
|
||||
|
||||
case TypeTag.U8:
|
||||
return MaybeNullableValueType(SyntaxHelpers.Type<byte>(), usage);
|
||||
return Type<byte>(nullability);
|
||||
|
||||
case TypeTag.Void:
|
||||
return PredefinedType(Token(SyntaxKind.VoidKeyword));
|
||||
@ -537,19 +551,22 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
public string MakeParamsStructName(Method method)
|
||||
{
|
||||
return string.Format(ParamsStructFormat, method.Name);
|
||||
return string.Format(ParamsStructFormat, GetCodeIdentifier(method));
|
||||
}
|
||||
|
||||
public string MakeResultStructName(Method method)
|
||||
{
|
||||
return string.Format(ResultStructFormat, method.Name);
|
||||
return string.Format(ResultStructFormat, GetCodeIdentifier(method));
|
||||
}
|
||||
|
||||
public Name GetCodeIdentifier(Method method)
|
||||
{
|
||||
return new Name(SyntaxHelpers.MakeCamel(method.Name));
|
||||
return new Name(method.CsName ?? IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeUpperCamel(method.Name)));
|
||||
}
|
||||
|
||||
string GetCodeIdentifierUpperCamel(Field field) => field.CsName ?? SyntaxHelpers.MakeUpperCamel(field.Name);
|
||||
string GetCodeIdentifierLowerCamel(Field field) => field.CsName ?? IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeLowerCamel(field.Name));
|
||||
|
||||
public Name GetCodeIdentifier(Field field)
|
||||
{
|
||||
if (_fieldNameMap.TryGetValue(field, out var name))
|
||||
@ -563,7 +580,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
// Method parameters are internally represented with the same class "Field".
|
||||
// They do not have a declaring type. Anyway, they don't suffer from the field-name-equals-nested-type-name problem.
|
||||
return new Name(SyntaxHelpers.MakeCamel(field.Name));
|
||||
return new Name(GetCodeIdentifierLowerCamel(field));
|
||||
}
|
||||
|
||||
var typeNames = new HashSet<Name>(def.NestedTypes.Select(t => MakeTypeName(t)));
|
||||
@ -571,7 +588,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
foreach (var member in def.Fields)
|
||||
{
|
||||
var memberName = new Name(SyntaxHelpers.MakeCamel(member.Name));
|
||||
var memberName = new Name(GetCodeIdentifierUpperCamel(member));
|
||||
|
||||
while (typeNames.Contains(memberName))
|
||||
{
|
||||
@ -584,6 +601,16 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
return _fieldNameMap[field];
|
||||
}
|
||||
|
||||
public string GetCodeIdentifier(TypeDefinition def)
|
||||
{
|
||||
string id = def.CsName ?? def.Name;
|
||||
if (def.Tag == TypeTag.Group) // special treatment for groups: Need to disambiguate between
|
||||
{ // the field name (use original name) and its type (make it start with a lower-case letter)
|
||||
id = IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeLowerCamel(id));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public Name GetGenericTypeParameter(string name)
|
||||
{
|
||||
return new Name(string.Format(GenericTypeParameterFormat, name));
|
||||
@ -637,5 +664,28 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
method.Name,
|
||||
MakePipeliningSupportExtensionMethodName(path)));
|
||||
}
|
||||
|
||||
public TypeSyntax MakeNullableRefType(TypeSyntax type)
|
||||
{
|
||||
return NullableEnable ?
|
||||
NullableType(type) :
|
||||
type;
|
||||
|
||||
}
|
||||
|
||||
public TypeSyntax Type<T>(Nullability nullability)
|
||||
{
|
||||
return (NullableEnable && !typeof(T).IsValueType && nullability != Nullability.NonNullable) ||
|
||||
( typeof(T).IsValueType && nullability == Nullability.NullableRefAndValue) ?
|
||||
NullableType(SyntaxHelpers.NonNullableType<T>()) :
|
||||
SyntaxHelpers.NonNullableType<T>();
|
||||
}
|
||||
|
||||
public ExpressionSyntax SuppressNullableWarning(ExpressionSyntax expression)
|
||||
{
|
||||
return NullableEnable ?
|
||||
PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expression) :
|
||||
expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
class GeneratorOptions
|
||||
public class GeneratorOptions
|
||||
{
|
||||
public string TopNamespaceName { get; set; } = "CapnpGen";
|
||||
public string ReaderStructName { get; set; } = "READER";
|
||||
@ -37,5 +37,6 @@
|
||||
public string TaskParameterName { get; set; } = "task";
|
||||
public string EagerMethodName { get; set; } = "Eager";
|
||||
public string TypeIdFieldName { get; set; } = "typeId";
|
||||
public bool NullableEnableDefault { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
@ -27,15 +28,19 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
case 0:
|
||||
return IdentifierName(nameof(Task));
|
||||
|
||||
case 1 when method.Results[0].Type.Tag == TypeTag.Struct:
|
||||
return GenericName(nameof(Task)).AddTypeArgumentListArguments(
|
||||
_names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NonNullable));
|
||||
|
||||
case 1:
|
||||
return GenericName(nameof(Task)).AddTypeArgumentListArguments(
|
||||
_names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClass));
|
||||
_names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NullableRef));
|
||||
|
||||
default:
|
||||
return GenericName(nameof(Task)).AddTypeArgumentListArguments(
|
||||
TupleType(SeparatedList(
|
||||
method.Results.Select(
|
||||
f => TupleElement(_names.MakeTypeSyntax(f.Type, method.DeclaringInterface, TypeUsage.DomainClass))))));
|
||||
f => TupleElement(_names.MakeTypeSyntax(f.Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NullableRef))))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,14 +55,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
if (arg0.Name == null)
|
||||
{
|
||||
list.Add(Parameter(_names.AnonymousParameter.Identifier)
|
||||
.WithType(_names.MakeTypeSyntax(arg0.Type, method.DeclaringInterface, TypeUsage.DomainClass)));
|
||||
.WithType(_names.MakeTypeSyntax(arg0.Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NullableRef)));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var arg in method.Params)
|
||||
{
|
||||
list.Add(Parameter(Identifier(IdentifierRenamer.ToNonKeyword(arg.Name)))
|
||||
.WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClass)));
|
||||
list.Add(Parameter(_names.GetCodeIdentifier(arg).Identifier)
|
||||
.WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NullableRef)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,7 +129,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
ifaceDecl = ifaceDecl.AddBaseListTypes(
|
||||
SimpleBaseType(_names.MakeTypeSyntax(
|
||||
superClass, type,
|
||||
TypeUsage.NotRelevant)));
|
||||
TypeUsage.DomainClass,
|
||||
Nullability.NonNullable)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,12 +188,15 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
IEnumerable<ExpressionSyntax> MakeProxyCallInitializerAssignments(Method method)
|
||||
{
|
||||
foreach (var methodParam in method.Params)
|
||||
for (int i = 0; i < method.Params.Count; i++)
|
||||
{
|
||||
var methodParam = method.Params[i];
|
||||
var field = method.ParamsStruct.Fields[i];
|
||||
|
||||
yield return AssignmentExpression(
|
||||
SyntaxKind.SimpleAssignmentExpression,
|
||||
_names.GetCodeIdentifier(methodParam).IdentifierName,
|
||||
IdentifierName(IdentifierRenamer.ToNonKeyword(methodParam.Name)));
|
||||
_names.GetCodeIdentifier(field).IdentifierName,
|
||||
_names.GetCodeIdentifier(methodParam).IdentifierName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,17 +235,24 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
StatementSyntax MakeProxyCreateResult(Method method)
|
||||
{
|
||||
var resultType = method.ResultStruct;
|
||||
var domainType = _names.MakeTypeSyntax(resultType, method.DeclaringInterface, TypeUsage.DomainClass);
|
||||
var domainType = _names.MakeTypeSyntax(resultType, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NonNullable);
|
||||
|
||||
var createDomain = InvocationExpression(
|
||||
ExpressionSyntax createDomain = InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
IdentifierName(nameof(Capnp.CapnpSerializable)),
|
||||
GenericName(nameof(Capnp.CapnpSerializable.Create))
|
||||
.AddTypeArgumentListArguments(domainType)))
|
||||
.AddTypeArgumentListArguments(MakeNonNullableType(domainType))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(_names.DeserializerLocal.IdentifierName));
|
||||
|
||||
if (_names.NullableEnable)
|
||||
{
|
||||
createDomain = PostfixUnaryExpression(
|
||||
SyntaxKind.SuppressNullableWarningExpression,
|
||||
createDomain);
|
||||
}
|
||||
|
||||
return LocalDeclarationStatement(
|
||||
VariableDeclaration(
|
||||
IdentifierName("var"))
|
||||
@ -271,7 +287,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
var classDecl = ClassDeclaration(_names.MakeTypeName(type, NameUsage.Proxy).Identifier)
|
||||
.AddModifiers(Public)
|
||||
.AddBaseListTypes(
|
||||
SimpleBaseType(Type<Capnp.Rpc.Proxy>()),
|
||||
SimpleBaseType(_names.Type<Capnp.Rpc.Proxy>(Nullability.NonNullable)),
|
||||
SimpleBaseType(_names.MakeGenericTypeName(type, NameUsage.Interface)));
|
||||
|
||||
if (type.GenericParameters.Count > 0)
|
||||
@ -311,7 +327,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
_names.MakeTypeSyntax(
|
||||
method.ParamsStruct,
|
||||
method.ParamsStruct.Definition,
|
||||
TypeUsage.Writer))))))))))));
|
||||
TypeUsage.Writer, Nullability.NonNullable))))))))))));
|
||||
|
||||
if (method.ParamsStruct.Definition.SpecialName == SpecialName.MethodParamsStruct)
|
||||
{
|
||||
@ -328,7 +344,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
_names.MakeTypeSyntax(
|
||||
method.ParamsStruct,
|
||||
method.ParamsStruct.Definition,
|
||||
TypeUsage.DomainClass))
|
||||
TypeUsage.DomainClass,
|
||||
Nullability.NonNullable))
|
||||
.WithArgumentList(
|
||||
ArgumentList())
|
||||
.WithInitializer(
|
||||
@ -340,13 +357,12 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
|
||||
bodyStmts.Add(ExpressionStatement(
|
||||
InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
ConditionalAccessExpression(
|
||||
_names.AnonymousParameter.IdentifierName,
|
||||
_names.SerializeMethod.IdentifierName))
|
||||
InvocationExpression(
|
||||
MemberBindingExpression(_names.SerializeMethod.IdentifierName))
|
||||
.AddArgumentListArguments(
|
||||
Argument(_names.ParamsLocal.IdentifierName))));
|
||||
Argument(_names.ParamsLocal.IdentifierName)))));
|
||||
|
||||
var call = InvocationExpression(IdentifierName(nameof(Capnp.Rpc.BareProxy.Call)))
|
||||
.AddArgumentListArguments(
|
||||
@ -361,7 +377,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.ParamsLocal.IdentifierName,
|
||||
GenericName(nameof(Capnp.SerializerState.Rewrap))
|
||||
.AddTypeArgumentListArguments(Type<Capnp.DynamicSerializerState>())))
|
||||
.AddTypeArgumentListArguments(_names.Type<Capnp.DynamicSerializerState>(Nullability.NonNullable))))
|
||||
.AddArgumentListArguments()),
|
||||
Argument(
|
||||
LiteralExpression(SyntaxKind.FalseLiteralExpression)),
|
||||
@ -446,7 +462,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
GenericName(_names.GetCodeIdentifier(method).ToString())
|
||||
.AddTypeArgumentListArguments(
|
||||
Enumerable.Repeat(
|
||||
Type<Capnp.AnyPointer>(),
|
||||
_names.Type<Capnp.AnyPointer>(Nullability.NonNullable),
|
||||
method.GenericParameters.Count).ToArray()));
|
||||
}
|
||||
else
|
||||
@ -502,7 +518,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
_names.MakeTypeSyntax(
|
||||
method.ResultStruct,
|
||||
method.ResultStruct.Definition,
|
||||
TypeUsage.Writer)))))))))));
|
||||
TypeUsage.Writer, Nullability.NonNullable)))))))))));
|
||||
|
||||
}
|
||||
|
||||
@ -523,7 +539,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
_names.MakeTypeSyntax(
|
||||
method.ResultStruct,
|
||||
method.ResultStruct.Definition,
|
||||
TypeUsage.DomainClass))
|
||||
TypeUsage.DomainClass,
|
||||
Nullability.NonNullable))
|
||||
.WithInitializer(
|
||||
InitializerExpression(SyntaxKind.ObjectInitializerExpression)
|
||||
.AddExpressions(
|
||||
@ -575,17 +592,24 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
if (method.Params.Count > 0)
|
||||
{
|
||||
var paramsType = method.ParamsStruct;
|
||||
var domainType = _names.MakeTypeSyntax(paramsType, method.ParamsStruct.Definition, TypeUsage.DomainClass);
|
||||
var domainType = _names.MakeTypeSyntax(paramsType, method.ParamsStruct.Definition, TypeUsage.DomainClass, Nullability.NonNullable);
|
||||
|
||||
var createDomain = InvocationExpression(
|
||||
ExpressionSyntax createDomain = InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
IdentifierName(nameof(Capnp.CapnpSerializable)),
|
||||
GenericName(nameof(Capnp.CapnpSerializable.Create))
|
||||
.AddTypeArgumentListArguments(domainType)))
|
||||
.AddTypeArgumentListArguments(MakeNonNullableType(domainType))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(_names.DeserializerLocal.IdentifierName));
|
||||
|
||||
if (_names.NullableEnable)
|
||||
{
|
||||
createDomain = PostfixUnaryExpression(
|
||||
SyntaxKind.SuppressNullableWarningExpression,
|
||||
createDomain);
|
||||
}
|
||||
|
||||
if (method.ParamsStruct.Definition.SpecialName == SpecialName.MethodParamsStruct)
|
||||
{
|
||||
yield return LocalDeclarationStatement(
|
||||
@ -630,10 +654,19 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
else
|
||||
{
|
||||
// CodeAnalysis.CSharp 3.2.1 has a bug which prevents us from using AddParameterListParameters. :-(
|
||||
|
||||
var paramList = new List<SyntaxNodeOrToken>();
|
||||
foreach (var arg in method.Results)
|
||||
{
|
||||
if (paramList.Count > 0)
|
||||
paramList.Add(Token(SyntaxKind.CommaToken));
|
||||
paramList.Add(Parameter(Identifier(arg.Name)));
|
||||
}
|
||||
lambdaArg = ParenthesizedLambdaExpression(
|
||||
MakeMaybeTailCallLambdaBody(method))
|
||||
.AddParameterListParameters(
|
||||
method.Results.Select(arg => Parameter(Identifier(arg.Name))).ToArray());
|
||||
ParameterList(
|
||||
SeparatedList<ParameterSyntax>(paramList)),
|
||||
MakeMaybeTailCallLambdaBody(method));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -662,13 +695,13 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
foreach (var method in def.Methods)
|
||||
{
|
||||
var methodDecl = MethodDeclaration(
|
||||
Type<Task<Capnp.Rpc.AnswerOrCounterquestion>>(),
|
||||
_names.Type<Task<Capnp.Rpc.AnswerOrCounterquestion>>(Nullability.NonNullable),
|
||||
_names.GetCodeIdentifier(method).Identifier)
|
||||
.AddParameterListParameters(
|
||||
Parameter(_names.DeserializerLocal.Identifier)
|
||||
.WithType(Type<Capnp.DeserializerState>()),
|
||||
.WithType(_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)),
|
||||
Parameter(_names.CancellationTokenParameter.Identifier)
|
||||
.WithType(Type<CancellationToken>()))
|
||||
.WithType(_names.Type<CancellationToken>(Nullability.NonNullable)))
|
||||
.AddBodyStatements(
|
||||
MakeSkeletonMethodBody(method).ToArray());
|
||||
|
||||
@ -709,7 +742,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
.AddArgumentListArguments(
|
||||
MakeSkeletonSetMethodTableArguments(type).ToArray()))),
|
||||
// InterfaceId
|
||||
PropertyDeclaration(Type<ulong>(), nameof(Capnp.Rpc.Skeleton<object>.InterfaceId))
|
||||
PropertyDeclaration(_names.Type<ulong>(Nullability.NonNullable), nameof(Capnp.Rpc.Skeleton<object>.InterfaceId))
|
||||
.AddModifiers(Public, Override)
|
||||
.WithExpressionBody(
|
||||
ArrowExpressionClause(
|
||||
@ -790,7 +823,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
var accessPath = _names.MakeMemberAccessPathFieldName(method, path);
|
||||
var methodName = _names.MakePipeliningSupportExtensionMethodName(path);
|
||||
var capType = path[path.Count - 1].Type;
|
||||
var capTypeSyntax = _names.MakeTypeSyntax(capType, null, TypeUsage.DomainClass);
|
||||
var capTypeSyntax = _names.MakeTypeSyntax(capType, null, TypeUsage.DomainClass, Nullability.NonNullable);
|
||||
|
||||
if (!_existingExtensionMethods.Add((capTypeSyntax.ToString(), methodName.ToString())))
|
||||
{
|
||||
@ -815,9 +848,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
.AddModifiers(Static, Readonly);
|
||||
|
||||
|
||||
var methodDecl = MethodDeclaration(
|
||||
capTypeSyntax,
|
||||
methodName.Identifier)
|
||||
var methodDecl = MethodDeclaration(capTypeSyntax, methodName.Identifier)
|
||||
.AddModifiers(Public, Static)
|
||||
.AddParameterListParameters(
|
||||
Parameter(
|
||||
|
@ -57,7 +57,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
ParameterList(
|
||||
SingletonSeparatedList<ParameterSyntax>(
|
||||
Parameter(_names.ReaderContextField.Identifier)
|
||||
.WithType(Type<Capnp.DeserializerState>()))))
|
||||
.WithType(_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)))))
|
||||
.WithExpressionBody(
|
||||
ArrowExpressionClause(
|
||||
ObjectCreationExpression(_names.ReaderStruct.IdentifierName)
|
||||
@ -78,7 +78,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
SingletonSeparatedList(
|
||||
Parameter(_names.ContextParameter.Identifier)
|
||||
.WithType(
|
||||
Type<Capnp.DeserializerState>()))))
|
||||
_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)))))
|
||||
.WithExpressionBody(
|
||||
ArrowExpressionClause(
|
||||
ObjectCreationExpression(_names.ReaderStruct.IdentifierName)
|
||||
@ -90,7 +90,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
yield return FieldDeclaration(
|
||||
VariableDeclaration(
|
||||
Type<Capnp.DeserializerState>())
|
||||
_names.Type<Capnp.DeserializerState>(Nullability.NonNullable))
|
||||
.AddVariables(_names.ReaderContextField.VariableDeclarator))
|
||||
.AddModifiers(Readonly);
|
||||
|
||||
@ -100,7 +100,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
ParameterList(
|
||||
SingletonSeparatedList(
|
||||
Parameter(_names.ContextParameter.Identifier)
|
||||
.WithType(Type<Capnp.DeserializerState>()))))
|
||||
.WithType(_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)))))
|
||||
.WithBody(
|
||||
Block(
|
||||
SingletonList<StatementSyntax>(
|
||||
@ -122,7 +122,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
yield return FieldDeclaration(
|
||||
VariableDeclaration(
|
||||
Type<Capnp.DeserializerState>())
|
||||
_names.Type<Capnp.DeserializerState>(Nullability.NonNullable))
|
||||
.AddVariables(_names.ReaderContextField.VariableDeclarator))
|
||||
.AddModifiers(Readonly);
|
||||
|
||||
@ -131,7 +131,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
.WithParameterList(
|
||||
ParameterList(
|
||||
SingletonSeparatedList(Parameter(_names.GroupReaderContextArg.Identifier)
|
||||
.WithType(Type<Capnp.DeserializerState>()))))
|
||||
.WithType(_names.Type<Capnp.DeserializerState>(Nullability.NonNullable)))))
|
||||
.WithBody(
|
||||
Block(
|
||||
SingletonList<StatementSyntax>(
|
||||
@ -173,57 +173,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
|
||||
}
|
||||
|
||||
static Func<ExpressionSyntax, ExpressionSyntax> MakeCastFunc(TypeSyntax type) =>
|
||||
x => CastExpression(type, x);
|
||||
|
||||
static Func<ExpressionSyntax, ExpressionSyntax> MakeListCastFunc(string castName, Field field)
|
||||
{
|
||||
// Insight: List may have complex default values (e.g. [true, false, false, true] as a
|
||||
// valid default value for a list of bools. This does not yet fit the author's mindset.
|
||||
|
||||
//if (field.DefaultValueIsExplicit)
|
||||
//{
|
||||
// return x => InvocationExpression(
|
||||
// MemberAccessExpression(
|
||||
// SyntaxKind.SimpleMemberAccessExpression,
|
||||
// x,
|
||||
// IdentifierName(castName))
|
||||
// )
|
||||
// .AddArgumentListArguments(
|
||||
// Argument(ValueOf(field.DefaultValue)));
|
||||
//}
|
||||
//else
|
||||
|
||||
{
|
||||
return x => InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
x,
|
||||
IdentifierName(castName))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static Func<ExpressionSyntax, ExpressionSyntax> MakeListCastFuncWithCons(
|
||||
string castName, ExpressionSyntax cons)
|
||||
{
|
||||
return x => InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
x,
|
||||
IdentifierName(castName))
|
||||
).AddArgumentListArguments(Argument(cons));
|
||||
}
|
||||
|
||||
static Func<ExpressionSyntax, ExpressionSyntax> MakeGenericListCastFunc(string castName, TypeSyntax genericArgument)
|
||||
{
|
||||
return x => InvocationExpression(
|
||||
MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
x,
|
||||
GenericName(castName).AddTypeArgumentListArguments(genericArgument))
|
||||
);
|
||||
}
|
||||
static Func<ExpressionSyntax, ExpressionSyntax> MakeCastFunc(TypeSyntax type) => x => CastExpression(type, x);
|
||||
|
||||
PropertyDeclarationSyntax MakeReadProperty(TypeSyntax type, string name, SimpleNameSyntax readName,
|
||||
object indexOrBitOffset, ExpressionSyntax secondArg,
|
||||
@ -261,13 +211,19 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeReadPrimitiveProperty<T>(Field field, string readName)
|
||||
{
|
||||
return MakeReadProperty(Type<T>(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value,
|
||||
ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue);
|
||||
return MakeReadProperty(
|
||||
_names.Type<T>(Nullability.NonNullable),
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
readName,
|
||||
field.BitOffset.Value,
|
||||
ValueOf(field.DefaultValue.ScalarValue),
|
||||
null,
|
||||
field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeReadEnumProperty(Field field)
|
||||
{
|
||||
var typeSyntax = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader);
|
||||
var typeSyntax = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NonNullable);
|
||||
return MakeReadProperty(typeSyntax,
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.SerializerExtensions.ReadDataUShort), field.BitOffset.Value,
|
||||
@ -278,9 +234,16 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeReadTextProperty(Field field)
|
||||
{
|
||||
return MakeReadProperty(Type<string>(), _names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.DeserializerState.ReadText), (int)field.Offset,
|
||||
ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue);
|
||||
bool cantBeNull = !field.DiscValue.HasValue && field.DefaultValue.ScalarValue != null;
|
||||
|
||||
return MakeReadProperty(
|
||||
_names.Type<string>(cantBeNull ? Nullability.NonNullable : Nullability.NullableRef),
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.DeserializerState.ReadText),
|
||||
(int)field.Offset,
|
||||
ValueOf(field.DefaultValue.ScalarValue),
|
||||
null,
|
||||
field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
MemberAccessExpressionSyntax MakeReaderCreator(TypeSyntax qtype)
|
||||
@ -293,7 +256,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeReadStructProperty(Field field)
|
||||
{
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader);
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NonNullable);
|
||||
var creator = MakeReaderCreator(qtype);
|
||||
|
||||
return MakeReadProperty(qtype, _names.GetCodeIdentifier(field).ToString(),
|
||||
@ -316,18 +279,16 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
return MakeReaderProperty(type, _names.GetCodeIdentifier(field).ToString(), right, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
void MakeReadListPropertyImpl(Model.Type elementType, TypeDefinition scope, ExpressionSyntax context, int depth,
|
||||
out TypeSyntax listType, out ExpressionSyntax impl)
|
||||
ExpressionSyntax MakeReadListPropertyImpl(Model.Type elementType, TypeDefinition scope, ExpressionSyntax context, int depth)
|
||||
{
|
||||
var elementTypeSyntax = _names.MakeTypeSyntax(elementType, scope, TypeUsage.Reader);
|
||||
listType = GenericName("IReadOnlyList").AddTypeArgumentListArguments(elementTypeSyntax);
|
||||
var elementTypeSyntax = _names.MakeTypeSyntax(elementType, scope, TypeUsage.Reader, Nullability.NonNullable);
|
||||
|
||||
if (elementType.Tag == TypeTag.Interface ||
|
||||
elementType.Tag == TypeTag.CapabilityPointer)
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
impl = InvocationExpression(MemberAccessExpression(
|
||||
return InvocationExpression(MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
_names.ReaderContextField.IdentifierName,
|
||||
GenericName(nameof(Capnp.DeserializerState.ReadCapList))
|
||||
@ -336,15 +297,13 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
}
|
||||
else
|
||||
{
|
||||
impl = InvocationExpression(
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
GenericName(nameof(Capnp.DeserializerState.RequireCapList))
|
||||
.AddTypeArgumentListArguments(elementTypeSyntax)
|
||||
));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
@ -374,56 +333,44 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
case TypeTag.List:
|
||||
{
|
||||
|
||||
MakeReadListPropertyImpl(
|
||||
var innerImpl = MakeReadListPropertyImpl(
|
||||
elementType.ElementType,
|
||||
scope,
|
||||
lambdaArg,
|
||||
depth + 1,
|
||||
out var innerListType,
|
||||
out var innerImpl);
|
||||
depth + 1);
|
||||
|
||||
listType = GenericName("IReadOnlyList").AddTypeArgumentListArguments(innerListType);
|
||||
|
||||
impl = InvocationExpression(
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.ListDeserializer.Cast))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(SimpleLambdaExpression(lambdaParam, innerImpl)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeTag.ListPointer:
|
||||
{
|
||||
listType = Type<IReadOnlyList<object>>();
|
||||
|
||||
context = InvocationExpression(MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.DeserializerState.RequireList))
|
||||
)).AddArgumentListArguments(Argument(lambdaArg));
|
||||
|
||||
impl = InvocationExpression(
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.ReadOnlyListExtensions.LazyListSelect))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(SimpleLambdaExpression(lambdaParam, context)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeTag.Struct:
|
||||
{
|
||||
impl = InvocationExpression(
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.ListDeserializer.Cast))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(MakeReaderCreator(elementTypeSyntax)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeTag.Enum:
|
||||
@ -432,32 +379,26 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
lambdaParam,
|
||||
CastExpression(elementTypeSyntax, lambdaArg));
|
||||
|
||||
impl = InvocationExpression(
|
||||
return InvocationExpression(
|
||||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.ListDeserializer.CastEnums))))
|
||||
.AddArgumentListArguments(
|
||||
Argument(cons));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeTag.AnyPointer:
|
||||
case TypeTag.StructPointer:
|
||||
{
|
||||
listType = Type<IReadOnlyList<Capnp.DeserializerState>>();
|
||||
impl = context;
|
||||
return;
|
||||
return context;
|
||||
}
|
||||
|
||||
case TypeTag.Void:
|
||||
{
|
||||
listType = Type<int>();
|
||||
impl = MemberAccessExpression(
|
||||
return MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(nameof(Capnp.ListDeserializer.Count)));
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeTag.Data:
|
||||
@ -517,7 +458,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
throw new NotImplementedException("Unexpected type tag, don't know how to deal with this");
|
||||
}
|
||||
|
||||
impl = InvocationExpression(MemberAccessExpression(
|
||||
return InvocationExpression(MemberAccessExpression(
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
context,
|
||||
IdentifierName(castFuncName)));
|
||||
@ -527,13 +468,18 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
var elementType = field.Type.ElementType;
|
||||
var context = ValueOf((int)field.Offset);
|
||||
MakeReadListPropertyImpl(elementType, field.DeclaringType, context, 0, out var listType, out var impl);
|
||||
var impl = MakeReadListPropertyImpl(elementType, field.DeclaringType, context, 0);
|
||||
var listType = _names.MakeTypeSyntax(
|
||||
field.Type,
|
||||
field.DeclaringType,
|
||||
TypeUsage.Reader,
|
||||
field.DiscValue.HasValue ? Nullability.NullableRef : Nullability.NonNullable);
|
||||
return MakeReaderProperty(listType, _names.GetCodeIdentifier(field).ToString(), impl, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeReadAnyListProperty(Field field)
|
||||
{
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader);
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NonNullable);
|
||||
|
||||
return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.DeserializerState.ReadList),
|
||||
@ -542,18 +488,19 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeReadCapProperty(Field field)
|
||||
{
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader);
|
||||
var nullableType = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NullableRef);
|
||||
var nonNullableType = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NonNullable);
|
||||
var readName = GenericName(nameof(Capnp.DeserializerState.ReadCap))
|
||||
.AddTypeArgumentListArguments(type);
|
||||
.AddTypeArgumentListArguments(nonNullableType);
|
||||
|
||||
return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(),
|
||||
return MakeReadProperty(nullableType, _names.GetCodeIdentifier(field).ToString(),
|
||||
readName,
|
||||
(int)field.Offset, null, null, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeReadAnyCapProperty(Field field)
|
||||
{
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader);
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader, Nullability.NonNullable);
|
||||
|
||||
return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.DeserializerState.ReadCap),
|
||||
@ -573,7 +520,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
IdentifierName(nameof(Capnp.ListDeserializer.CastByte))));
|
||||
|
||||
return MakeReaderProperty(
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader),
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader,
|
||||
field.DiscValue.HasValue ? Nullability.NullableRefAndValue : Nullability.NonNullable),
|
||||
_names.GetCodeIdentifier(field).ToString(), impl, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
{
|
||||
static class SyntaxHelpers
|
||||
{
|
||||
public static string MakeCamel(string name) => $"{char.ToUpperInvariant(name[0])}{name.Substring(1)}";
|
||||
public static string MakeAllLower(string name) => $"@{name}";
|
||||
public static string MakeUpperCamel(string name) => $"{char.ToUpperInvariant(name[0])}{name.Substring(1)}";
|
||||
public static string MakeLowerCamel(string name) => $"{char.ToLowerInvariant(name[0])}{name.Substring(1)}";
|
||||
|
||||
public static readonly SyntaxToken Async = Token(SyntaxKind.AsyncKeyword);
|
||||
public static readonly SyntaxToken Public = Token(SyntaxKind.PublicKeyword);
|
||||
@ -21,7 +21,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword);
|
||||
public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword);
|
||||
|
||||
public static TypeSyntax Type(Type type)
|
||||
public static TypeSyntax NonNullableType(Type type)
|
||||
{
|
||||
switch (0)
|
||||
{
|
||||
@ -66,14 +66,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
case 0 when type.IsGenericType:
|
||||
return GenericName(type.Name.Substring(0, type.Name.IndexOf('`')))
|
||||
.AddTypeArgumentListArguments(type.GetGenericArguments().Select(Type).ToArray());
|
||||
.AddTypeArgumentListArguments(type.GetGenericArguments().Select(NonNullableType).ToArray());
|
||||
|
||||
default:
|
||||
return ParseTypeName(type.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeSyntax Type<T>() => Type(typeof(T));
|
||||
public static TypeSyntax NonNullableType<T>() => NonNullableType(typeof(T));
|
||||
|
||||
public static ExpressionSyntax ValueOf(object value)
|
||||
{
|
||||
@ -83,16 +83,16 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
|
||||
|
||||
case sbyte x:
|
||||
return CastExpression(Type<sbyte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
return CastExpression(NonNullableType<sbyte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
|
||||
case byte x:
|
||||
return CastExpression(Type<byte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
return CastExpression(NonNullableType<byte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
|
||||
case short x:
|
||||
return CastExpression(Type<short>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
return CastExpression(NonNullableType<short>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
|
||||
case ushort x:
|
||||
return CastExpression(Type<ushort>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
return CastExpression(NonNullableType<ushort>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
|
||||
|
||||
case int x:
|
||||
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x));
|
||||
@ -122,5 +122,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeSyntax MakeNonNullableType(TypeSyntax type)
|
||||
{
|
||||
if (type is NullableTypeSyntax nts)
|
||||
{
|
||||
type = nts.ElementType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,12 +115,21 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
.AddArgumentListArguments(
|
||||
Argument(ValueOf(index)));
|
||||
|
||||
ExpressionSyntax MakeLinkSyntax(object index) =>
|
||||
InvocationExpression(
|
||||
ExpressionSyntax MakeLinkSyntax(object index, bool suppressNullableWarning)
|
||||
{
|
||||
ExpressionSyntax value = IdentifierName("value");
|
||||
|
||||
if (suppressNullableWarning)
|
||||
{
|
||||
value = _names.SuppressNullableWarning(value);
|
||||
}
|
||||
|
||||
return InvocationExpression(
|
||||
IdentifierName(SerializerStateWorder.LinkName))
|
||||
.AddArgumentListArguments(
|
||||
Argument(ValueOf(index)),
|
||||
Argument(IdentifierName("value")));
|
||||
Argument(value));
|
||||
}
|
||||
|
||||
ExpressionSyntax MakeLinkObjectSyntax(object index) =>
|
||||
InvocationExpression(
|
||||
@ -129,22 +138,46 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
Argument(ValueOf(index)),
|
||||
Argument(IdentifierName("value")));
|
||||
|
||||
PropertyDeclarationSyntax MakeWriterRefTypeProperty(
|
||||
TypeSyntax type,
|
||||
string name,
|
||||
ExpressionSyntax getter,
|
||||
ExpressionSyntax setter,
|
||||
bool cast,
|
||||
bool cond)
|
||||
{
|
||||
if (cond)
|
||||
{
|
||||
type = _names.MakeNullableRefType(type);
|
||||
}
|
||||
|
||||
var prop = MakeWriterProperty(type, name, getter, setter, cast, cond);
|
||||
|
||||
if (cond && _names.NullableEnable)
|
||||
{
|
||||
prop = prop.AddAttributeLists(
|
||||
AttributeList(
|
||||
SingletonSeparatedList(
|
||||
Attribute(
|
||||
IdentifierName("DisallowNull")))));
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakePointerProperty(TypeSyntax type, string name, object index, bool cast, bool cond)
|
||||
{
|
||||
ExpressionSyntax getter = MakePointerSyntax(type, index);
|
||||
ExpressionSyntax setter = MakeLinkSyntax(index);
|
||||
ExpressionSyntax setter = MakeLinkSyntax(index, cond);
|
||||
|
||||
return MakeWriterProperty(type, name, getter, setter, cast, cond);
|
||||
return MakeWriterRefTypeProperty(type, name, getter, setter, cast, cond);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakePointerAsStructProperty(
|
||||
TypeSyntax type, string name, object index,
|
||||
bool cast, bool cond)
|
||||
PropertyDeclarationSyntax MakePointerAsStructProperty(TypeSyntax type, string name, object index, bool cast, bool cond)
|
||||
{
|
||||
ExpressionSyntax getter = MakeTypedPointerSyntax(index, type);
|
||||
ExpressionSyntax setter = MakeLinkSyntax(index);
|
||||
ExpressionSyntax setter = MakeLinkSyntax(index, cond);
|
||||
|
||||
return MakeWriterProperty(type, name, getter, setter, cast, cond);
|
||||
return MakeWriterRefTypeProperty(type, name, getter, setter, cast, cond);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeProperty(
|
||||
@ -195,7 +228,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakePrimitiveProperty<T>(Field field, string readName)
|
||||
{
|
||||
return MakeProperty(Type<T>(), null, _names.GetCodeIdentifier(field).ToString(),
|
||||
return MakeProperty(
|
||||
_names.Type<T>(Nullability.NonNullable),
|
||||
null,
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
readName,
|
||||
nameof(Capnp.SerializerExtensions.WriteData),
|
||||
field.BitOffset.Value,
|
||||
@ -207,7 +243,9 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeEnumProperty(Field field, string readName)
|
||||
{
|
||||
return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), Type<ushort>(),
|
||||
return MakeProperty(
|
||||
_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant, Nullability.NonNullable),
|
||||
_names.Type<ushort>(Nullability.NonNullable),
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
readName,
|
||||
nameof(Capnp.SerializerExtensions.WriteData),
|
||||
@ -220,7 +258,9 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeTextProperty(Field field)
|
||||
{
|
||||
return MakeProperty(Type<string>(), null,
|
||||
return MakeProperty(
|
||||
_names.Type<string>(Nullability.NullableRef),
|
||||
null,
|
||||
_names.GetCodeIdentifier(field).ToString(),
|
||||
nameof(Capnp.SerializerState.ReadText),
|
||||
nameof(Capnp.SerializerState.WriteText),
|
||||
@ -233,7 +273,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeStructProperty(Field field)
|
||||
{
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer);
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer, Nullability.NonNullable);
|
||||
|
||||
return MakePointerAsStructProperty(qtype, _names.GetCodeIdentifier(field).ToString(),
|
||||
(int)field.Offset, false, field.DiscValue.HasValue);
|
||||
@ -241,7 +281,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeGroupProperty(Field field)
|
||||
{
|
||||
var type = QualifiedName(
|
||||
TypeSyntax type = QualifiedName(
|
||||
_names.MakeTypeName(field.Type.Definition).IdentifierName,
|
||||
_names.WriterStruct.IdentifierName);
|
||||
|
||||
@ -249,12 +289,17 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
GenericName(nameof(Capnp.SerializerState.Rewrap))
|
||||
.AddTypeArgumentListArguments(type));
|
||||
|
||||
if (field.DiscValue.HasValue)
|
||||
{
|
||||
type = _names.MakeNullableRefType(type);
|
||||
}
|
||||
|
||||
return MakeWriterProperty(type, _names.GetCodeIdentifier(field).ToString(), getter, null, false, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeListProperty(Field field)
|
||||
{
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer);
|
||||
var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer, Nullability.NonNullable);
|
||||
|
||||
return MakePointerProperty(qtype, _names.GetCodeIdentifier(field).ToString(),
|
||||
(int)field.Offset, false, field.DiscValue.HasValue);
|
||||
@ -269,20 +314,21 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
||||
|
||||
PropertyDeclarationSyntax MakeCapProperty(Field field)
|
||||
{
|
||||
var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer);
|
||||
var nonNullableType = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer, Nullability.NonNullable);
|
||||
var nullableType = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer, Nullability.NullableRef);
|
||||
int index = (int)field.Offset;
|
||||
string name = _names.GetCodeIdentifier(field).ToString();
|
||||
ExpressionSyntax getter = MakeReadCapSyntax(type, index);
|
||||
ExpressionSyntax getter = MakeReadCapSyntax(nonNullableType, index);
|
||||
ExpressionSyntax setter = MakeLinkObjectSyntax(index);
|
||||
|
||||
return MakeWriterProperty(type, name, getter, setter, false, field.DiscValue.HasValue);
|
||||
return MakeWriterProperty(nullableType, name, getter, setter, false, field.DiscValue.HasValue);
|
||||
}
|
||||
|
||||
PropertyDeclarationSyntax MakeWriterUnionSelector(TypeDefinition def)
|
||||
{
|
||||
return MakeProperty(
|
||||
_names.UnionDiscriminatorEnum.IdentifierName,
|
||||
Type<ushort>(),
|
||||
_names.Type<ushort>(Nullability.NonNullable),
|
||||
_names.UnionDiscriminatorProp.ToString(),
|
||||
nameof(Capnp.SerializerExtensions.ReadDataUShort),
|
||||
nameof(Capnp.SerializerExtensions.WriteData),
|
||||
|
@ -8,6 +8,7 @@
|
||||
get => _literal;
|
||||
set => _literal = IdentifierRenamer.ToNonKeyword(value);
|
||||
}
|
||||
public string CsLiteral { get; set; }
|
||||
public ushort? Ordinal { get; set; }
|
||||
public int CodeOrder { get; set; }
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
public TypeDefinition DeclaringType { get; set; }
|
||||
public Field Parent { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string CsName { get; set; }
|
||||
public Type Type { get; set; }
|
||||
public Value DefaultValue { get; set; }
|
||||
public bool DefaultValueIsExplicit { get; set; }
|
||||
|
@ -11,6 +11,8 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
|
||||
public string Name { get; set; }
|
||||
public string[] Namespace { get; set; }
|
||||
public bool? NullableEnable { get; set; }
|
||||
public bool EmitNullableDirective { get; set; }
|
||||
|
||||
public IEnumerable<TypeDefinition> NestedTypes { get => this.GetNestedTypes(); }
|
||||
public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>();
|
||||
|
@ -8,6 +8,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
public TypeDefinition DeclaringInterface { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string CsName { get; set; }
|
||||
public List<Field> Params { get; } = new List<Field>();
|
||||
public List<Field> Results { get; } = new List<Field>();
|
||||
public Type ParamsStruct { get; set; }
|
||||
@ -21,6 +22,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
DeclaringInterface = DeclaringInterface,
|
||||
Id = Id,
|
||||
Name = Name,
|
||||
CsName = CsName,
|
||||
ParamsStruct = ParamsStruct,
|
||||
ResultStruct = ResultStruct
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static CapnpC.CSharp.Generator.Model.SupportedAnnotations;
|
||||
|
||||
namespace CapnpC.CSharp.Generator.Model
|
||||
{
|
||||
@ -92,6 +92,8 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
state.parent = null;
|
||||
file.Namespace = GetNamespaceAnnotation(node);
|
||||
file.Name = name;
|
||||
file.NullableEnable = GetNullableEnable(node);
|
||||
file.EmitNullableDirective = GetEmitNullableDirective(node) ?? false;
|
||||
return ProcessNodePass1(id, name, state) as GenFile;
|
||||
}
|
||||
|
||||
@ -145,6 +147,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
Trace.Assert(state.parent != null, $"The {node.GetTypeTag().ToString()} node {node.StrId()} was expected to have a parent.");
|
||||
var typeDef = _typeDefMgr.CreateTypeDef(id, node.GetTypeTag(), state.parent);
|
||||
typeDef.Name = name;
|
||||
typeDef.CsName = GetCsName(node);
|
||||
state.parent = typeDef;
|
||||
def = typeDef;
|
||||
}
|
||||
@ -175,18 +178,6 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
return def;
|
||||
}
|
||||
|
||||
string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode)
|
||||
{
|
||||
foreach (var annotation in fileNode.Annotations)
|
||||
{
|
||||
if (annotation.Id == 0xb9c6f99ebf805f2c) // Cxx namespace
|
||||
{
|
||||
return annotation.Value.Text.Split(new string[1] { "::" }, default);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2nd pass: Generate types based on definitions
|
||||
|
||||
struct Pass2State
|
||||
@ -492,6 +483,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
{
|
||||
DeclaringType = declaringType,
|
||||
Name = fieldReader.Name,
|
||||
CsName = GetCsName(fieldReader),
|
||||
CodeOrder = fieldReader.CodeOrder
|
||||
};
|
||||
|
||||
@ -505,6 +497,8 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
case 0 when fieldReader.IsGroup:
|
||||
var def = ProcessTypeDef(fieldReader.Group_TypeId, state, TypeTag.Group);
|
||||
field.Type = Types.FromDefinition(def);
|
||||
def.CsName = field.CsName; // Type definitions for unions are artificially generated.
|
||||
// Transfer the C# name of the using field.
|
||||
break;
|
||||
|
||||
case 0 when fieldReader.IsSlot:
|
||||
@ -549,7 +543,8 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
{
|
||||
DeclaringInterface = def,
|
||||
Id = def.Methods.Count,
|
||||
Name = methodReader.Name
|
||||
Name = methodReader.Name,
|
||||
CsName = GetCsName(methodReader)
|
||||
};
|
||||
foreach (var implicitParameterReader in methodReader.ImplicitParameters)
|
||||
{
|
||||
@ -664,6 +659,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
{
|
||||
TypeDefinition = def,
|
||||
Literal = fieldReader.Name,
|
||||
CsLiteral = GetCsName(fieldReader),
|
||||
CodeOrder = fieldReader.CodeOrder
|
||||
};
|
||||
|
||||
@ -745,9 +741,6 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
|
||||
public static class SchemaExtensions
|
||||
{
|
||||
public static string GetName(this Schema.Node.Reader node)
|
||||
=> node.DisplayName.Substring((int)node.DisplayNamePrefixLength);
|
||||
|
||||
public static string StrId(this Schema.Node.Reader node)
|
||||
=> $"0x{node.Id:X}";
|
||||
|
||||
|
102
CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs
Normal file
102
CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs
Normal file
@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CapnpC.CSharp.Generator.Model
|
||||
{
|
||||
static class SupportedAnnotations
|
||||
{
|
||||
static class AnnotationIds
|
||||
{
|
||||
public static class Cxx
|
||||
{
|
||||
public const ulong Namespace = 0xb9c6f99ebf805f2c;
|
||||
}
|
||||
|
||||
public static class Cs
|
||||
{
|
||||
public const ulong Namespace = 0xeb0d831668c6eda0;
|
||||
public const ulong NullableEnable = 0xeb0d831668c6eda1;
|
||||
public const ulong Name = 0xeb0d831668c6eda2;
|
||||
public const ulong EmitNullableDirective = 0xeb0d831668c6eda3;
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode)
|
||||
{
|
||||
foreach (var annotation in fileNode.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.Namespace)
|
||||
{
|
||||
return annotation.Value.Text.Split(new string[1] { "." }, default);
|
||||
}
|
||||
|
||||
if (annotation.Id == AnnotationIds.Cxx.Namespace)
|
||||
{
|
||||
return annotation.Value.Text.Split(new string[1] { "::" }, default);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetCsName(Schema.Field.Reader node)
|
||||
{
|
||||
foreach (var annotation in node.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.Name)
|
||||
{
|
||||
return annotation.Value.Text;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetCsName(Schema.Node.Reader node)
|
||||
{
|
||||
foreach (var annotation in node.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.Name)
|
||||
{
|
||||
return annotation.Value.Text;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetCsName(Schema.Method.Reader node)
|
||||
{
|
||||
foreach (var annotation in node.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.Name)
|
||||
{
|
||||
return annotation.Value.Text;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool? GetNullableEnable(Schema.Node.Reader node)
|
||||
{
|
||||
foreach (var annotation in node.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.NullableEnable && annotation.Value.IsBool)
|
||||
{
|
||||
return annotation.Value.Bool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool? GetEmitNullableDirective(Schema.Node.Reader node)
|
||||
{
|
||||
foreach (var annotation in node.Annotations)
|
||||
{
|
||||
if (annotation.Id == AnnotationIds.Cs.EmitNullableDirective && annotation.Value.IsBool)
|
||||
{
|
||||
return annotation.Value.Bool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,7 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
|
||||
public Method UsingMethod { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string CsName { get; set; }
|
||||
public SpecialName SpecialName { get; set; }
|
||||
public DiscriminationInfo UnionInfo { get; set; }
|
||||
public List<Field> Fields { get; } = new List<Field>();
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<Version>1.2-local</Version>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Nullable>Enable</Nullable>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<PackageReferenceVersion Condition="'$(PackageReferenceVersion)'==''">$(Version)*</PackageReferenceVersion>
|
||||
</PropertyGroup>
|
||||
|
@ -9,13 +9,24 @@ namespace MsBuildGenerationTest
|
||||
// Instantiate some generated classes ensures that they are really present.
|
||||
// Note that this code is not supposed to test runtime behavior, we have plenty of other test cases for that purpose.
|
||||
|
||||
void use(object y)
|
||||
{
|
||||
}
|
||||
|
||||
var vatId = new Capnp.Rpc.Twoparty.VatId();
|
||||
use(vatId);
|
||||
var msg = new Capnp.Rpc.Message();
|
||||
use(msg);
|
||||
var node = new Capnp.Schema.Node();
|
||||
use(node);
|
||||
var x = Capnproto_test.Capnp.Test.TestEnum.garply;
|
||||
use(x);
|
||||
var imp = new CapnpGen.TestImport();
|
||||
use(imp);
|
||||
var imp2 = new CapnpGen.TestImport2();
|
||||
use(imp2);
|
||||
var book = new CapnpGen.AddressBook();
|
||||
use(book);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@
|
||||
# it for free.
|
||||
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("capnp::rpc");
|
||||
$Cxx.namespace("test::rpc");
|
||||
|
||||
# ========================================================================================
|
||||
# The Four Tables
|
||||
|
@ -55,14 +55,14 @@ test_script:
|
||||
- cmd: |
|
||||
nbgv get-version -v NuGetPackageVersion >> version.txt
|
||||
set /P VERSION=< version.txt
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp2.1\CapnpC.CSharp.Generator.Tests.dll
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.Generator.Tests.dll
|
||||
choco install capnproto --source="https://chocolatey.org/api/v2" --force -y
|
||||
cd %APPVEYOR_BUILD_FOLDER%\capnpc-csharp
|
||||
dotnet tool install --global --add-source ./nupkg capnpc-csharp --version %VERSION%
|
||||
cd %APPVEYOR_BUILD_FOLDER%\install-test
|
||||
compile-test
|
||||
cd %APPVEYOR_BUILD_FOLDER%
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp2.1\CapnpC.CSharp.Generator.Tests.dll
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.Generator.Tests.dll
|
||||
dotnet tool uninstall --global capnpc-csharp
|
||||
cd %APPVEYOR_BUILD_FOLDER%\install-test
|
||||
notinstalled-test
|
||||
@ -73,7 +73,7 @@ test_script:
|
||||
choco uninstall capnpc-csharp-win-x86 -y
|
||||
notinstalled-test
|
||||
cd %APPVEYOR_BUILD_FOLDER%
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.MsBuild.Generation.Tests\bin\Release\netcoreapp2.1\CapnpC.CSharp.MsBuild.Generation.Tests.dll
|
||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.MsBuild.Generation.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.MsBuild.Generation.Tests.dll
|
||||
msbuild -t:restore ./MsBuildGenerationTest/MsBuildGenerationTest.csproj /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
||||
msbuild ./MsBuildGenerationTest/MsBuildGenerationTest.sln /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
||||
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Debug\net471\Capnp.Net.Runtime.Tests.Std20.dll
|
||||
|
14
include/csharp.capnp
Normal file
14
include/csharp.capnp
Normal file
@ -0,0 +1,14 @@
|
||||
@0xeb0d831668c6edab;
|
||||
$namespace("Capnp.Annotations");
|
||||
|
||||
annotation namespace @0xeb0d831668c6eda0 (file) : Text;
|
||||
# C# namespace for code generation
|
||||
|
||||
annotation nullableEnable @0xeb0d831668c6eda1 (file) : Bool;
|
||||
# Whether to generate C# nullable reference types
|
||||
|
||||
annotation emitNullableDirective @0xeb0d831668c6eda3 (file) : Bool;
|
||||
# Whether to surround the generated with with #nullable enable/disable ... #nullable restore
|
||||
|
||||
annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text;
|
||||
# C# member name for code generation
|
Loading…
x
Reference in New Issue
Block a user