Merge pull request #42 from c80k/nullable

Nullable support
This commit is contained in:
c80k 2020-02-09 12:11:48 +01:00 committed by GitHub
commit 7d4aefe37e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
135 changed files with 2462 additions and 1465 deletions

View File

@ -28,4 +28,4 @@
Reserializing.DeepCopy(State, state);
}
}
}
}

View File

@ -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>

View File

@ -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);
}
}
}
}

View File

@ -22,4 +22,4 @@ namespace Capnp
{
}
}
}
}

View File

@ -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,10 +84,15 @@ 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)
{
@ -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)!;
}
}
}
}

View File

@ -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)
{
@ -225,4 +225,4 @@ namespace Capnp
}
}
}
}
}

View File

@ -35,4 +35,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -85,4 +85,4 @@ namespace Capnp
/// </summary>
public override IReadOnlyList<ushort> CastUShort() => new EmptyList<ushort>();
}
}
}

View File

@ -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.
@ -195,4 +193,4 @@ namespace Capnp
_tracers.Add(tracer);
}
}
}
}

View File

@ -244,4 +244,4 @@ namespace Capnp.FrameTracing
}
}
}
}
}

View File

@ -122,4 +122,4 @@ namespace Capnp
}
}
}
}
}

View File

@ -18,4 +18,4 @@
/// <param name="state">Source deserializer state</param>
void Deserialize(DeserializerState state);
}
}
}

View File

@ -26,4 +26,4 @@ namespace Capnp
/// <returns>Whether allocation was successful</returns>
bool Allocate(uint nwords, uint preferredSegment, out SegmentSlice slice, bool forcePreferredSegment);
}
}
}

View File

@ -19,4 +19,4 @@ namespace Capnp
/// <exception cref="DeserializationException">this state does not represent a struct</exception>
ulong StructReadData(ulong bitOffset, int bitCount);
}
}
}

View File

@ -24,4 +24,4 @@ namespace Capnp
/// </summary>
Span<ulong> StructDataSection { get; }
}
}
}

View File

@ -10,7 +10,7 @@ namespace Capnp
{
static class GenericCasts<T>
{
public static Func<ListDeserializer, T> CastFunc;
public static Func<ListDeserializer, T>? CastFunc;
}
static ListDeserializer()
@ -400,4 +400,4 @@ namespace Capnp
return Cast(sd => sd.ReadDataDouble(0));
}
}
}
}

View File

@ -45,4 +45,4 @@
/// </summary>
ListOfStructs = 7
}
}
}

View File

@ -76,4 +76,4 @@ namespace Capnp
throw new NotSupportedException("Cannot cast a list of bits to anything else");
}
}
}
}

View File

@ -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)
{
@ -95,4 +95,4 @@ namespace Capnp
IEnumerator IEnumerable.GetEnumerator() => this.ToArray().GetEnumerator();
}
}
}

View File

@ -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)!;
}
}
@ -69,4 +68,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -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)
{
@ -108,4 +106,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -63,4 +63,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -30,4 +30,4 @@ namespace Capnp
SetListOfValues(0, count);
}
}
}
}

View File

@ -88,4 +88,4 @@ namespace Capnp
return this.LazyListSelect(d => d.RequireCapList<T>());
}
}
}
}

View File

@ -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)
{
@ -114,5 +112,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -231,4 +231,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -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)
{
@ -93,4 +92,4 @@ namespace Capnp
IEnumerator IEnumerable.GetEnumerator() => Data.ToArray().GetEnumerator();
}
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Capnp
{
@ -78,4 +77,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -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)
{
@ -92,4 +92,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -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)
{
@ -108,5 +108,4 @@ namespace Capnp
return GetEnumerator();
}
}
}
}

View File

@ -1,5 +1,4 @@
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
namespace Capnp
{
@ -20,4 +19,4 @@ namespace Capnp
/// <returns>The logger instance</returns>
public static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();
}
}
}

View File

@ -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;
}
}
}

View 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

View File

