removed unused methods(BeginPlay, Tick) and added rider plugin
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
#include "RiderLogging.hpp"
|
||||
|
||||
#include "BlueprintProvider.hpp"
|
||||
#include "IRiderLink.hpp"
|
||||
#include "Model/Library/UE4Library/LogMessageInfo.Pregenerated.h"
|
||||
#include "Model/Library/UE4Library/StringRange.Pregenerated.h"
|
||||
#include "Model/Library/UE4Library/UnrealLogEvent.Pregenerated.h"
|
||||
|
||||
#include "Internationalization/Regex.h"
|
||||
#include "Misc/DateTime.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "RiderLogging"
|
||||
|
||||
DEFINE_LOG_CATEGORY(FLogRiderLoggingModule);
|
||||
|
||||
IMPLEMENT_MODULE(FRiderLoggingModule, RiderLogging);
|
||||
|
||||
namespace LoggingExtensionImpl
|
||||
{
|
||||
static TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetPathRanges(
|
||||
const FRegexPattern& Pattern,
|
||||
const FString& Str)
|
||||
{
|
||||
using JetBrains::EditorPlugin::StringRange;
|
||||
FRegexMatcher Matcher(Pattern, Str);
|
||||
TArray<rd::Wrapper<StringRange>> Ranges;
|
||||
while (Matcher.FindNext())
|
||||
{
|
||||
const int Start = Matcher.GetMatchBeginning();
|
||||
const int End = Matcher.GetMatchEnding();
|
||||
FString PathName = Str.Mid(Start, End - Start);
|
||||
if (BluePrintProvider::IsBlueprint(PathName))
|
||||
Ranges.Emplace(StringRange(Start, End));
|
||||
}
|
||||
return Ranges;
|
||||
}
|
||||
|
||||
static TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetMethodRanges(
|
||||
const FRegexPattern& Pattern,
|
||||
const FString& Str)
|
||||
{
|
||||
using JetBrains::EditorPlugin::StringRange;
|
||||
FRegexMatcher Matcher(Pattern, Str);
|
||||
TArray<rd::Wrapper<StringRange>> Ranges;
|
||||
while (Matcher.FindNext())
|
||||
{
|
||||
Ranges.Emplace(StringRange(Matcher.GetMatchBeginning(), Matcher.GetMatchEnding()));
|
||||
}
|
||||
return Ranges;
|
||||
}
|
||||
|
||||
static bool SendMessageToRider(const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo, const FString& Message)
|
||||
{
|
||||
static const FRegexPattern PathPattern = FRegexPattern(TEXT("(/[\\w\\.]+)+"));
|
||||
static const FRegexPattern MethodPattern = FRegexPattern(TEXT("[0-9a-z_A-Z]+::~?[0-9a-z_A-Z]+"));
|
||||
|
||||
return IRiderLinkModule::Get().FireAsyncAction(
|
||||
[&MessageInfo, &Message] (JetBrains::EditorPlugin::RdEditorModel const& RdEditorModel)
|
||||
{
|
||||
rd::ISignal<JetBrains::EditorPlugin::UnrealLogEvent> const& UnrealLog = RdEditorModel.get_unrealLog();
|
||||
UnrealLog.fire({
|
||||
MessageInfo,
|
||||
Message,
|
||||
GetPathRanges(PathPattern, Message),
|
||||
GetMethodRanges(MethodPattern, Message)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void SendMessageInChunks(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)
|
||||
{
|
||||
static int NUMBER_OF_CHUNKS = 1024;
|
||||
while (!Msg->IsEmpty())
|
||||
{
|
||||
SendMessageToRider(MessageInfo, Msg->Left(NUMBER_OF_CHUNKS));
|
||||
*Msg = Msg->RightChop(NUMBER_OF_CHUNKS);
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduledSendMessage(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)
|
||||
{
|
||||
FString ToSend;
|
||||
while (Msg->Split("\n", &ToSend, Msg))
|
||||
{
|
||||
SendMessageInChunks(&ToSend, MessageInfo);
|
||||
}
|
||||
|
||||
SendMessageInChunks(Msg, MessageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FRiderLoggingModule::StartupModule()
|
||||
{
|
||||
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("STARTUP START"));
|
||||
|
||||
static const auto START_TIME = FDateTime::UtcNow().ToUnixTimestamp();
|
||||
static const auto GetTimeNow = [](double Time) -> rd::DateTime
|
||||
{
|
||||
return rd::DateTime(START_TIME + static_cast<int64>(Time));
|
||||
};
|
||||
|
||||
ModuleLifetimeDef = IRiderLinkModule::Get().CreateNestedLifetimeDefinition();
|
||||
LoggingScheduler = MakeUnique<rd::SingleThreadScheduler>(ModuleLifetimeDef.lifetime, "LoggingScheduler");
|
||||
ModuleLifetimeDef.lifetime->bracket(
|
||||
[this]()
|
||||
{
|
||||
OutputDevice.Setup([this](const TCHAR* msg, ELogVerbosity::Type Type, const FName& Name, TOptional<double> Time)
|
||||
{
|
||||
if (Type > ELogVerbosity::All) return;
|
||||
|
||||
rd::optional<rd::DateTime> DateTime;
|
||||
if (Time)
|
||||
{
|
||||
DateTime = GetTimeNow(Time.GetValue());
|
||||
}
|
||||
const FString PlainName = Name.GetPlainNameString();
|
||||
const JetBrains::EditorPlugin::LogMessageInfo MessageInfo{Type, PlainName, DateTime};
|
||||
|
||||
LoggingScheduler->queue([Msg = FString(msg), MessageInfo]() mutable
|
||||
{
|
||||
LoggingExtensionImpl::ScheduledSendMessage(&Msg, MessageInfo);
|
||||
});
|
||||
});
|
||||
},
|
||||
[this]()
|
||||
{
|
||||
OutputDevice.TearDown();
|
||||
});
|
||||
|
||||
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("STARTUP FINISH"));
|
||||
}
|
||||
|
||||
void FRiderLoggingModule::ShutdownModule()
|
||||
{
|
||||
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("SHUTDOWN START"));
|
||||
ModuleLifetimeDef.terminate();
|
||||
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("SHUTDOWN FINISH"));
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "RiderOutputDevice.hpp"
|
||||
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "lifetime/LifetimeDefinition.h"
|
||||
|
||||
#include "Logging/LogMacros.h"
|
||||
#include "Logging/LogVerbosity.h"
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "scheduler/SingleThreadScheduler.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(FLogRiderLoggingModule, Log, All);
|
||||
|
||||
class FRiderLoggingModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
FRiderLoggingModule() = default;
|
||||
virtual ~FRiderLoggingModule() override = default;
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
virtual bool SupportsDynamicReloading() override { return true; }
|
||||
|
||||
private:
|
||||
TUniquePtr<rd::SingleThreadScheduler> LoggingScheduler;
|
||||
FRiderOutputDevice OutputDevice;
|
||||
rd::LifetimeDefinition ModuleLifetimeDef;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "RiderOutputDevice.hpp"
|
||||
|
||||
#include "CoreGlobals.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
#include "Misc/OutputDeviceRedirector.h"
|
||||
|
||||
void FRiderOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category)
|
||||
{
|
||||
Serialize(V, Verbosity, Category, {});
|
||||
}
|
||||
|
||||
void FRiderOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category,
|
||||
const double Time)
|
||||
{
|
||||
FScopeLock Lock{&CriticalSection};
|
||||
|
||||
onSerializeMessage.ExecuteIfBound(V, Verbosity, Category, {Time});
|
||||
}
|
||||
|
||||
FRiderOutputDevice::~FRiderOutputDevice()
|
||||
{
|
||||
// At shutdown, GLog may already be null
|
||||
// This should be out of scoped lock, because it'll implicitly try take a lock in OutputDeviceRedirector
|
||||
// And Serialize is already holding that lock, so we'll have a deadlock here
|
||||
if (GLog != nullptr)
|
||||
{
|
||||
GLog->RemoveOutputDevice(this);
|
||||
}
|
||||
}
|
||||
|
||||
void FRiderOutputDevice::Setup(TFunction<FOnSerializeMessage::TFuncType> Callback)
|
||||
{
|
||||
FScopeLock Lock{&CriticalSection};
|
||||
|
||||
if(onSerializeMessage.IsBound()) return;
|
||||
|
||||
onSerializeMessage.BindLambda(Callback);
|
||||
GLog->AddOutputDevice(this);
|
||||
#if ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 7)
|
||||
GLog->SerializeBacklog(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FRiderOutputDevice::TearDown()
|
||||
{
|
||||
FScopeLock Lock{&CriticalSection};
|
||||
|
||||
if(onSerializeMessage.IsBound() == false) return;
|
||||
|
||||
onSerializeMessage.Unbind();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "Misc/OutputDevice.h"
|
||||
#include "Delegates/Delegate.h"
|
||||
#include "Logging/LogVerbosity.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
|
||||
using FOnSerializeMessage =
|
||||
#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 26
|
||||
TBaseDelegate<void, const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>>;
|
||||
#elif ENGINE_MAJOR_VERSION < 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 3)
|
||||
TDelegate<void(const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>)>;
|
||||
#else
|
||||
TDelegate<void(const TCHAR*, ELogVerbosity::Type, const FName&, TOptional<double>), FDefaultTSDelegateUserPolicy>;
|
||||
#endif
|
||||
|
||||
class FRiderOutputDevice : public FOutputDevice {
|
||||
public:
|
||||
~FRiderOutputDevice();
|
||||
void Setup(TFunction<FOnSerializeMessage::TFuncType>);
|
||||
virtual void TearDown() override;
|
||||
|
||||
protected:
|
||||
virtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) override;
|
||||
virtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category, double Time) override;
|
||||
|
||||
private:
|
||||
FOnSerializeMessage onSerializeMessage;
|
||||
FCriticalSection CriticalSection;
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class RiderLogging : ModuleRules
|
||||
{
|
||||
public RiderLogging(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
#if UE_4_22_OR_LATER
|
||||
PCHUsage = PCHUsageMode.NoPCHs;
|
||||
#else
|
||||
PCHUsage = PCHUsageMode.NoSharedPCHs;
|
||||
#endif
|
||||
|
||||
#if UE_5_2_OR_LATER
|
||||
if(Target.Platform == UnrealTargetPlatform.Linux || Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
bUseRTTI = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bUseRTTI = true;
|
||||
}
|
||||
|
||||
#if UE_5_2_OR_LATER
|
||||
bDisableStaticAnalysis = true;
|
||||
#endif
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new []
|
||||
{
|
||||
"Core",
|
||||
"RD",
|
||||
"RiderLink",
|
||||
"RiderBlueprint"
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user