// Copyright Epic Games, Inc. All Rights Reserved. // uLang Parser Public API #pragma once #include "uLang/Common/Containers/SharedPointerArray.h" #include "uLang/Common/Misc/Event.h" #include "uLang/Diagnostics/Glitch.h" namespace uLang { enum class EBuildEvent { UseOfExperimentalDefinition, PersistentWeakMapDefinition, FunctionDefinition, ClassDefinition, TopLevelDefinition }; // In the future, for other types of events (e.g. memory calculation) this can be expanded to accommodate other types of statistics // that aren't just a simple "number of events". struct SBuildEventInfo { union { uint32_t Count; }; EBuildEvent Type; }; /// Various statistics for a given build that can be used in analytics. struct SBuildStatistics { uint32_t NumUsesOfExperimentalDefinitions = 0; uint32_t NumPersistentWeakMaps = 0; uint32_t NumFunctions = 0; uint32_t NumClasses = 0; uint32_t NumTopLevelDefinitions = 0; }; // Accumulated issues for full set of compilation passes class CDiagnostics : public CSharedMix { public: // Just warnings (no info or errors) ULANG_FORCEINLINE bool HasWarnings() const { return _Glitches.ContainsByPredicate([](const SGlitch* Glitch) -> bool { return Glitch->_Result.IsWarning(); }); } VERSECOMPILER_API int32_t GetWarningNum() const; // Just errors (no info or warnings) ULANG_FORCEINLINE bool HasErrors() const { return _Glitches.ContainsByPredicate([](const SGlitch* Glitch) -> bool { return Glitch->_Result.IsError(); }); } VERSECOMPILER_API int32_t GetErrorNum() const; // Any type of glitch including info, warnings and errors ULANG_FORCEINLINE bool HasGlitches() const { return _Glitches.IsFilled(); } ULANG_FORCEINLINE int32_t GetGlitchNum() const { return _Glitches.Num(); } ULANG_FORCEINLINE const TSRefArray& GetGlitches() const { return _Glitches; } ULANG_FORCEINLINE bool IsGlitchWithId(uintptr_t VstIdentifier) const { return _Glitches.ContainsByPredicate([VstIdentifier](const SGlitch* Glitch) -> bool { return Glitch->_Locus._VstIdentifier == VstIdentifier; }); } ULANG_FORCEINLINE bool HasUseOfExperimentalDefinition() const { return _Statistics.NumUsesOfExperimentalDefinitions > 0; } ULANG_FORCEINLINE const SBuildStatistics& GetStatistics() const { return _Statistics; } ULANG_FORCEINLINE void Reset() { _Glitches.Empty(); } void AppendGlitch(const TSRef& Glitch) { _Glitches.Add(Glitch); _OnGlitchEvent.Broadcast(Glitch); } void AppendGlitch(const TSPtr& Glitch) { AppendGlitch(Glitch.AsRef()); } ULANG_FORCEINLINE void AppendGlitch(SGlitchResult&& Result, SGlitchLocus&& Locus) { AppendGlitch(TSRef::New(Move(Result), Move(Locus))); } ULANG_FORCEINLINE void AppendGlitch(SGlitchResult&& Result) { AppendGlitch(TSRef::New(Move(Result), SGlitchLocus())); } ULANG_FORCEINLINE void AppendGlitches(TSRefArray& Glitches) { for (const TSRef& NewGlitch : Glitches) { _OnGlitchEvent.Broadcast(NewGlitch); } _Glitches.Append(Glitches); } ULANG_FORCEINLINE void Append(CDiagnostics&& Other) { for (const TSRef& NewGlitch : Other._Glitches) { _OnGlitchEvent.Broadcast(NewGlitch); } _Glitches.Append(Move(Other._Glitches)); for (uint32_t I = Other._Statistics.NumPersistentWeakMaps; I != 0; --I) { _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::PersistentWeakMapDefinition}); } _Statistics.NumPersistentWeakMaps += Other._Statistics.NumPersistentWeakMaps; _Statistics.NumClasses += Other._Statistics.NumClasses; _Statistics.NumFunctions += Other._Statistics.NumFunctions; _Statistics.NumTopLevelDefinitions += Other._Statistics.NumTopLevelDefinitions; _Statistics.NumUsesOfExperimentalDefinitions += Other._Statistics.NumUsesOfExperimentalDefinitions; for (uint32_t I = Other._Statistics.NumUsesOfExperimentalDefinitions; I != 0; --I) { _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::UseOfExperimentalDefinition}); } } ULANG_FORCEINLINE void AppendPersistentWeakMap() { ++_Statistics.NumPersistentWeakMaps; _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::PersistentWeakMapDefinition}); } ULANG_FORCEINLINE void AppendFunctionDefinition(const uint32_t Count) { _Statistics.NumFunctions += Count; _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::FunctionDefinition}); } ULANG_FORCEINLINE void AppendClassDefinition(const uint32_t Count) { _Statistics.NumClasses += Count; _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::ClassDefinition}); } ULANG_FORCEINLINE void AppendTopLevelDefinition(const uint32_t Count) { _Statistics.NumTopLevelDefinitions += Count; _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::TopLevelDefinition}); } ULANG_FORCEINLINE void AppendUseOfExperimentalDefinition() { _Statistics.NumUsesOfExperimentalDefinitions += 1; _OnBuildStatisticEvent.Broadcast({.Count = 1, .Type = EBuildEvent::UseOfExperimentalDefinition}); } using COnGlitchEvent = TEvent&>; COnGlitchEvent::Registrar& OnGlitchEvent() { return _OnGlitchEvent; } /// The type of event, followed by the count of that type of event. using COnBuildStatisticEvent = TEvent; COnBuildStatisticEvent::Registrar& OnBuildStatisticEvent() { return _OnBuildStatisticEvent; } protected: // All the issues encountered across all the phases (Parser and SemanticAnalyzer) TSRefArray _Glitches; SBuildStatistics _Statistics{ .NumUsesOfExperimentalDefinitions = 0, .NumPersistentWeakMaps = 0, .NumFunctions = 0, .NumClasses = 0, .NumTopLevelDefinitions = 0 }; COnGlitchEvent _OnGlitchEvent; COnBuildStatisticEvent _OnBuildStatisticEvent; }; }