Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/api-doc-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiao Luo <basehello@icloud.com>2021-01-21 00:55:48 +0300
committerGitHub <noreply@github.com>2021-01-21 00:55:48 +0300
commitc6411bbcbcf3b4aad999e455d4b2767370abffb9 (patch)
treebed24260db72abb680f6b523548e7ef3abacd9ff /mdoc/mdoc.Test/NullableReferenceTypesTests.cs
parent8b52f5293ccfad0a4f754c10d27d308e89d901e7 (diff)
Add support for C# 8.0 nullable reference types feature (#532)
https://dev.azure.com/ceapex/Engineering/_workitems/edit/317995?src=WorkItemMention&src-action=artifact_link
Diffstat (limited to 'mdoc/mdoc.Test/NullableReferenceTypesTests.cs')
-rw-r--r--mdoc/mdoc.Test/NullableReferenceTypesTests.cs303
1 files changed, 303 insertions, 0 deletions
diff --git a/mdoc/mdoc.Test/NullableReferenceTypesTests.cs b/mdoc/mdoc.Test/NullableReferenceTypesTests.cs
new file mode 100644
index 00000000..48897efc
--- /dev/null
+++ b/mdoc/mdoc.Test/NullableReferenceTypesTests.cs
@@ -0,0 +1,303 @@
+using Mono.Documentation;
+using Mono.Documentation.Updater.Formatters;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace mdoc.Test
+{
+ public class NullableReferenceTypesTests : BasicFormatterTests<CSharpMemberFormatter>
+ {
+ private const string NullableReferenceTypesAssemblyPath = "../../../../external/Test/mdoc.Test.NullableReferenceTypes.dll";
+
+ private CSharpMemberFormatter csharpMemberFormatter = new CSharpMemberFormatter();
+
+ protected override CSharpMemberFormatter formatter => csharpMemberFormatter;
+
+ [TestCase("dynamic", "DynamicType")]
+ [TestCase("dynamic?", "NullableDynamicType")]
+ [TestCase("DayOfWeek", "Enumeration")]
+ [TestCase("DayOfWeek?", "NullableEnumeration")]
+ [TestCase("int", "ValueType")]
+ [TestCase("int?", "NullableValueType")]
+ [TestCase("int[]", "ArrayOfValueType")]
+ [TestCase("int?[]", "ArrayOfValueTypeNullable")]
+ [TestCase("int[]?", "NullableArrayOfValueType")]
+ [TestCase("int?[]?", "NullableArrayOfNullableValueType")]
+ [TestCase("int[][]", "DimensionalArrayOfValueType")]
+ [TestCase("int?[][]", "DimensionalArrayOfNullableValueType")]
+ [TestCase("int?[]?[]", "DimensionalArrayOfNullableValueTypeOfNullableRow")]
+ [TestCase("int?[]?[]?", "NullableDimensionalArrayOfNullableValueTypeOfNullableRow")]
+ [TestCase("int?[][]?", "NullableDimensionalArrayOfNullableValueType")]
+ [TestCase("int[][]?", "NullableDimensionalArrayOfValueType")]
+ [TestCase("int[][]?[][]?", "NullableFourDimensionalArrayOfValueTypeOfMiddleNullableArray")]
+ [TestCase("int?[][]?[][]", "FourDimensionalArrayOfNullableValueTypeOfMiddleNullableArray")]
+ [TestCase("Tuple<int,int>", "TupleOfValueType")]
+ [TestCase("Tuple<int,int>?", "NullableTupleOfValueType")]
+ [TestCase("Tuple<int?,int?>", "TupleOfNullableValueType")]
+ [TestCase("Tuple<int?,int?>?", "NullableTupleOfNullableValueType")]
+ [TestCase("(int,int)", "ValueTupleOfValueType")]
+ [TestCase("(int,int)?", "NullableValueTupleOfValueType")]
+ [TestCase("(int?,int?)", "ValueTupleOfNullableValueType")]
+ [TestCase("(int?,int?)?", "NullableValueTupleOfNullableValueType")]
+ [TestCase("ICollection<int>", "InterfaceOfValueType")]
+ [TestCase("ICollection<int>?", "NullableInterfaceOfValueType")]
+ [TestCase("ICollection<int?>?", "NullableInterfaceOfNullableValueType")]
+ [TestCase("Action<int>", "ActionOfValueType")]
+ [TestCase("Action<int?>", "ActionOfNullableValueType")]
+ [TestCase("Action<int>?", "NullableActionOfValueType")]
+ [TestCase("Action<int?>?", "NullableActionOfNullableValueType")]
+ [TestCase("Dictionary<int,int>", "DictionaryOfValueType")]
+ [TestCase("Dictionary<int,int>?", "NullableDictionaryOfValueType")]
+ [TestCase("Dictionary<int?,int?>", "DictionaryOfNullableValueType")]
+ [TestCase("Dictionary<int?,int?>?", "NullableDictionaryOfNullableValueType")]
+ [TestCase("Dictionary<int,int?>", "DictionaryOfNullableValueTypeValue")]
+ [TestCase("Dictionary<int,int?>?", "NullableDictionaryOfNullableValueTypeValue")]
+ [TestCase("Dictionary<int?,int>?", "NullableDictionaryOfNullableValueTypeKey")]
+ [TestCase("Dictionary<int,Dictionary<int,int>>", "DictionaryOfValueTypeKeyAndDictionaryOfValueTypeValue")]
+ [TestCase("Dictionary<int,Dictionary<int,int>>?", "NullableDictionaryOfValueTypeKeyAndDictionaryOfValueTypeValue")]
+ [TestCase("Dictionary<int?,Dictionary<int,int>?>?", "NullableDictionaryOfNullableValueTypeKeyAndNullableDictionaryOfValueTypeValue")]
+ [TestCase("Dictionary<int?,Dictionary<int?,int?>?>?", "NullableDictionaryOfNullableValueTypeKeyAndNullableDictionaryOfNullableValueTypeValue")]
+ [TestCase("Dictionary<int,Tuple<int,int>>", "DictionaryOfValueTypeKeyAndTupleOfValueTypeValue")]
+ [TestCase("Dictionary<int,Tuple<int,int>>?", "NullableDictionaryOfValueTypeKeyAndTupleOfValueTypeValue")]
+ [TestCase("Dictionary<int?,Tuple<int,int>?>?", "NullableDictionaryOfNullableValueTypeKeyAndNullableTupleOfValueTypeValue")]
+ [TestCase("Dictionary<int?,Tuple<int?,int?>?>?", "NullableDictionaryOfNullableValueTypeKeyAndNullableTupleOfNullableValueTypeValue")]
+ [TestCase("Dictionary<Dictionary<int,int>,Dictionary<int,int>>", "DictionaryOfDictionaryOfValueType")]
+ [TestCase("Dictionary<Dictionary<int,int>?,Dictionary<int,int>?>?", "NullableDictionaryOfNullableDictionaryOfValueType")]
+ [TestCase("Dictionary<Dictionary<int?,int?>?,Dictionary<int?,int?>?>?", "NullableDictionaryOfNullableDictionaryOfNullableValueType")]
+ [TestCase("string", "ReferenceType")]
+ [TestCase("string?", "NullableReferenceType")]
+ [TestCase("string[]", "ArrayOfReferenceType")]
+ [TestCase("string?[]", "ArrayOfNullableReferenceType")]
+ [TestCase("string[]?", "NullableArrayOfReferenceType")]
+ [TestCase("string?[]?", "NullableArrayOfNullableReferenceType")]
+ [TestCase("string[][]", "DimensionalArrayOfReferenceType")]
+ [TestCase("string?[][]", "DimensionalArrayOfNullableReferenceType")]
+ [TestCase("string?[]?[]", "DimensionalArrayOfNullableReferenceTypeOfNullableRow")]
+ [TestCase("string?[]?[]?", "NullableDimensionalArrayOfNullableReferenceTypeOfNullableRow")]
+ [TestCase("string?[][]?", "NullableDimensionalArrayOfNullableReferenceType")]
+ [TestCase("string[][]?", "NullableDimensionalArrayOfReferenceType")]
+ [TestCase("string[][]?[][]?", "NullableFourDimensionalArrayOfReferenceTypeOfMiddleNullableArray")]
+ [TestCase("string?[][]?[][]", "FourDimensionalArrayOfNullableReferenceTypeOfMiddleNullableArray")]
+ [TestCase("Tuple<string,string>", "TupleOfReferenceType")]
+ [TestCase("Tuple<string,string>?", "NullableTupleOfReferenceType")]
+ [TestCase("Tuple<string?,string?>", "TupleOfNullableReferenceType")]
+ [TestCase("Tuple<string?,string?>?", "NullableTupleOfNullableReferenceType")]
+ [TestCase("(string,string)", "ValueTupleOfReferenceType")]
+ [TestCase("(string,string)?", "NullableValueTupleOfReferenceType")]
+ [TestCase("(string?,string?)", "ValueTupleOfNullableReferenceType")]
+ [TestCase("(string?,string?)?", "NullableValueTupleOfNullableReferenceType")]
+ [TestCase("ICollection<string>", "InterfaceOfReferenceType")]
+ [TestCase("ICollection<string>?", "NullableInterfaceOfReferenceType")]
+ [TestCase("ICollection<string?>?", "NullableInterfaceOfNullableReferenceType")]
+ [TestCase("ICollection<dynamic>", "InterfaceOfDynamicType")]
+ [TestCase("ICollection<dynamic>?", "NullableInterfaceOfDynamicType")]
+ [TestCase("ICollection<dynamic?>?", "NullableInterfaceOfNullableDynamicType")]
+ [TestCase("Action<string>", "ActionOfReferenceType")]
+ [TestCase("Action<string?>", "ActionOfNullableReferenceType")]
+ [TestCase("Action<string>?", "NullableActionOfReferenceType")]
+ [TestCase("Action<string?>?", "NullableActionOfNullableReferenceType")]
+ [TestCase("Dictionary<string,string>", "DictionaryOfReferenceType")]
+ [TestCase("Dictionary<string,string>?", "NullableDictionaryOfReferenceType")]
+ [TestCase("Dictionary<string?,string?>", "DictionaryOfNullableReferenceType")]
+ [TestCase("Dictionary<string?,string?>?", "NullableDictionaryOfNullableReferenceType")]
+ [TestCase("Dictionary<string,string?>", "DictionaryOfNullableReferenceTypeValue")]
+ [TestCase("Dictionary<string,string?>?", "NullableDictionaryOfNullableReferenceTypeValue")]
+ [TestCase("Dictionary<string?,string>?", "NullableDictionaryOfNullableReferenceTypeKey")]
+ [TestCase("Dictionary<Dictionary<string,string>,Dictionary<string,string>>", "DictionaryOfDictionaryOfReferenceType")]
+ [TestCase("Dictionary<Dictionary<string,string>?,Dictionary<string,string>?>?", "NullableDictionaryOfNullableDictionaryOfReferenceType")]
+ [TestCase("Dictionary<Dictionary<string?,string?>?,Dictionary<string?,string?>?>?", "NullableDictionaryOfNullableDictionaryOfNullableReferenceType")]
+ [TestCase("Dictionary<string,Dictionary<string,string>>", "DictionaryOfReferenceTypeKeyAndDictionaryOfReferenceTypeValue")]
+ [TestCase("Dictionary<string,Dictionary<string,string>>?", "NullableDictionaryOfReferenceTypeKeyAndDictionaryOfReferenceTypeValue")]
+ [TestCase("Dictionary<string?,Dictionary<string,string>?>?", "NullableDictionaryOfNullableReferenceTypeKeyAndNullableDictionaryOfReferenceTypeValue")]
+ [TestCase("Dictionary<string?,Dictionary<string?,string?>?>?", "NullableDictionaryOfNullableReferenceTypeKeyAndNullableDictionaryOfNullableReferenceTypeValue")]
+ [TestCase("Dictionary<string,Tuple<string,string>>", "DictionaryOfReferenceTypeKeyAndTupleOfReferenceTypeValue")]
+ [TestCase("Dictionary<string,Tuple<string,string>>?", "NullableDictionaryOfReferenceTypeKeyAndTupleOfReferenceTypeValue")]
+ [TestCase("Dictionary<string?,Tuple<string,string>?>?", "NullableDictionaryOfNullableReferenceTypeKeyAndNullableTupleOfReferenceTypeValue")]
+ [TestCase("Dictionary<string?,Tuple<string?,string?>?>?", "NullableDictionaryOfNullableReferenceTypeKeyAndNullableTupleOfNullableReferenceTypeValue")]
+ public void TypeName(string returnType, string methodName)
+ {
+ // Test single parameter and return type for method, extension method, property, field, event, delegate.
+ // They have the same process logic that we just test once the type of them.
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.CommonType",
+ methodName, $"public {returnType} {methodName} ();");
+ }
+
+ [TestCase("ParamsArrayOfNullableValueType", "int i, params int?[] array")]
+ [TestCase("ParamsArrayOfNullableReferenceType", "string s, params object?[] array")]
+ [TestCase("NullableAndNonNullableValueType", "int i1, int? i2, int i3")]
+ [TestCase("NullableAndNonNullableReferenceType", "string s1, string? s2, string s3")]
+ [TestCase("NullableGenericValueTypeOfValueType", "ReadOnlySpan<int> s1, ReadOnlySpan<int?> s2, ReadOnlySpan<int> s3")]
+ [TestCase("NullableGenericValueTypeOfReferenceType", "ReadOnlySpan<string> s1, ReadOnlySpan<string?> s2, ReadOnlySpan<string> s3")]
+ [TestCase("NullableAndNonNullableInterfaceOfValueType", "ICollection<int> collection1, ICollection<int>? collection2, ICollection<int> collection3")]
+ [TestCase("NullableAndNonNullableInterfaceOfReferenceType", "ICollection<string> collection1, ICollection<string>? collection2, ICollection<string> collection3")]
+ public void MethodParameter(string methodName, string methodParameter)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.MethodParameter",
+ methodName, $"public void {methodName} ({methodParameter});");
+ }
+
+ [TestCase("GenericType", "<T> ({0})", "T t")]
+ [TestCase("GenericReferenceType", "<T> ({0}) where T : class", "T t")]
+ [TestCase("GenericNullableReferenceType", "<T> ({0}) where T : class", "T? t")]
+ [TestCase("ActionOfGenericNullableReferenceType", "<T> ({0}) where T : class", "Action<T?> t")]
+ [TestCase("NullableActionOfGenericNullableReferenceType", "<T> ({0}) where T : class", "Action<T?>? t")]
+ [TestCase("FuncGenericNullableReferenceType", "<T> ({0}) where T : class", "Func<T?> t")]
+ [TestCase("NullableFuncGenericNullableReferenceType", "<T> ({0}) where T : class", "Func<T?>? t")]
+ [TestCase("GenericNonNullableAndNullableReferenceType", "<T1,T2> ({0}) where T2 : class", "T1 t1, T2? t2")]
+ [TestCase("GenericValueType", "<T> ({0}) where T : struct", "T t")]
+ [TestCase("GenericNullableValueType", "<T> ({0}) where T : struct", "T? t")]
+ [TestCase("ActionOfGenericNullableValueType", "<T> ({0}) where T : struct", "Action<T?> action")]
+ [TestCase("NullableActionOfGenericNullableValueType", "<T> ({0}) where T : struct", "Action<T?>? action")]
+ [TestCase("FuncGenericNullableValueType", "<T> ({0}) where T : struct", "Func<T?> func")]
+ [TestCase("NullableFuncGenericNullableValueType", "<T> ({0}) where T : struct", "Func<T?>? func")]
+ [TestCase("GenericNonNullableAndNullableValueType", "<T1,T2> ({0}) where T2 : struct", "T1 t1, T2? t2")]
+ public void GenericMethodParameter(string methodName, string otherPartOfMethodSignature, string genericParameter)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.GenericMethodParameter",
+ methodName, $"public void {methodName}{string.Format(otherPartOfMethodSignature, genericParameter)};");
+ }
+
+ [TestCase("T", "GenericType", "<T> ()")]
+ [TestCase("T", "GenericReferenceType", "<T> () where T : class")]
+ [TestCase("T?", "GenericNullableReferenceType", "<T> () where T : class")]
+ [TestCase("T", "GenericValueType", "<T> () where T : struct")]
+ [TestCase("T?", "GenericNullableValueType", "<T> () where T : struct")]
+ public void GenericMethodReturnType(string returnType, string methodName, string otherPartOfMethodSignature)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.GenericMethodReturnType",
+ methodName, $"public {returnType} {methodName}{otherPartOfMethodSignature};");
+ }
+
+ [TestCase("T", "GenericType")]
+ [TestCase("TClass", "GenericReferenceType")]
+ [TestCase("TClass?", "GenericNullableReferenceType")]
+ [TestCase("TStruct", "GenericValueType")]
+ [TestCase("TStruct?", "GenericNullableValueType")]
+ public void GenericPropertyReturnType(string returnType, string propertyName)
+ {
+ TestPropertySignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.{GetGenericTypeILName("GenericPropertyReturnType<T, TClass, TStruct>")}",
+ propertyName, $"public {returnType} {propertyName} {{ get; }}");
+ }
+
+ [TestCase("EventHandler", "EventHandler")]
+ [TestCase("EventHandler?", "NullableEventHandler")]
+ [TestCase("EventHandler<EventArgs>", "GenericEventHandler")]
+ [TestCase("EventHandler<EventArgs?>", "GenericEventHandlerOfNullableEventArgs")]
+ [TestCase("EventHandler<EventArgs>?", "NullableGenericEventHandler")]
+ [TestCase("EventHandler<EventArgs?>?", "NullableGenericEventHandlerOfNullableEventArgs")]
+ public void EventDelegateType(string delegateType, string eventName)
+ {
+ TestEventSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.Event",
+ eventName, $"public event {delegateType} {eventName};");
+ }
+
+ [TestCase("Handler", "object sender, EventArgs args")]
+ [TestCase("NullableSender", "object? sender, EventArgs args")]
+ [TestCase("NullableSenderAndEventArgs", "object? sender, EventArgs? args")]
+ public void DelegateTypeParameter(string delegateName, string delegateParameter)
+ {
+ TestTypeSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.Delegate.{delegateName}",
+ $"public delegate void {delegateName}({delegateParameter});");
+ }
+
+ [TestCase("GenericHandler<TEventArgs>", "object sender, TEventArgs args", "{0}")]
+ [TestCase("NullableSender<TEventArgs>", "object? sender, TEventArgs args", "{0}")]
+ [TestCase("NullableSenderAndEventArgs<TEventArgs>", "object? sender, TEventArgs? args", "{0} where TEventArgs : class")]
+ [TestCase("ActionHandler<TClass,TStruct>", "TClass t1, TStruct t2", "{0} where TClass : class where TStruct : struct")]
+ [TestCase("NullableActionHandler<TClass,TStruct>", "TClass? t1, TStruct? t2", "{0} where TClass : class where TStruct : struct")]
+ public void GenericDelegateTypeParameter(string delegateName, string delegateParameter, string otherPartOfMethodSignature)
+ {
+ TestTypeSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.Delegate.{GetGenericTypeILName(delegateName)}",
+ $"public delegate void {delegateName}{string.Format(otherPartOfMethodSignature, $"({delegateParameter})")};");
+ }
+
+ [TestCase("TReturn", "FuncHandler<TReturn>", "()")]
+ [TestCase("TReturn?", "NullableReferenceType<TReturn>", "() where TReturn : class")]
+ [TestCase("TReturn?", "NullableValueType<TReturn>", "() where TReturn : struct")]
+ public void GenericDelegateTypeReturnType(string returnType, string delegateName, string otherPartOfMethodSignature)
+ {
+ TestTypeSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.Delegate.{GetGenericTypeILName(delegateName)}",
+ $"public delegate {returnType} {delegateName}{otherPartOfMethodSignature};");
+ }
+
+ [TestCase("NonNullableAndNullableValueType", "int i1, int? i2, int i3")]
+ [TestCase("NonNullableAndNullableReferenceType", "string s1, string? s2, string s3")]
+ [TestCase("InterfaceOfValueType", "ICollection<int> collection1, ICollection<int>? collection2, ICollection<int> collection3")]
+ [TestCase("InterfaceOfReferenceType", "ICollection<string> collection1, ICollection<string>? collection2, ICollection<string> collection3")]
+ public void ConstructorParameter(string typeName, string constructorParameter)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.Constructor.{typeName}",
+ ".ctor", $"public {typeName} ({constructorParameter});");
+ }
+
+ [TestCase("GenericFieldType<T>", "T", "GenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "T", "GenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "T?", "NullableGenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "ICollection<T>", "InterfaceOfGenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "ICollection<T?>", "InterfaceOfNullableGenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "ICollection<T>?", "NullableInterfaceOfGenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "ICollection<T?>?", "NullableInterfaceOfNullableGenericType")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "Dictionary<Dictionary<T,string>,string>", "DictionaryOfDictionary")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "Dictionary<Dictionary<T?,string>,string>", "DictionaryOfDictionaryOfNullableGenericTypeKey")]
+ [TestCase("GenericFieldTypeOfValueType<T>", "Dictionary<Dictionary<T?,string>,string>?", "NullableDictionaryOfDictionaryOfNullableGenericTypeKey")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "T", "GenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "T?", "NullableGenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "ICollection<T>", "InterfaceOfGenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "ICollection<T?>", "InterfaceOfNullableGenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "ICollection<T>?", "NullableInterfaceOfGenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "ICollection<T?>?", "NullableInterfaceOfNullableGenericType")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "Dictionary<Dictionary<T,string>,string>", "DictionaryOfDictionary")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "Dictionary<Dictionary<T?,string>,string>", "DictionaryOfDictionaryOfNullableGenericTypeKey")]
+ [TestCase("GenericFieldTypeOfReferenceType<T>", "Dictionary<Dictionary<T?,string>,string>?", "NullableDictionaryOfDictionaryOfNullableGenericTypeKey")]
+ public void GenericFieldReturnType(string typeName, string returnType, string fieldName)
+ {
+ TestFieldSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.{GetGenericTypeILName(typeName)}",
+ fieldName, $"public {returnType} {fieldName};");
+ }
+
+ [TestCase("NullableAndNonNullableValueType", "this int? type, int? i1, int i2, int? i3")]
+ [TestCase("NullableAndNonNullableNullableReferenceType", "this string? type, string? s1, string s2, string? s3")]
+ [TestCase("NullableAndNonNullableNullableReferenceTypeAndValueType", "this string? type, string? s1, int? i1, int i2, string s2, string? s3")]
+ public void ExtensionMethodParameter(string methodName, string methodParameter)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, "mdoc.Test.NullableReferenceTypes.ExtensionMethod",
+ methodName, $"public static void {methodName} ({methodParameter});");
+ }
+
+ [TestCase("Student", "op_Addition", "Student operator +", "Student s1, Student s2")]
+ [TestCase("Student", "op_Subtraction", "Student? operator -", "Student? s1, Student? s2")]
+ [TestCase("Student", "op_Multiply", "Student operator *", "Student s1, Student? s2")]
+ [TestCase("Student", "op_Division", "Student operator /", "Student? s1, Student s2")]
+ [TestCase("Student", "op_Implicit", "implicit operator ExamScore", "Student? s")]
+ [TestCase("Student", "op_Explicit", "explicit operator Student?", "ExamScore? s")]
+ [TestCase("ExamScore", "op_Addition", "ExamScore operator +", "ExamScore s1, ExamScore s2")]
+ [TestCase("ExamScore", "op_Subtraction", "ExamScore? operator -", "ExamScore? s1, ExamScore? s2")]
+ [TestCase("ExamScore", "op_Multiply", "ExamScore operator *", "ExamScore s1, ExamScore? s2")]
+ [TestCase("ExamScore", "op_Division", "ExamScore operator /", "ExamScore? s1, ExamScore s2")]
+ [TestCase("ExamScore", "op_Implicit", "implicit operator ExamScore", "Student? s")]
+ [TestCase("ExamScore", "op_Explicit", "explicit operator Student?", "ExamScore? s")]
+ public void OperatorOverloading(string typeName, string methodName, string operatorName, string methodParameter)
+ {
+ TestMethodSignature(NullableReferenceTypesAssemblyPath, $"mdoc.Test.NullableReferenceTypes.OperatorOverloading.{typeName}",
+ methodName, $"public static {operatorName} ({methodParameter});");
+ }
+
+ private string GetGenericTypeILName(string genericTypeName)
+ {
+ var startParameterIndex = genericTypeName.IndexOf('<');
+ var endParameterIndex = genericTypeName.IndexOf('>');
+
+ if (startParameterIndex != -1 && endParameterIndex != -1 && endParameterIndex == genericTypeName.Length - 1)
+ {
+ var parameterList = genericTypeName.Substring(startParameterIndex + 1, endParameterIndex - startParameterIndex - 1);
+ var parameterCount = parameterList.Split(',').Count();
+ var genericTypeNameWithoutParameter = genericTypeName.Substring(0, startParameterIndex);
+
+ return $"{genericTypeNameWithoutParameter}`{parameterCount}";
+ }
+
+ throw new ArgumentException("The generic type name is not a valid value.", nameof(genericTypeName));
+ }
+ }
+}