From 5c99f08511f8628c14e176026c641bf1da3eaed2 Mon Sep 17 00:00:00 2001 From: Bruno da Silva Belo Date: Thu, 2 Jan 2020 22:27:25 +0000 Subject: [PATCH] c#: Checking null for parameters generated code. Checking null for generated code ref T8399 Reviewed-by: Felipe Magno de Almeida Differential Revision: https://phab.enlightenment.org/D10970 --- src/bin/eolian_mono/eolian/mono/events.hh | 17 +++++++++---- .../eolian/mono/function_definition.hh | 1 + src/bin/eolian_mono/eolian/mono/parameter.hh | 25 +++++++++++-------- src/bin/eolian_mono/eolian_mono.cc | 3 ++- src/tests/efl_mono/EinaTestData.cs | 3 +++ 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh index a77f6d7d9c..8bb1799485 100644 --- a/src/bin/eolian_mono/eolian/mono/events.hh +++ b/src/bin/eolian_mono/eolian/mono/events.hh @@ -165,7 +165,8 @@ struct pack_event_info_and_call_visitor if (regular.is_struct()) { return as_generator( - indent << "IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(e.arg));\n" + indent << "Contract.Requires(e != null, nameof(e));\n" + << indent << "IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(e.arg));\n" << indent << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n" ).generate(sink, attributes::unused, *context); } @@ -192,7 +193,8 @@ struct pack_event_info_and_call_visitor auto str_accept_func = [&](std::string const& conversion) { return as_generator( - indent << "IntPtr info = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(" << conversion << ");\n" + indent << "Contract.Requires(e != null, nameof(e));\n" + << indent << "IntPtr info = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(" << conversion << ");\n" << indent << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Eina.MemoryNative.Free(p));\n" ).generate(sink, attributes::unused, *context); }; @@ -210,7 +212,8 @@ struct pack_event_info_and_call_visitor auto value_accept_func = [&](std::string const& conversion) { return as_generator( - indent << "IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << conversion << ");\n" + indent << "Contract.Requires(e != null, nameof(e));\n" + << indent << "IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << conversion << ");\n" << indent << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n" ).generate(sink, attributes::unused, *context); }; @@ -223,7 +226,9 @@ struct pack_event_info_and_call_visitor bool operator()(grammar::attributes::klass_name const&) const { auto const& indent = current_indentation(*context); - return as_generator(indent << "IntPtr info = e.arg.NativeHandle;\n" + return as_generator( + indent << "Contract.Requires(e != null, nameof(e));\n" + << indent << "IntPtr info = e.arg.NativeHandle;\n" << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", IntPtr.Zero, null);\n" ).generate(sink, attributes::unused, *context); } @@ -233,7 +238,9 @@ struct pack_event_info_and_call_visitor if ((type.outer.base_type == "iterator") || (type.outer.base_type == "accessor")) return true; - return as_generator(indent << "IntPtr info = e.arg.Handle;\n" + return as_generator( + indent << "Contract.Requires(e != null, nameof(e));\n" + << indent << "IntPtr info = e.arg.Handle;\n" << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", IntPtr.Zero, null);\n" ).generate(sink, attributes::unused, *context); } diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh index 86eb2db192..fa4941213f 100644 --- a/src/bin/eolian_mono/eolian/mono/function_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh @@ -305,6 +305,7 @@ struct property_extension_method_definition_generator if (!as_generator(scope_tab << "public static Efl.BindableProperty<" << type(true) << "> " << managed_name << "(this Efl.BindablePart part, Efl.Csharp.ExtensionTag<" << name_helpers::klass_full_concrete_or_interface_name(cls) << ", T>magic = null) where T : " << name_helpers::klass_full_concrete_or_interface_name(cls) << " {\n" + << scope_tab << scope_tab << "Contract.Requires(part != null, nameof(part));\n" << scope_tab << scope_tab << "return new Efl.BindableProperty<" << type(true) << ">(part.PartName, \"" << property.name << "\", part.Binder);\n" << scope_tab << "}\n\n" ).generate(sink, std::make_tuple(prop_type, prop_type), context)) diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh index 4af5fe2aef..5e6246d174 100644 --- a/src/bin/eolian_mono/eolian/mono/parameter.hh +++ b/src/bin/eolian_mono/eolian/mono/parameter.hh @@ -693,10 +693,10 @@ struct convert_in_variable_generator } else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") { - auto var_name = in_variable_name(param.param_name); if (!as_generator( - "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" - ).generate(sink, var_name, context)) + "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" + << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context)) return false; if (param.type.has_own) { @@ -710,10 +710,10 @@ struct convert_in_variable_generator attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex || complex->subtypes.size() != 2) return false; - auto var_name = in_variable_name(param.param_name); if (!as_generator( - "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" - ).generate(sink, var_name, context)) + "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" + << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context)) return false; if (param.type.has_own && !as_generator( escape_keyword(param.param_name) << ".SetOwn(false);\n" @@ -736,10 +736,12 @@ struct convert_in_variable_generator attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; - auto var_name = in_variable_name(param.param_name); if (!as_generator( - "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" - ).generate(sink, var_name, context)) + "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" + << "var " << string << " = " << string << ".Handle;\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), + in_variable_name(param.param_name), escape_keyword(param.param_name)) + , context)) return false; if (param.type.has_own && !as_generator( escape_keyword(param.param_name) << ".Own = false;\n" @@ -777,8 +779,9 @@ struct convert_in_variable_generator else if (param.type.c_type == "Eina_Value") { return as_generator( - "var " << string << " = " << string << ".GetNative();\n" - ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.param_name), context); + "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" + "var " << string << " = " << string << ".GetNative();\n" + ).generate(sink, std::make_tuple(param.param_name, param.param_name, in_variable_name(param.param_name), param.param_name), context); } return true; } diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc index b6d2b6f1a0..bf3874a414 100644 --- a/src/bin/eolian_mono/eolian_mono.cc +++ b/src/bin/eolian_mono/eolian_mono.cc @@ -172,7 +172,8 @@ run(options_type const& opts) "using System.Linq;\n" "using System.Threading;\n" "using System.ComponentModel;\n" - "using System.Diagnostics.CodeAnalysis;\n") + "using System.Diagnostics.CodeAnalysis;\n" + "using System.Diagnostics.Contracts;\n") .generate(iterator, efl::eolian::grammar::attributes::unused, efl::eolian::grammar::context_null())) { throw std::runtime_error("Failed to generate file preamble"); diff --git a/src/tests/efl_mono/EinaTestData.cs b/src/tests/efl_mono/EinaTestData.cs index 5b8c84db81..9727548f93 100644 --- a/src/tests/efl_mono/EinaTestData.cs +++ b/src/tests/efl_mono/EinaTestData.cs @@ -17,6 +17,7 @@ using System; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.Diagnostics.Contracts; namespace EinaTestData { @@ -95,6 +96,8 @@ public static class BaseData [ CallerLineNumber ] int line = 0, [ CallerFilePath ] string file = null, [ CallerMemberName ] string member = null) { + Contract.Requires(a != null, nameof(a)); + Contract.Requires(b != null, nameof(b)); Test.Assert(a.Length == b.Length, "Different lenght", line, file, member); for (int i = 0; i < a.Length; ++i) {