-
Notifications
You must be signed in to change notification settings - Fork 2
Exceptions Tutorial
Sheets includes a custom error handling system. Rather than just throwing a plain-old-Lua error, it uses an OOP approach as well. This is where the Exception class comes in.
An exception can be thrown in two similar ways:
-- Throw the exception XException
Exception.throw( XException( ... ) )
-- The following syntax has the same effect
Exception.throw( XException, ... )Exceptions contain what is called a 'stack traceback'. This is a list of all the bits of code (their location and line number) through which the exception had to 'travel'. An example stack traceback might look like this:
{
"lib:27";
"main:21";
"Button:52";
"Sheet:101";
}This allows you to easily track down where the exception was thrown from, and exactly where in the program it was called from.
Since exceptions are technically not errors, you cannot handle them with pcall() or xpcall(). Instead, Exception.try() is used to emulate a try&catch statement. Its syntax in Sheets is as follows:
Exception.try (f) {
-- Catch the exception of type XException using handler1
Exception.catch (XException) (handler1);
-- If the exception isn't an XException, try catching YException with handler2
Exception.catch "YException" (handler2);
-- If the exception didn't match any of the above, default to handler3
Exception.default (handler3);
}That will try to execute the function f, and if it errors, will go through the list of catches/defaults until one matches, at which point the handler of that catch will be called with the exception.
A catch will match if the exception thrown is of the same type as the one the catch was called with. A default will match any exception.
Exceptions are in fact standard classes. Creating new exception types is as easy as extending the base Exception class:
-- Create a new empty class MyCustomException that inherits behaviour from Exception
class "MyCustomException" extends "Exception"
-- The constructor for our newly created class
function MyCustomException:MyCustomException( ... )
return self:Exception( "MyCustomException", ... )
endYou would then be able to use MyCustomException as an exception type, and throw exceptions like:
Exception.throw( MyCustomException( ... ) )and
Exception.throw( MyCustomException, ... )Using the try&catch statement, you can control what code is executed based on the exception. For example, you might want to catch an IncorrectConstructorException and write anything else to a file. To do this, you could use:
local function saveExceptionToLogFile( exception )
-- Open a log file in append mode and save the exception data
local h = fs.open( "log.txt", "a" )
h.writeLine( tostring( exception ) )
h.close()
end
local function errorWithException( exception )
-- Simply error with the exception data
error( tostring( exception ), 0 )
end
-- Try running function f
Exception.try (f) {
-- In case of an IncorrectConstructorException, call errorWithException
Exception.catch (IncorrectConstructorException) (errorWithException);
-- Otherwise call saveExceptionToLogFile
Exception.default (saveExceptionToLogFile)
}- Exception
- DynamicValueException
- ExpressionException
- IncorrectConstructorException
- IncorrectParameterException
- ParserException
- ResourceLoadException
- ThreadRuntimeException