From 45fa3561a5c8fcbba3ebcef7aff25ed296e49fe9 Mon Sep 17 00:00:00 2001 From: A-Ron Date: Mon, 12 Aug 2024 21:10:19 +0100 Subject: [PATCH] Lua skin additions (#3667) * pushNSObject: checks for exact class match first * log*: supports format, args style without NSString stringWithFormat: --- LuaSkin/LuaSkin/Skin.h | 26 ++++----- LuaSkin/LuaSkin/Skin.m | 123 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 122 insertions(+), 27 deletions(-) diff --git a/LuaSkin/LuaSkin/Skin.h b/LuaSkin/LuaSkin/Skin.h index 10ea47381..1655d9342 100644 --- a/LuaSkin/LuaSkin/Skin.h +++ b/LuaSkin/LuaSkin/Skin.h @@ -891,49 +891,49 @@ NSString *specMaskToString(int spec); @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_VERBOSE @/link @param theMessage the message to log */ -- (void)logVerbose:(NSString *)theMessage ; +- (void)logVerbose:(NSString *)theMessage, ... ; /*! @abstract Log the specified message with LS_LOG_DEBUG level @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_DEBUG @/link @param theMessage the message to log */ -- (void)logDebug:(NSString *)theMessage ; +- (void)logDebug:(NSString *)theMessage, ... ; /*! @abstract Log the specified message with LS_LOG_INFO level @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_INFO @/link @param theMessage the message to log */ -- (void)logInfo:(NSString *)theMessage ; +- (void)logInfo:(NSString *)theMessage, ... ; /*! @abstract Log the specified message with LS_LOG_WARN level @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_WARN @/link @param theMessage the message to log */ -- (void)logWarn:(NSString *)theMessage ; +- (void)logWarn:(NSString *)theMessage, ... ; /*! @abstract Log the specified message with LS_LOG_ERROR level @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_ERROR @/link @param theMessage the message to log */ -- (void)logError:(NSString *)theMessage ; +- (void)logError:(NSString *)theMessage, ... ; /*! @abstract Log the specified message with LS_LOG_BREADCRUMB level @discussion This method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_BREADCRUMB @/link @param theMessage the message to log */ -- (void)logBreadcrumb:(NSString *)theMessage ; +- (void)logBreadcrumb:(NSString *)theMessage, ... ; /*! @abstract Log a known, but avoided issue via the log delegate, primarily to ensure it can be recorded in a crash reporting service @discussion If no delegate has been assigned, the message is logged to the system logs via NSLog. @param message The message to log */ -- (void)logKnownBug:(NSString *)message; +- (void)logKnownBug:(NSString *)message, ... ; // FIXME: Should this be documented? Seems unnecessary to do so, at the moment + (void)classLogAtLevel:(int)level withMessage:(NSString *)theMessage; @@ -950,7 +950,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_VERBOSE @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logVerbose:(NSString *)theMessage ; ++ (void)logVerbose:(NSString *)theMessage, ... ; /*! @apiuid //apple_ref/doc/classmethodparam/LuaSkin/logDebug:/theMessage @@ -958,7 +958,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_DEBUG @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logDebug:(NSString *)theMessage ; ++ (void)logDebug:(NSString *)theMessage, ... ; /*! @apiuid //apple_ref/doc/classmethodparam/LuaSkin/logInfo:/theMessage @@ -966,7 +966,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_INFO @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logInfo:(NSString *)theMessage ; ++ (void)logInfo:(NSString *)theMessage, ... ; /*! @apiuid //apple_ref/doc/classmethodparam/LuaSkin/logWarn:/theMessage @@ -974,7 +974,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_WARN @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logWarn:(NSString *)theMessage ; ++ (void)logWarn:(NSString *)theMessage, ... ; /*! @apiuid //apple_ref/doc/classmethodparam/LuaSkin/logError:/theMessage @@ -982,7 +982,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_ERROR @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logError:(NSString *)theMessage ; ++ (void)logError:(NSString *)theMessage, ... ; /*! @apiuid //apple_ref/doc/classmethodparam/LuaSkin/logBreadcrumb:/theMessage @@ -990,7 +990,7 @@ NSString *specMaskToString(int spec); @discussion This class method is equivalent to invoking @link logAtLevel:withMessage: @/link with level @link LS_LOG_BREADCRUMB @/link, but is safe to use from any thread, not just the main application thread. If this method is invoked from a thread other than the main thread, it uses dispatch_async to submit the logging message to the main thread for proper handling by the delegate. @param theMessage the message to log */ -+ (void)logBreadcrumb:(NSString *)theMessage ; ++ (void)logBreadcrumb:(NSString *)theMessage, ... ; #pragma clang diagnostic pop diff --git a/LuaSkin/LuaSkin/Skin.m b/LuaSkin/LuaSkin/Skin.m index 697fb02d0..3c024d0f4 100644 --- a/LuaSkin/LuaSkin/Skin.m +++ b/LuaSkin/LuaSkin/Skin.m @@ -1259,6 +1259,16 @@ - (int)pushNSObject:(id)obj withOptions:(NSUInteger)options alreadySeenObjects:( // check for registered helpers + // first check for exact class match + for (id key in self.registeredNSHelperFunctions) { + if ([obj isMemberOfClass: NSClassFromString(key)]) { + pushNSHelperFunction theFunc = (pushNSHelperFunction)[self.registeredNSHelperFunctions[key] pointerValue] ; + int resultAnswer = theFunc(self.L, obj) ; + if (resultAnswer > -1) return resultAnswer ; + } + } + + // if we're still here, check for kind of class (i.e. possible superclass of object) for (id key in self.registeredNSHelperFunctions) { if ([obj isKindOfClass: NSClassFromString(key)]) { pushNSHelperFunction theFunc = (pushNSHelperFunction)[self.registeredNSHelperFunctions[key] pointerValue] ; @@ -1746,14 +1756,57 @@ - (void) logAtLevel:(int)level withMessage:(NSString *)theMessage { } // shorthand -- (void)logVerbose:(NSString *)theMessage { [self logAtLevel:LS_LOG_VERBOSE withMessage:theMessage] ; } -- (void)logDebug:(NSString *)theMessage { [self logAtLevel:LS_LOG_DEBUG withMessage:theMessage] ; } -- (void)logInfo:(NSString *)theMessage { [self logAtLevel:LS_LOG_INFO withMessage:theMessage] ; } -- (void)logWarn:(NSString *)theMessage { [self logAtLevel:LS_LOG_WARN withMessage:theMessage] ; } -- (void)logError:(NSString *)theMessage { [self logAtLevel:LS_LOG_ERROR withMessage:theMessage] ; } -- (void)logBreadcrumb:(NSString *)theMessage { [self logAtLevel:LS_LOG_BREADCRUMB withMessage:theMessage] ; } - -- (void)logKnownBug:(NSString *)message { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" + +- (void)logVerbose:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_VERBOSE withMessage:theMessage] ; +} + +- (void)logDebug:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_DEBUG withMessage:theMessage] ; +} + +- (void)logInfo:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_INFO withMessage:theMessage] ; +} + +- (void)logWarn:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_WARN withMessage:theMessage] ; +} + +- (void)logError:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_ERROR withMessage:theMessage] ; +} + +- (void)logBreadcrumb:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self logAtLevel:LS_LOG_BREADCRUMB withMessage:theMessage] ; +} + +- (void)logKnownBug:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *message = [[NSString alloc] initWithFormat:format arguments:args]; + id theDelegate = self.delegate; if (theDelegate && [theDelegate respondsToSelector:@selector(logKnownBug:)]) { @@ -1764,6 +1817,8 @@ - (void)logKnownBug:(NSString *)message { } +#pragma clang diagnostic pop + + (void)classLogAtLevel:(int)level withMessage:(NSString *)theMessage { if ([NSThread isMainThread]) { // the class logging methods *do* use the shared instance, so backup the state/thread in case @@ -1783,12 +1838,52 @@ + (void)classLogAtLevel:(int)level withMessage:(NSString *)theMessage { } } -+ (void)logVerbose:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_VERBOSE withMessage:theMessage]; } -+ (void)logDebug:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_DEBUG withMessage:theMessage]; } -+ (void)logInfo:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_INFO withMessage:theMessage]; } -+ (void)logWarn:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_WARN withMessage:theMessage]; } -+ (void)logError:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_ERROR withMessage:theMessage]; } -+ (void)logBreadcrumb:(NSString *)theMessage { [[self class] classLogAtLevel:LS_LOG_BREADCRUMB withMessage:theMessage]; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" + ++ (void)logVerbose:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_VERBOSE withMessage:theMessage] ; +} + ++ (void)logDebug:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_DEBUG withMessage:theMessage] ; +} + ++ (void)logInfo:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_INFO withMessage:theMessage] ; +} + ++ (void)logWarn:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_WARN withMessage:theMessage] ; +} + ++ (void)logError:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_ERROR withMessage:theMessage] ; +} + ++ (void)logBreadcrumb:(NSString *)format, ... { + va_list args; + va_start(args, format); + NSString *theMessage = [[NSString alloc] initWithFormat:format arguments:args]; + [self classLogAtLevel:LS_LOG_BREADCRUMB withMessage:theMessage] ; +} + +#pragma clang diagnostic pop - (NSString *)tracebackWithTag:(NSString *)theTag fromStackPos:(int)level{ int topIndex = lua_gettop(self.L) ;