@ -70,4 +70,4 @@ namespace Capnp
/// </summary>
Value = 16
}
}
}

View File

@ -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()
@ -44,4 +42,4 @@ namespace Capnp
throw new NotSupportedException("Generic type argument is not a supported primitive type, no coder defined");
}
}
}
}

View File

@ -2,7 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Capnp
{
@ -70,4 +69,4 @@ namespace Capnp
return source.Select(selector).ToList().AsReadOnly();
}
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Capnp
{
@ -102,4 +101,4 @@ namespace Capnp
to.InheritFrom(ds);
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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)
{
}
@ -49,4 +49,4 @@
return base.Call(interfaceId, methodId, args, default);
}
}
}
}

View File

@ -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)
@ -285,4 +284,4 @@ namespace Capnp.Rpc
return proxy;
}
}
}
}

View File

@ -21,4 +21,4 @@
/// </summary>
Down
}
}
}

View File

@ -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();
@ -30,4 +26,4 @@ namespace Capnp.Rpc
public int CreatorLineNumber { get; set; }
#endif
}
}
}

View File

@ -67,4 +67,4 @@ namespace Capnp.Rpc
/// </summary>
void Close();
}
}
}

View File

@ -15,4 +15,4 @@
/// </summary>
void Dismiss();
}
}
}

View File

@ -10,4 +10,4 @@
/// </summary>
ulong InterfaceId { get; }
}
}
}

View File

@ -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);
}
}
}

View File

@ -21,4 +21,4 @@ namespace Capnp.Rpc
Task<AnswerOrCounterquestion> Invoke(ulong interfaceId, ushort methodId,
DeserializerState args, CancellationToken cancellationToken = default);
}
}
}

View File

@ -12,4 +12,4 @@ namespace Capnp.Rpc
/// </summary>
Task<Proxy> WhenResolved { get; }
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
@ -18,4 +16,4 @@ namespace Capnp.Rpc
Task RequestSenderLoopback(Action<MessageTarget.WRITER> writer);
void DeleteQuestion(PendingQuestion question);
}
}
}

View File

@ -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; }
@ -251,4 +251,4 @@ namespace Capnp.Rpc
return MaybeTailCall(task, (ValueTuple<T1, T2, T3, T4, T5, T6, T7> t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7));
}
}
}
}

View File

@ -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.
@ -51,4 +49,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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;

View File

@ -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;
}
@ -41,4 +41,4 @@
{
}
}
}
}

View File

@ -20,4 +20,4 @@ namespace Capnp.Rpc.Interception
/// <param name="callContext"></param>
void OnReturnFromBob(CallContext callContext);
}
}
}

View File

@ -25,4 +25,4 @@
/// </summary>
ReturnedToAlice
}
}
}

View File

@ -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:
@ -112,4 +112,4 @@ namespace Capnp.Rpc.Interception
}
}
}
}
}

View File

@ -21,4 +21,4 @@
{
}
}
}
}

View File

@ -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
@ -105,4 +105,4 @@ namespace Capnp.Rpc
return new LocalAnswer(cts, CallImpl(interfaceId, methodId, args, cts.Token));
}
}
}
}

View File

@ -49,4 +49,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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)))
@ -86,4 +86,4 @@ namespace Capnp.Rpc
this.DisposeWhenResolved();
}
}
}
}

View File

@ -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;
}
@ -68,4 +67,4 @@ namespace Capnp.Rpc
{
}
}
}
}

View File

@ -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,11 +184,11 @@ 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");
}
}
}
}
}

View File

@ -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)
{
@ -198,4 +197,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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)
@ -376,4 +375,4 @@ namespace Capnp.Rpc
}
#endregion
}
}
}

View File

@ -70,4 +70,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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!;
}
}
}
@ -257,4 +256,4 @@ namespace Capnp.Rpc
return call;
}
}
}
}

View File

