[objc] Add error handling. (#33)
This commit is contained in:
Родитель
2b8c858e9c
Коммит
7d22482959
|
@ -0,0 +1,40 @@
|
||||||
|
id:{932C3F0C-D968-42D1-BB14-D97C73361983}
|
||||||
|
title:Embeddinator-4000 errors
|
||||||
|
|
||||||
|
[//]: # (The original file resides under https://github.com/mono/Embeddinator-4000/tree/master/docs/error.md)
|
||||||
|
[//]: # (This allows all contributors (including external) to submit, using a PR, updates to the documentation that match the tools changes)
|
||||||
|
[//]: # (Modifications outside of mono/Embeddinator-4000 will be lost on future updates)
|
||||||
|
|
||||||
|
# EM0xxx: binding error messages
|
||||||
|
|
||||||
|
E.g. parameters, environment
|
||||||
|
|
||||||
|
<!-- 0xxx: the generator itself, e.g. parameters, environment -->
|
||||||
|
<h3><a name="EM0000"/>EM0000: Unexpected error - Please fill a bug report at https://github.com/mono/Embeddinator-4000/issues</h3>
|
||||||
|
|
||||||
|
An unexpected error condition occurred. Please [file an issue](https://github.com/mono/Embeddinator-4000/issues) with as much information as possible, including:
|
||||||
|
|
||||||
|
* Full build logs, with maximum verbosity
|
||||||
|
* A minimal test case that reproduce the error
|
||||||
|
* All version informations
|
||||||
|
|
||||||
|
The easiest way to get exact version information is to use the **Xamarin Studio** menu, **About Xamarin Studio** item, **Show Details** button and copy/paste the version informations (you can use the **Copy Information** button).
|
||||||
|
|
||||||
|
<h3><a name="EM0099"/>EM0099: Internal error *. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).</h3>
|
||||||
|
|
||||||
|
This error message is reported when an internal consistency check in the Embeddinator-4000 fails.
|
||||||
|
|
||||||
|
This indicates a bug in the Embeddinator-4000; please file a bug report at [https://github.com/mono/Embeddinator-4000/issues](https://github.com/mono/Embeddinator-4000/issues) with a test case.
|
||||||
|
|
||||||
|
# EM1xxx: code generation
|
||||||
|
|
||||||
|
<!-- 1xxx: code generation -->
|
||||||
|
|
||||||
|
<!-- 2xxx: reserved -->
|
||||||
|
<!-- 3xxx: reserved -->
|
||||||
|
<!-- 4xxx: reserved -->
|
||||||
|
<!-- 5xxx: reserved -->
|
||||||
|
<!-- 6xxx: reserved -->
|
||||||
|
<!-- 7xxx: reserved -->
|
||||||
|
<!-- 8xxx: reserved -->
|
||||||
|
<!-- 9xxx: reserved -->
|
|
@ -0,0 +1,176 @@
|
||||||
|
// Copyright 2014, Xamarin Inc. All rights reserved,
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using ProductException = Embeddinator.EmbeddinatorException;
|
||||||
|
|
||||||
|
namespace Embeddinator
|
||||||
|
{
|
||||||
|
static class ErrorHelper
|
||||||
|
{
|
||||||
|
public enum WarningLevel
|
||||||
|
{
|
||||||
|
Error = -1,
|
||||||
|
Warning = 0,
|
||||||
|
Disable = 1,
|
||||||
|
}
|
||||||
|
const string Prefix = ProductException.PREFIX;
|
||||||
|
static Dictionary<int, WarningLevel> warning_levels;
|
||||||
|
public static int Verbosity { get; set; }
|
||||||
|
|
||||||
|
public static WarningLevel GetWarningLevel (int code)
|
||||||
|
{
|
||||||
|
WarningLevel level;
|
||||||
|
|
||||||
|
if (warning_levels == null)
|
||||||
|
return WarningLevel.Warning;
|
||||||
|
|
||||||
|
// code -1: all codes
|
||||||
|
if (warning_levels.TryGetValue (-1, out level))
|
||||||
|
return level;
|
||||||
|
|
||||||
|
if (warning_levels.TryGetValue (code, out level))
|
||||||
|
return level;
|
||||||
|
|
||||||
|
return WarningLevel.Warning; ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetWarningLevel (WarningLevel level, int? code = null /* if null, apply to all warnings */)
|
||||||
|
{
|
||||||
|
if (warning_levels == null)
|
||||||
|
warning_levels = new Dictionary<int, WarningLevel> ();
|
||||||
|
if (code.HasValue) {
|
||||||
|
warning_levels [code.Value] = level;
|
||||||
|
} else {
|
||||||
|
warning_levels [-1] = level; // code -1: all codes.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProductException CreateError (int code, string message, params object [] args)
|
||||||
|
{
|
||||||
|
return new ProductException (code, true, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProductException CreateError (int code, Exception innerException, string message, params object [] args)
|
||||||
|
{
|
||||||
|
return new ProductException (code, true, innerException, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProductException CreateWarning (int code, string message, params object [] args)
|
||||||
|
{
|
||||||
|
return new ProductException (code, false, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error (int code, Exception innerException, string message, params object [] args)
|
||||||
|
{
|
||||||
|
throw new ProductException (code, true, innerException, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error (int code, string message, params object [] args)
|
||||||
|
{
|
||||||
|
throw new ProductException (code, true, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warning (int code, string message, params object [] args)
|
||||||
|
{
|
||||||
|
Show (new ProductException (code, false, message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warning (int code, Exception innerException, string message, params object [] args)
|
||||||
|
{
|
||||||
|
Show (new ProductException (code, false, innerException, message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Show (IEnumerable<Exception> list)
|
||||||
|
{
|
||||||
|
List<Exception> exceptions = new List<Exception> ();
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
foreach (var e in list)
|
||||||
|
CollectExceptions (e, exceptions);
|
||||||
|
|
||||||
|
foreach (var ex in exceptions)
|
||||||
|
error |= ShowInternal (ex);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
Exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void Show (Exception e)
|
||||||
|
{
|
||||||
|
List<Exception> exceptions = new List<Exception> ();
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
CollectExceptions (e, exceptions);
|
||||||
|
|
||||||
|
foreach (var ex in exceptions)
|
||||||
|
error |= ShowInternal (ex);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
Exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Exit (int exitCode)
|
||||||
|
{
|
||||||
|
Environment.Exit (exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CollectExceptions (Exception ex, List<Exception> exceptions)
|
||||||
|
{
|
||||||
|
AggregateException ae = ex as AggregateException;
|
||||||
|
|
||||||
|
if (ae != null) {
|
||||||
|
foreach (var ie in ae.InnerExceptions)
|
||||||
|
CollectExceptions (ie, exceptions);
|
||||||
|
} else {
|
||||||
|
exceptions.Add (ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ShowInternal (Exception e)
|
||||||
|
{
|
||||||
|
ProductException mte = (e as ProductException);
|
||||||
|
bool error = true;
|
||||||
|
|
||||||
|
if (mte != null) {
|
||||||
|
error = mte.Error;
|
||||||
|
|
||||||
|
if (!error && GetWarningLevel (mte.Code) == WarningLevel.Disable)
|
||||||
|
return false; // This is an ignored warning.
|
||||||
|
|
||||||
|
Console.Error.WriteLine (mte.ToString ());
|
||||||
|
|
||||||
|
if (Verbosity > 1)
|
||||||
|
ShowInner (e);
|
||||||
|
|
||||||
|
if (Verbosity > 2 && !string.IsNullOrEmpty (e.StackTrace))
|
||||||
|
Console.Error.WriteLine (e.StackTrace);
|
||||||
|
} else {
|
||||||
|
Console.Error.WriteLine (e.ToString ());
|
||||||
|
if (Verbosity > 1)
|
||||||
|
ShowInner (e);
|
||||||
|
if (Verbosity > 2 && !string.IsNullOrEmpty (e.StackTrace))
|
||||||
|
Console.Error.WriteLine (e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowInner (Exception e)
|
||||||
|
{
|
||||||
|
Exception ie = e.InnerException;
|
||||||
|
if (ie == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Verbosity > 3) {
|
||||||
|
Console.Error.WriteLine ("--- inner exception");
|
||||||
|
Console.Error.WriteLine (ie);
|
||||||
|
Console.Error.WriteLine ("---");
|
||||||
|
} else {
|
||||||
|
Console.Error.WriteLine ("\t{0}", ie.Message);
|
||||||
|
}
|
||||||
|
ShowInner (ie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,8 +13,18 @@ namespace Embeddinator {
|
||||||
static class Driver {
|
static class Driver {
|
||||||
|
|
||||||
// TODO: use Mono.Options
|
// TODO: use Mono.Options
|
||||||
// TODO: add errors.cs
|
|
||||||
public static int Main (string [] args)
|
static int Main (string [] args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Main2 (args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ErrorHelper.Show (e);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Main2 (string [] args)
|
||||||
{
|
{
|
||||||
bool shared = true; // dylib
|
bool shared = true; // dylib
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2011-2012, Xamarin Inc. All rights reserved,
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// Error allocation: the errors are listed (and documented) in $(TOP)/docs/errors.md
|
||||||
|
|
||||||
|
namespace Embeddinator
|
||||||
|
{
|
||||||
|
public class EmbeddinatorException : Exception
|
||||||
|
{
|
||||||
|
internal const string PREFIX = "EM";
|
||||||
|
|
||||||
|
public EmbeddinatorException (int code, string message, params object [] args) :
|
||||||
|
this (code, true, message, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddinatorException (int code, bool error, string message, params object [] args) :
|
||||||
|
this (code, error, null, message, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddinatorException (int code, bool error, Exception innerException, string message, params object [] args) :
|
||||||
|
base (String.Format (message, args), innerException)
|
||||||
|
{
|
||||||
|
Code = code;
|
||||||
|
Error = error || ErrorHelper.GetWarningLevel (code) == ErrorHelper.WarningLevel.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
public int LineNumber { get; set; }
|
||||||
|
|
||||||
|
public int Code { get; private set; }
|
||||||
|
|
||||||
|
public bool Error { get; private set; }
|
||||||
|
|
||||||
|
// http://blogs.msdn.com/b/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty (FileName)) {
|
||||||
|
return String.Format ("{0} {3}{1:0000}: {2}", Error ? "error" : "warning", Code, Message, PREFIX);
|
||||||
|
} else {
|
||||||
|
return String.Format ("{3}({4}): {0} {5}{1:0000}: {2}", Error ? "error" : "warning", Code, Message, FileName, LineNumber, PREFIX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -303,6 +303,8 @@
|
||||||
<Compile Include="..\external\ikvm\reflect\Writer\VersionInfo.cs">
|
<Compile Include="..\external\ikvm\reflect\Writer\VersionInfo.cs">
|
||||||
<Link>ikvm\VersionInfo.cs</Link>
|
<Link>ikvm\VersionInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="error.cs" />
|
||||||
|
<Compile Include="ErrorHelper.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="support\" />
|
<Folder Include="support\" />
|
||||||
|
@ -331,6 +333,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
<None Include="..\docs\error.md">
|
||||||
|
<Link>error.md</Link>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -140,7 +140,7 @@ namespace ObjC {
|
||||||
var setter = pi.GetSetMethod ();
|
var setter = pi.GetSetMethod ();
|
||||||
// FIXME: setter only is valid, even if discouraged, in .NET - we should create a SetX method
|
// FIXME: setter only is valid, even if discouraged, in .NET - we should create a SetX method
|
||||||
if (getter == null && setter != null)
|
if (getter == null && setter != null)
|
||||||
throw new NotSupportedException ();
|
throw ErrorHelper.CreateError (99, "Internal error. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).");
|
||||||
|
|
||||||
// TODO override with attribute ? e.g. [ObjC.Selector ("foo")]
|
// TODO override with attribute ? e.g. [ObjC.Selector ("foo")]
|
||||||
var name = CamelCase (pi.Name);
|
var name = CamelCase (pi.Name);
|
||||||
|
@ -204,7 +204,7 @@ namespace ObjC {
|
||||||
implementation.WriteLine ($"\treturn *(({name}*)__unbox);");
|
implementation.WriteLine ($"\treturn *(({name}*)__unbox);");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException ();
|
throw ErrorHelper.CreateError (99, "Internal error. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ namespace ObjC {
|
||||||
case TypeCode.Int32:
|
case TypeCode.Int32:
|
||||||
return "int";
|
return "int";
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException ();
|
throw ErrorHelper.CreateError (99, "Internal error. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,14 @@ namespace ObjCGeneratorTest {
|
||||||
Assert.That (ObjCGenerator.GetTypeName (asm.GetType ("System.Int32")), Is.EqualTo ("int"), "int");
|
Assert.That (ObjCGenerator.GetTypeName (asm.GetType ("System.Int32")), Is.EqualTo ("int"), "int");
|
||||||
Assert.That (ObjCGenerator.GetTypeName (asm.GetType ("System.Object")), Is.EqualTo ("NSObject"), "object");
|
Assert.That (ObjCGenerator.GetTypeName (asm.GetType ("System.Object")), Is.EqualTo ("NSObject"), "object");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TypeMatchFailure ()
|
||||||
|
{
|
||||||
|
var universe = new Universe (UniverseOptions.None);
|
||||||
|
var asm = universe.Load ("mscorlib.dll");
|
||||||
|
|
||||||
|
Assert.Throws<Embeddinator.EmbeddinatorException> (() => ObjCGenerator.GetTypeName (asm.GetType ("System.Char")), "char");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче