Example #1
0
TSharedRef<FTokenizedMessage> FTokenizedMessage::Create(EMessageSeverity::Type InSeverity, const FText& InMessageText)
{
	TSharedRef<FTokenizedMessage> Message = MakeShareable(new FTokenizedMessage());
	Message->SetSeverity( InSeverity );
	Message->AddToken( FSeverityToken::Create(InSeverity) );
	if(!InMessageText.IsEmpty())
	{
		Message->AddToken( FTextToken::Create(InMessageText) );
	}
	return Message;
}
Example #2
0
		/** Helper function to output more detailed error info if available */
		static void OutputErrorDetail(FArchiveUObject* LinkerArchive, const FName& LogName)
		{
			if ( GSerializedObject && GSerializedImportLinker )
			{
				FMessageLog LoadErrors(LogName);

				TSharedRef<FTokenizedMessage> Message = LoadErrors.Info();
				Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Message", "Failed to load")));
				Message->AddToken(FAssetNameToken::Create(GSerializedImportLinker->GetImportPathName(GSerializedImportIndex)));
				Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Referenced", "Referenced by")));
				Message->AddToken(FUObjectToken::Create(GSerializedObject));
				auto SerializedProperty = LinkerArchive ? LinkerArchive->GetSerializedProperty() : nullptr;
				if (SerializedProperty != nullptr)
				{
					FString PropertyPathName = SerializedProperty->GetPathName();
					Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Property", "Property")));
					Message->AddToken(FAssetNameToken::Create(PropertyPathName, FText::FromString( PropertyPathName) ) );
				}
			}
		}
