Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.82k stars 821 forks source link

Include the name of the class when throwing an error #959

Closed kevinfoley closed 7 years ago

kevinfoley commented 7 years ago

E.g. "[DisplayObject] Invalid horizontal alignment: lfet"

This is useful when debugging in an environment or situation where we don't have access to the line number or call stack, such as when the error is caught by a handler or logged to a file:

try {
    var texture:Texture = assetManager.getTexture("texture");
    var image:Image = new Image(texture);
    image.alignPivot("lfet", "top");
    addChild(image);
} catch (error:Error) {
    Alert.show(error.message, "Error!"); //we'll see the call stack, but not what 
}

This isn't the best example, but the point is that sometimes you end up with an error message and it's not immediately obvious which class it came from.

So far I've implemented this for Juggler, Tween, Starling, Button, DisplayObject, AssetManager. If you like the change, I can continue applying it in the remaining classes.

A possible enhancement I just thought of, in case we're concerned about potentially displaying class names to users in a production environment:

private static function get outputName():String { 
    return (Starling.current.includeClassNamesInErrors) ? "[DisplayObject] " : "";
}
PrimaryFeather commented 7 years ago

Thanks a lot for the pull request, Kevin!

To be honest, though, I don't think this is really necessary! You can actually get this information without adding the class name to the error string.

Add the following UncaughtErrorEvent-handler to your startup-class:

loaderInfo.uncaughtErrorEvents.addEventListener(
    UncaughtErrorEvent.UNCAUGHT_ERROR, function(event:UncaughtErrorEvent):void 
    {
        var stackTrace:String = event.error.getStackTrace();
        trace(stackTrace);
    }
);

Then, in case of an error, this will print out the full stack trace, even in release mode. E.g.

ArgumentError: Something bad just happened.
    at Game/onButtonTriggered()
    at starling.events::EventDispatcher/invokeEvent()
    at starling.events::EventDispatcher/bubbleEvent()
    at starling.events::EventDispatcher/dispatchEvent()
    at starling.display::DisplayObject/dispatchEvent()
    at starling.events::EventDispatcher/dispatchEventWith()
    at starling.display::Button/onTouch()
    at starling.events::EventDispatcher/invokeEvent()
    at starling.events::TouchEvent/dispatch()
    at starling.events::Touch/dispatchEvent()
    at starling.events::TouchProcessor/processTouches()
    at starling.events::TouchProcessor/advanceTime()
    at starling.core::Starling/advanceTime()
    at starling.core::Starling/nextFrame()
    at starling.core::Starling/onEnterFrame()

Of course, you can also just get the top two lines, for example:

var lines:Array = stackTrace.split("\n\t");
yourLogger.write(lines[0], lines[1]);

Or is there anything else you'd need, but are not getting with this approach? Just let me know!!

kheftel-old commented 7 years ago

I just learned that UncaughtErrorEvent is a thing from this issue. Thanks Daniel!

PrimaryFeather commented 7 years ago

Yes, that feature is easy to overlook! I, too, found it only a few years after starting with AS3!