@ -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));
@ -238,4 +237,4 @@ namespace Capnp.Rpc
public int CreatorLineNumber { get; set; }
#endif
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Capnp.Rpc
{
@ -27,4 +25,4 @@ namespace Capnp.Rpc
/// </summary>
public Type ProxyClass { get; }
}
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
@ -111,4 +110,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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
{
@ -254,4 +256,4 @@ namespace Capnp.Rpc
this.DisposeWhenResolved();
}
}
}
}

View File

@ -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;
@ -37,4 +38,4 @@ namespace Capnp.Rpc
return call;
}
}
}
}

View File

@ -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);
@ -123,4 +126,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -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)
{
@ -41,4 +41,4 @@
}
}
}
}
}

View File

@ -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
@ -1508,4 +1504,4 @@ namespace Capnp.Rpc
}
}
}
}
}

View File

@ -19,4 +19,4 @@
{
}
}
}
}

View File

@ -3,4 +3,4 @@
class RpcUnimplementedException : System.Exception
{
}
}
}

View File

@ -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.
@ -298,4 +295,4 @@ namespace Capnp.Rpc
Impl = (T)impl;
}
}
}
}

View File

@ -31,4 +31,4 @@ namespace Capnp.Rpc
/// </summary>
public Type SkeletonClass { get; }
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@ -69,4 +67,4 @@ namespace Capnp.Rpc
base.Dispose(disposing);
}
}
}
}

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591
#nullable disable
using Capnp;
using Capnp.Rpc;
@ -2640,4 +2641,6 @@ namespace Capnp.Rpc
unimplemented
}
}
}
}
#nullable restore

View File

@ -15,4 +15,4 @@
/// </summary>
public static int RecursionLimit { get; set; } = 64;
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Capnp
{
@ -144,4 +143,4 @@ namespace Capnp
return true;
}
}
}
}

View File

@ -1,6 +1,4 @@
using System;
namespace Capnp
namespace Capnp
{
/// <summary>
/// Helper struct to represent the tuple (segment index, offset)
@ -17,4 +15,4 @@ namespace Capnp
/// </summary>
public int Offset;
}
}
}

View File

@ -338,4 +338,4 @@ namespace Capnp
WriteData(d, bitOffset, bits, defaultBits);
}
}
}
}

View File

@ -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,14 +660,21 @@ 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)
{
byte[] srcBytes = Encoding.UTF8.GetBytes(text);
SetListOfValues(8, srcBytes.Length + 1);
var srcSpan = new ReadOnlySpan<byte>(srcBytes);
var dstSpan = ListGetBytes();
dstSpan = dstSpan.Slice(0, dstSpan.Length - 1);
srcSpan.CopyTo(dstSpan);
if (text == null)
{
VerifyNotYetAllocated();
}
else
{
byte[] srcBytes = Encoding.UTF8.GetBytes(text);
SetListOfValues(8, srcBytes.Length + 1);
var srcSpan = new ReadOnlySpan<byte>(srcBytes);
var dstSpan = ListGetBytes();
dstSpan = dstSpan.Slice(0, dstSpan.Length - 1);
srcSpan.CopyTo(dstSpan);
}
}
/// <summary>
@ -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;
@ -1391,4 +1404,4 @@ namespace Capnp
return new Rpc.BareProxy(cap);
}
}
}
}

View File

@ -24,4 +24,4 @@ namespace Capnp
/// </summary>
public ulong Id { get; }
}
}
}

View File

@ -4,8 +4,8 @@ using System.Threading.Tasks;
namespace Capnp
{
internal static class UtilityExtensions
{
internal static class UtilityExtensions
{
/// <summary>
/// This method exists until NET Standard 2.1 is released
/// </summary>
@ -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>

View File

@ -21,4 +21,4 @@ namespace Capnp
Segments = segments;
}
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Capnp
{
@ -227,4 +225,4 @@ namespace Capnp
_ptrData = ((ulong)index << 32) | (ulong)PointerKind.Other;
}
}
}
}

View File

@ -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>

View File

@ -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 |

View File

@ -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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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);
this.ScenarioStart();
#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
}
}

View File

@ -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)

Some files were not shown because too many files have changed in this diff Show More