[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 {
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
@ -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">
|
||||
<Link>ikvm\VersionInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="error.cs" />
|
||||
<Compile Include="ErrorHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="support\" />
|
||||
|
@ -331,6 +333,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="..\docs\error.md">
|
||||
<Link>error.md</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -140,7 +140,7 @@ namespace ObjC {
|
|||
var setter = pi.GetSetMethod ();
|
||||
// FIXME: setter only is valid, even if discouraged, in .NET - we should create a SetX method
|
||||
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")]
|
||||
var name = CamelCase (pi.Name);
|
||||
|
@ -204,7 +204,7 @@ namespace ObjC {
|
|||
implementation.WriteLine ($"\treturn *(({name}*)__unbox);");
|
||||
break;
|
||||
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:
|
||||
return "int";
|
||||
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.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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче