FString UGatherTextFromSourceCommandlet::RemoveStringFromTextMacro(const FString& TextMacro, const FString& IdentForLogging, bool& Error) { FString Text; Error = true; // need to strip text literal out of TextMacro ( format should be TEXT("stringvalue") ) if (!TextMacro.StartsWith(FMacroDescriptor::TextMacroString)) { Error = false; //UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Missing TEXT macro in %s"), *IdentForLogging); return TextMacro.TrimQuotes(); } else { int32 OpenQuoteIdx = TextMacro.Find(TEXT("\""), ESearchCase::CaseSensitive); if (0 > OpenQuoteIdx || TextMacro.Len() - 1 == OpenQuoteIdx) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Missing quotes in %s"), *MungeLogOutput(IdentForLogging)); } else { int32 CloseQuoteIdx = TextMacro.Find(TEXT("\""), ESearchCase::CaseSensitive, ESearchDir::FromStart, OpenQuoteIdx+1); if (0 > CloseQuoteIdx) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Missing quotes in %s"), *MungeLogOutput(IdentForLogging)); } else { Text = TextMacro.Mid(OpenQuoteIdx + 1, CloseQuoteIdx - OpenQuoteIdx - 1); Error = false; } } } return Text; }
void UGatherTextFromSourceCommandlet::FStringMacroDescriptor::TryParse(const FString& Text, FSourceFileParseContext& Context) const { // Attempt to parse something of the format // MACRONAME(param0, param1, param2) if (!Context.ExcludedRegion && (Context.Filename.EndsWith(TEXT(".inl")) || (!Context.WithinBlockComment && !Context.WithinLineComment && !Context.WithinStringLiteral)) ) { TArray<FString> ArgArray; if (ParseArgsFromMacro(Text, ArgArray, Context)) { int32 NumArgs = ArgArray.Num(); if (NumArgs != Arguments.Num()) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Too many arguments in %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); } else { FString Identifier; FString Namespace = Context.Namespace; FString SourceLocation = FString( Context.Filename + TEXT(" - line ") + FString::FromInt(Context.LineNumber) ); FString SourceText; bool ArgParseError = false; for (int32 ArgIdx=0; ArgIdx<Arguments.Num(); ArgIdx++) { FMacroArg Arg = Arguments[ArgIdx]; FString ArgText = ArgArray[ArgIdx].Trim(); bool HasQuotes; FString MacroDesc = FString::Printf(TEXT("argument %d of %d in localization macro %s %s(%d):%s"), ArgIdx+1, Arguments.Num(), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); if (!PrepareArgument(ArgText, Arg.IsAutoText, MacroDesc, HasQuotes)) { ArgParseError = true; break; } switch (Arg.Semantic) { case MAS_Namespace: { Namespace = ArgText; } break; case MAS_Identifier: { Identifier = ArgText; } break; case MAS_SourceText: { SourceText = ArgText; } break; } } if ( Identifier.IsEmpty() ) { //The command doesn't have an identifier so we can't gather it UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Macro doesn't have unique identifier. %s"), *SourceLocation ); return; } if (!ArgParseError && !Identifier.IsEmpty() && !SourceText.IsEmpty()) { FContext MacroContext; MacroContext.Key = Identifier; MacroContext.SourceLocation = SourceLocation; Context.AddManifestText( GetToken(), Namespace, SourceText, MacroContext ); } } } } }
void UGatherTextFromSourceCommandlet::FCommandMacroDescriptor::TryParse(const FString& Text, FSourceFileParseContext& Context) const { // Attempt to parse something of the format // UI_COMMAND(LocKey, DefaultLangString, DefaultLangTooltipString, <IgnoredParam>, <IgnoredParam>) if (!Context.ExcludedRegion && (Context.Filename.EndsWith(TEXT(".inl")) || (!Context.WithinBlockComment && !Context.WithinLineComment && !Context.WithinStringLiteral)) ) { TArray<FString> Arguments; if (ParseArgsFromMacro(Text, Arguments, Context)) { if (Arguments.Num() != 5) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Too many arguments in command %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); } else { FString Identifier = Arguments[0].Trim(); const FString UICommandRootNamespace = TEXT("UICommands"); FString Namespace = Context.WithinNamespaceDefine && !Context.Namespace.IsEmpty() ? FString::Printf( TEXT("%s.%s"), *UICommandRootNamespace, *Context.Namespace) : UICommandRootNamespace; FString SourceLocation = FString( Context.Filename + TEXT(" - line ") + FString::FromInt(Context.LineNumber) ); FString SourceText = Arguments[1].Trim(); if ( Identifier.IsEmpty() ) { //The command doesn't have an identifier so we can't gather it UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("UICOMMAND macro doesn't have unique identifier. %s"), *SourceLocation ); return; } // parse DefaultLangString argument - this arg will be in quotes without TEXT macro bool HasQuotes; FString MacroDesc = FString::Printf(TEXT("\"FriendlyName\" argument in %s macro %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *Context.LineText); if ( PrepareArgument(SourceText, true, MacroDesc, HasQuotes) ) { if ( HasQuotes && !Identifier.IsEmpty() && !SourceText.IsEmpty() ) { // First create the command entry FContext CommandContext; CommandContext.Key = Identifier; CommandContext.SourceLocation = SourceLocation; Context.AddManifestText( GetToken(), Namespace, SourceText, CommandContext ); // parse DefaultLangTooltipString argument - this arg will be in quotes without TEXT macro FString TooltipSourceText = Arguments[2].Trim(); MacroDesc = FString::Printf(TEXT("\"InDescription\" argument in %s macro %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *Context.LineText); if (PrepareArgument(TooltipSourceText, true, MacroDesc, HasQuotes)) { if (HasQuotes && !TooltipSourceText.IsEmpty()) { // Create the tooltip entry FContext CommandTooltipContext; CommandTooltipContext.Key = Identifier + TEXT("_ToolTip"); CommandTooltipContext.SourceLocation = SourceLocation; Context.AddManifestText( GetToken(), Namespace, TooltipSourceText, CommandTooltipContext ); } } } } } } } }
bool UGatherTextFromSourceCommandlet::FMacroDescriptor::ParseArgsFromMacro(const FString& Text, TArray<FString>& Args, FSourceFileParseContext& Context) const { // Attempt to parse something of the format // NAME(param0, param1, param2, etc) bool Success = false; FString RemainingText = Text.RightChop(GetToken().Len()).Trim(); int32 OpenBracketIdx = RemainingText.Find(TEXT("(")); if (0 > OpenBracketIdx) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Missing bracket '(' in %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); //Dont assume this is an error. It's more likely trying to parse something it shouldn't be. return false; } else { Args.Empty(); bool bInDblQuotes = false; bool bInSglQuotes = false; int32 BracketStack = 1; bool bEscapeNextChar = false; const TCHAR* ArgStart = *RemainingText + OpenBracketIdx + 1; const TCHAR* Cursor = ArgStart; for (; 0 < BracketStack && '\0' != *Cursor; ++Cursor) { if (bEscapeNextChar) { bEscapeNextChar = false; } else if ((bInDblQuotes || bInSglQuotes) && !bEscapeNextChar && '\\' == *Cursor) { bEscapeNextChar = true; } else if (bInDblQuotes) { if ('\"' == *Cursor) { bInDblQuotes = false; } } else if (bInSglQuotes) { if ('\'' == *Cursor) { bInSglQuotes = false; } } else if ('\"' == *Cursor) { bInDblQuotes = true; } else if ('\'' == *Cursor) { bInSglQuotes = true; } else if ('(' == *Cursor) { ++BracketStack; } else if (')' == *Cursor) { --BracketStack; if (0 > BracketStack) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Unexpected bracket ')' in %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); return false; } } else if (1 == BracketStack && ',' == *Cursor) { // create argument from ArgStart to Cursor and set Start next char Args.Add(FString(Cursor - ArgStart, ArgStart)); ArgStart = Cursor + 1; } } if (0 == BracketStack) { Args.Add(FString(Cursor - ArgStart - 1, ArgStart)); } else { Args.Add(FString(ArgStart)); } Success = 0 < Args.Num() ? true : false; } return Success; }