Example #3
0
static void LogGetPackageLinkerError(FArchiveUObject* LinkerArchive, const TCHAR* InFilename, const FText& InFullErrorMessage, const FText& InSummaryErrorMessage, UObject* InOuter, uint32 LoadFlags)
{
	static FName NAME_LoadErrors("LoadErrors");
	struct Local
	{
		/** Helper function to output more detailed error info if available */
		static void OutputErrorDetail(FArchiveUObject* LinkerArchive, const FName& LogName)
		{
			if ( GSerializedObject && GSerializedImportLinker )
			{
				FMessageLog LoadErrors(LogName);

				TSharedRef<FTokenizedMessage> Message = LoadErrors.Info();
				Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Message", "Failed to load")));
				Message->AddToken(FAssetNameToken::Create(GSerializedImportLinker->GetImportPathName(GSerializedImportIndex)));
				Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Referenced", "Referenced by")));
				Message->AddToken(FUObjectToken::Create(GSerializedObject));
				auto SerializedProperty = LinkerArchive ? LinkerArchive->GetSerializedProperty() : nullptr;
				if (SerializedProperty != nullptr)
				{
					FString PropertyPathName = SerializedProperty->GetPathName();
					Message->AddToken(FTextToken::Create(LOCTEXT("FailedLoad_Property", "Property")));
					Message->AddToken(FAssetNameToken::Create(PropertyPathName, FText::FromString( PropertyPathName) ) );
				}
			}
		}
	};

	FMessageLog LoadErrors(NAME_LoadErrors);

	// Display log error regardless LoadFlag settings
	SET_WARN_COLOR(COLOR_RED);
	if (LoadFlags & LOAD_NoWarn)
	{
		UE_LOG(LogLinker, Log, TEXT("%s"), *InFullErrorMessage.ToString());
	}
	else 
	{
		UE_LOG(LogLinker, Warning, TEXT("%s"), *InFullErrorMessage.ToString());
	}
	CLEAR_WARN_COLOR();
	if( GIsEditor && !IsRunningCommandlet() )
	{
		// if we don't want to be warned, skip the load warning
		if (!(LoadFlags & LOAD_NoWarn))
		{
			// we only want to output errors that content creators will be able to make sense of,
			// so any errors we cant get links out of we will just let be output to the output log (above)
			// rather than clog up the message log

			if(InFilename != NULL && InOuter != NULL)
			{
				// Output the summary error & the filename link. This might be something like "..\Content\Foo.upk Out of Memory"
				TSharedRef<FTokenizedMessage> Message = LoadErrors.Error();
				Message->AddToken(FAssetNameToken::Create(FPackageName::FilenameToLongPackageName(InFilename)));
				Message->AddToken(FTextToken::Create(FText::FromString(TEXT(":"))));
				Message->AddToken(FTextToken::Create(InSummaryErrorMessage));
				Message->AddToken(FAssetNameToken::Create(FPackageName::FilenameToLongPackageName(InOuter->GetPathName())));
			}

			Local::OutputErrorDetail(LinkerArchive, NAME_LoadErrors);
		}
	}
	else
	{
		if (!(LoadFlags & LOAD_NoWarn))
		{
			Local::OutputErrorDetail(LinkerArchive, NAME_LoadErrors);
		}

		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("FileName"), FText::FromString(InFilename ? InFilename : InOuter ? *InOuter->GetName() : TEXT("NULL")));
		Arguments.Add(TEXT("ErrorMessage"), InFullErrorMessage);
		const FText Error = FText::Format(LOCTEXT("FailedLoad", "Failed to load '{FileName}': {ErrorMessage}"), Arguments);

		// @see ResavePackagesCommandlet
		if( FParse::Param(FCommandLine::Get(),TEXT("SavePackagesThatHaveFailedLoads")) == true )
		{
			LoadErrors.Warning(Error);
		}
		else
		{
			// Gracefully handle missing packages
			SafeLoadError( InOuter, LoadFlags, *InFullErrorMessage.ToString(), *Error.ToString() );
		}
	}
}
Example #4
0
TArray< TSharedRef<FTokenizedMessage> > FCompilerResultsLog::ParseCompilerLogDump(const FString& LogDump)
{
	TArray< TSharedRef<FTokenizedMessage> > Messages;

	TArray< FString > MessageLines;
	LogDump.ParseIntoArray(MessageLines, TEXT("\n"), false);

	// delete any trailing empty lines
	for (int32 i = MessageLines.Num()-1; i >= 0; --i)
	{
		if (!MessageLines[i].IsEmpty())
		{
			if (i < MessageLines.Num() - 1)
			{
				MessageLines.RemoveAt(i+1, MessageLines.Num() - (i+1));
			}
			break;
		}
	}

	for (int32 i = 0; i < MessageLines.Num(); ++i)
	{
		FString Line = MessageLines[i];
		if (Line.EndsWith(TEXT("\r")))
		{
			Line = Line.LeftChop(1);
		}
		Line = Line.ConvertTabsToSpaces(4).TrimTrailing();

		// handle output line error message if applicable
		// @todo Handle case where there are parenthesis in path names
		// @todo Handle errors reported by Clang
		FString LeftStr, RightStr;
		FString FullPath, LineNumberString;
		if (Line.Split(TEXT(")"), &LeftStr, &RightStr, ESearchCase::CaseSensitive) &&
			LeftStr.Split(TEXT("("), &FullPath, &LineNumberString, ESearchCase::CaseSensitive) &&
			LineNumberString.IsNumeric() && (FCString::Strtoi(*LineNumberString, NULL, 10) > 0))
		{
			EMessageSeverity::Type Severity = EMessageSeverity::Error;
			FString FullPathTrimmed = FullPath;
			FullPathTrimmed.Trim();
			if (FullPathTrimmed.Len() != FullPath.Len()) // check for leading whitespace
			{
				Severity = EMessageSeverity::Info;
			}

			TSharedRef<FTokenizedMessage> Message = FTokenizedMessage::Create( Severity );
			if ( Severity == EMessageSeverity::Info )	// add whitespace now
			{
				FString Whitespace = FullPath.Left(FullPath.Len() - FullPathTrimmed.Len());
				Message->AddToken( FTextToken::Create( FText::FromString( Whitespace ) ) );
				FullPath = FullPathTrimmed;
			}

			FString Link = FullPath + TEXT("(") + LineNumberString + TEXT(")");
			Message->AddToken( FTextToken::Create( FText::FromString( Link ) )->OnMessageTokenActivated(FOnMessageTokenActivated::CreateStatic(&FCompilerResultsLog::OnGotoError) ) );
			Message->AddToken( FTextToken::Create( FText::FromString( RightStr ) ) );
			Messages.Add(Message);
		}
		else
		{
			EMessageSeverity::Type Severity = EMessageSeverity::Info;
			if (Line.Contains(TEXT("error LNK"), ESearchCase::CaseSensitive))
			{
				Severity = EMessageSeverity::Error;
			}

			TSharedRef<FTokenizedMessage> Message = FTokenizedMessage::Create( Severity );
			Message->AddToken( FTextToken::Create( FText::FromString( Line ) ) );
			Messages.Add(Message);
		}
	}

	return Messages;
}
Example #5
0
/** Create a tokenized message record from a message containing @@ indicating where each UObject* in the ArgPtr list goes and place it in the MessageLog. */
void FCompilerResultsLog::InternalLogMessage(const EMessageSeverity::Type& Severity, const TCHAR* Message, va_list ArgPtr)
{
	UEdGraphNode* OwnerNode = nullptr;

	// Create the tokenized message
	TSharedRef<FTokenizedMessage> Line = FTokenizedMessage::Create( Severity );
	Messages.Add(Line);

	const TCHAR* DelimiterStr = TEXT("@@");
	int32 DelimLength = FCString::Strlen(DelimiterStr);

	const TCHAR* Start = Message;
	if (Start && DelimLength)
	{
		while (const TCHAR* At = FCString::Strstr(Start, DelimiterStr))
		{
			// Found a delimiter, create a token from the preceding text
			Line->AddToken( FTextToken::Create( FText::FromString( FString(At - Start, Start) ) ) );
			Start += DelimLength + (At - Start);

			// And read the object and add another token for the object
			UObject* ObjectArgument = va_arg(ArgPtr, UObject*);

			FText ObjText;
			if (ObjectArgument)
			{
				// Remap object references to the source nodes
				ObjectArgument = FindSourceObject(ObjectArgument);

				if (ObjectArgument)
				{
					UEdGraphNode* Node = Cast<UEdGraphNode>(ObjectArgument);
					const UEdGraphPin* Pin = (Node? nullptr : Cast<UEdGraphPin>(ObjectArgument));

					//Get owner node reference, consider the first 
					if (OwnerNode == nullptr)
					{
						OwnerNode = (Pin ? Pin->GetOwningNodeUnchecked() : Node);
					}

					if (ObjectArgument->GetOutermost() == GetTransientPackage())
					{
						ObjText = LOCTEXT("Transient", "(transient)");					
					}
					else if (Node != NULL)
					{
						ObjText = Node->GetNodeTitle(ENodeTitleType::ListView);
					}
					else if (Pin != NULL)
					{
						ObjText = Pin->GetDisplayName();
					}
					else
					{
						ObjText = FText::FromString( ObjectArgument->GetName() );
					}
				}
				else
				{
					ObjText = LOCTEXT("None", "(none)");
				}

			}
			else
			{
				ObjText = LOCTEXT("None", "(none)");
			}
			
			Line->AddToken( FUObjectToken::Create( ObjectArgument, ObjText ) );
		}
		Line->AddToken( FTextToken::Create( FText::FromString( Start ) ) );
	}

	va_end(ArgPtr);

	// Register node error/warning.
	AnnotateNode(OwnerNode, Line);

	if( !bSilentMode && (!bLogInfoOnly || (Severity == EMessageSeverity::Info)) )
	{
		if(Severity == EMessageSeverity::CriticalError || Severity == EMessageSeverity::Error)
		{
			UE_LOG(LogBlueprint, Error, TEXT("[compiler] %s"), *Line->ToText().ToString());
		}
		else if(Severity == EMessageSeverity::Warning || Severity == EMessageSeverity::PerformanceWarning)
		{
			UE_LOG(LogBlueprint, Warning, TEXT("[compiler] %s"), *Line->ToText().ToString());
		}
		else
		{
			UE_LOG(LogBlueprint, Log, TEXT("[compiler] %s"), *Line->ToText().ToString());
		}
	}
}