From f9c0f2a311720c69190041e802f952b4bc747821 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 14 Jul 2020 08:27:25 -0700 Subject: [PATCH] Added reflect method filters --- IDEHelper/Compiler/BfContext.cpp | 12 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 2 +- IDEHelper/Compiler/BfModule.cpp | 16 +-- IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 152 +++++++++-------------- IDEHelper/Compiler/BfSystem.cpp | 16 ++- IDEHelper/Compiler/BfSystem.h | 20 ++- IDEHelper/Compiler/BfUtil.cpp | 94 ++++++++++++++ IDEHelper/Compiler/BfUtil.h | 2 + 9 files changed, 204 insertions(+), 112 deletions(-) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 2a328c69..7a77fe16 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1900,10 +1900,18 @@ void BfContext::UpdateRevisedTypes() workspaceConfigHashCtx.Mixin(typeOptions.mOrFlags); workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodFilters.size()); for (auto& filter : typeOptions.mReflectMethodFilters) - workspaceConfigHashCtx.MixinStr(filter); + { + workspaceConfigHashCtx.MixinStr(filter.mFilter); + workspaceConfigHashCtx.Mixin(filter.mAndFlags); + workspaceConfigHashCtx.Mixin(filter.mOrFlags); + } workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodAttributeFilters.size()); for (auto& filter : typeOptions.mReflectMethodAttributeFilters) - workspaceConfigHashCtx.MixinStr(filter); + { + workspaceConfigHashCtx.MixinStr(filter.mFilter); + workspaceConfigHashCtx.Mixin(filter.mAndFlags); + workspaceConfigHashCtx.Mixin(filter.mOrFlags); + } workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth); } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b1006517..f790b18a 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -6932,7 +6932,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp // If we call "GetType" on a value type, statically determine the type rather than boxing and then dispatching if ((methodDef) && (target) && (curTypeInst == mModule->mContext->mBfObjectType) && - (methodDef->mName == "GetType") && (target.mType->IsValueType())) + (methodDef->mName == "GetType") && (target.mType->IsValueType()) && (argValues.mArguments->IsEmpty())) { BfType* targetType = target.mType; if (origTarget) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 2691771e..de8f97b2 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6042,19 +6042,9 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0)) includeMethod = true; - if (methodDef->mMethodType == BfMethodType_Ctor) - { - if (typeOptions != NULL) - includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectConstructors); - } - else - { - if ((!methodDef->mIsStatic) && (typeOptions != NULL)) - includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectNonStaticMethods); - if ((methodDef->mIsStatic) && (typeOptions != NULL)) - includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectStaticMethods); - } - + if ((!includeMethod) && (typeOptions != NULL)) + includeMethod = ApplyTypeOptionMethodFilters(includeMethod, methodDef, typeOptions); + if (!includeMethod) continue; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index a2a50014..07f808d2 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1604,7 +1604,7 @@ public: void CheckAddFailType(); bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data); BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef); - bool CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions* typeOptions); + bool ApplyTypeOptionMethodFilters(bool includeMethod, BfMethodDef* methodDef, BfTypeOptions* typeOptions); int GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName); void SetTypeOptions(BfTypeInstance* typeInstance); BfModuleOptions GetModuleOptions(); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 1c950cd6..e0a5558c 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -1452,18 +1452,34 @@ BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef) if (typeOptions.mEmitDebugInfo != -1) mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo; + if (typeOptions.mReflectMethodFilters.IsEmpty()) + mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags); mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags); mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags); mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags); + if (mergedTypeOptions.HasReflectMethodFilters()) + { + // If merging filter has non-default method flags but no filter then we need to append it as a filtered modification + if ((!typeOptions.HasReflectMethodFilters()) && + (((typeOptions.mAndFlags & BfOptionFlags_Reflect_MethodMask) != BfOptionFlags_Reflect_MethodMask) || + ((typeOptions.mOrFlags & BfOptionFlags_Reflect_MethodMask) != 0))) + { + mergedTypeOptions.mReflectMethodFilters.Add({"*", typeOptions.mAndFlags, typeOptions.mOrFlags}); + } + + mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | BfOptionFlags_Reflect_MethodMask); + mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & ~BfOptionFlags_Reflect_MethodMask); + } + if (typeOptions.mAllocStackTraceDepth != -1) mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth; for (auto filter : typeOptions.mReflectMethodFilters) mergedTypeOptions.mReflectMethodFilters.Add(filter); for (auto filter : typeOptions.mReflectMethodAttributeFilters) - mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter); + mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter); } matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size(); mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions); @@ -1473,9 +1489,36 @@ BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef) return mSystem->GetTypeOptions( matchedIdx); } -bool BfModule::CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions * typeOptions) +bool BfModule::ApplyTypeOptionMethodFilters(bool includeMethod, BfMethodDef* methodDef, BfTypeOptions* typeOptions) { - return true; + BfOptionFlags findFlag = BfOptionFlags_None; + if (methodDef->mMethodType == BfMethodType_Ctor) + findFlag = BfOptionFlags_ReflectConstructors; + else if (methodDef->mIsStatic) + findFlag = BfOptionFlags_ReflectStaticMethods; + else + findFlag = BfOptionFlags_ReflectNonStaticMethods; + + if ((typeOptions->mAndFlags & findFlag) == 0) + includeMethod = false; + if ((typeOptions->mOrFlags & findFlag) != 0) + includeMethod = true; + + if (!typeOptions->mReflectMethodFilters.IsEmpty()) + { + for (auto& filter : typeOptions->mReflectMethodFilters) + { + if (BfCheckWildcard(filter.mFilter, methodDef->mName)) + { + if ((filter.mAndFlags & findFlag) == 0) + includeMethod = false; + if ((filter.mAndFlags | findFlag) != 0) + includeMethod = true; + } + } + } + + return includeMethod; } int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName) @@ -1533,92 +1576,10 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn int filterIdx = 0; int typeNameIdx = 0; - const char* filterPtr = filter.c_str(); - const char* namePtr = typeName.c_str(); - - char prevFilterC = 0; - while (true) + if (BfCheckWildcard(filter, typeName)) { - char filterC; - while (true) - { - filterC = *(filterPtr++); - if (filterC != ' ') - break; - } - - char nameC; - while (true) - { - nameC = *(namePtr++); - if (nameC != ' ') - break; - } - - if ((filterC == 0) || (nameC == 0)) - { - matched = (filterC == 0) && (nameC == 0); - break; - } - - bool doWildcard = false; - - if (nameC != filterC) - { - if (filterC == '*') - doWildcard = true; - else if (((filterC == ',') || (filterC == '>')) && - ((prevFilterC == '<') || (prevFilterC == ','))) - { - doWildcard = true; - filterPtr--; - } - - if (!doWildcard) - { - matched = false; - break; - } - } - - if (doWildcard) - { - int openDepth = 0; - - const char* startNamePtr = namePtr; - - while (true) - { - nameC = *(namePtr++); - if (nameC == 0) - { - namePtr--; - if (openDepth != 0) - matched = false; - break; - } - if ((nameC == '>') && (openDepth == 0)) - { - namePtr--; - break; - } - - if (nameC == '<') - openDepth++; - else if (nameC == '>') - openDepth--; - else if ((nameC == ',') && (openDepth == 0)) - { - namePtr--; - break; - } - } - - if (!matched) - break; - } - - prevFilterC = filterC; + matched = true; + break; } } @@ -1705,9 +1666,9 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn if (typeOptions.mAllocStackTraceDepth != -1) mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth; - for (auto filter : typeOptions.mReflectMethodFilters) + for (auto& filter : typeOptions.mReflectMethodFilters) mergedTypeOptions.mReflectMethodFilters.Add(filter); - for (auto filter : typeOptions.mReflectMethodAttributeFilters) + for (auto& filter : typeOptions.mReflectMethodAttributeFilters) mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter); } matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size(); @@ -2537,8 +2498,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy { auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx); if (typeOptions != NULL) - { - typeInstance->mIncludeAllMethods = typeOptions->Apply(typeInstance->mIncludeAllMethods, BfOptionFlags_ReflectAlwaysIncludeAll); + { typeInstance->mHasBeenInstantiated = typeOptions->Apply(typeInstance->mHasBeenInstantiated, BfOptionFlags_ReflectAssumeInstantiated); } } @@ -3896,6 +3856,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) isFailedType = true; } + bool typeOptionsIncludeAll = false; + if (typeOptions != NULL) + typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll); + // Generate all methods. Pass 1 for (auto methodDef : typeDef->mMethods) { @@ -3997,6 +3961,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } if (typeInstance->mIncludeAllMethods) implRequired = true; + + if ((typeOptionsIncludeAll) && (ApplyTypeOptionMethodFilters(true, methodDef, typeOptions))) + implRequired = true; + // if ((typeOptions != NULL) && (CheckTypeOptionMethodFilters(typeOptions, methodDef))) // implRequired = true; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index e67ce1c8..b7b7fc8d 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -3666,7 +3666,21 @@ BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* fil typeOptions.mOrFlags = (BfOptionFlags)orFlags; typeOptions.mAllocStackTraceDepth = allocStackTraceDepth; - _ParseFilters(reflectMethodFilter, typeOptions.mReflectMethodFilters, typeOptions.mReflectMethodAttributeFilters); + Array methodReflectFilters; + Array methodReflectAttributeFilters; + + _ParseFilters(reflectMethodFilter, methodReflectFilters, methodReflectAttributeFilters); + // When we have method filters we want to apply those to the methods for when we merge options + if ((!methodReflectFilters.IsEmpty()) || (!methodReflectAttributeFilters.IsEmpty())) + { + for (auto& filter : methodReflectFilters) + typeOptions.mReflectMethodFilters.Add({ filter, (BfOptionFlags)andFlags, (BfOptionFlags)orFlags }); + for (auto& filter : methodReflectAttributeFilters) + typeOptions.mReflectMethodAttributeFilters.Add({ filter, (BfOptionFlags)andFlags, (BfOptionFlags)orFlags }); + + typeOptions.mAndFlags = (BfOptionFlags)(typeOptions.mAndFlags | BfOptionFlags_Reflect_MethodMask); + typeOptions.mOrFlags = (BfOptionFlags)(typeOptions.mOrFlags & ~BfOptionFlags_Reflect_MethodMask); + } bfSystem->mTypeOptions.push_back(typeOptions); } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 0f6289d4..dbb3c862 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1285,10 +1285,21 @@ enum BfOptionFlags BfOptionFlags_ReflectNonStaticMethods = 0x400, BfOptionFlags_ReflectConstructors = 0x800, + BfOptionFlags_Reflect_MethodMask = BfOptionFlags_ReflectStaticMethods | BfOptionFlags_ReflectNonStaticMethods | BfOptionFlags_ReflectConstructors, + BfOptionFlags_Mask = 0xFFF + }; class BfTypeOptions { +public: + struct MethodFilter + { + String mFilter; + BfOptionFlags mOrFlags; + BfOptionFlags mAndFlags; + }; + public: Array mTypeFilters; Array mAttributeFilters; @@ -1298,8 +1309,8 @@ public: int mEmitDebugInfo; BfOptionFlags mAndFlags; BfOptionFlags mOrFlags; - Array mReflectMethodFilters; - Array mReflectMethodAttributeFilters; + Array mReflectMethodFilters; + Array mReflectMethodAttributeFilters; int mAllocStackTraceDepth; public: @@ -1317,6 +1328,11 @@ public: else return (mOrFlags & flags) != 0; } + + bool HasReflectMethodFilters() + { + return !mReflectMethodFilters.IsEmpty() || !mReflectMethodAttributeFilters.IsEmpty(); + } }; class BfSystem diff --git a/IDEHelper/Compiler/BfUtil.cpp b/IDEHelper/Compiler/BfUtil.cpp index ee415512..5998105f 100644 --- a/IDEHelper/Compiler/BfUtil.cpp +++ b/IDEHelper/Compiler/BfUtil.cpp @@ -60,3 +60,97 @@ uint64 stouln(const char* str, int len) } return val; } + +bool Beefy::BfCheckWildcard(const StringImpl& wildcard, const StringImpl& checkStr) +{ + bool matched = true; + const char* filterPtr = wildcard.c_str(); + const char* namePtr = checkStr.c_str(); + + char prevFilterC = 0; + while (true) + { + char filterC; + while (true) + { + filterC = *(filterPtr++); + if (filterC != ' ') + break; + } + + char nameC; + while (true) + { + nameC = *(namePtr++); + if (nameC != ' ') + break; + } + + if ((filterC == 0) || (nameC == 0)) + { + matched = (filterC == 0) && (nameC == 0); + break; + } + + bool doWildcard = false; + + if (nameC != filterC) + { + if (filterC == '*') + doWildcard = true; + else if (((filterC == ',') || (filterC == '>')) && + ((prevFilterC == '<') || (prevFilterC == ','))) + { + doWildcard = true; + filterPtr--; + } + + if (!doWildcard) + { + matched = false; + break; + } + } + + if (doWildcard) + { + int openDepth = 0; + + const char* startNamePtr = namePtr; + + while (true) + { + nameC = *(namePtr++); + if (nameC == 0) + { + namePtr--; + if (openDepth != 0) + matched = false; + break; + } + if ((nameC == '>') && (openDepth == 0)) + { + namePtr--; + break; + } + + if (nameC == '<') + openDepth++; + else if (nameC == '>') + openDepth--; + else if ((nameC == ',') && (openDepth == 0)) + { + namePtr--; + break; + } + } + + if (!matched) + break; + } + + prevFilterC = filterC; + } + + return matched; +} \ No newline at end of file diff --git a/IDEHelper/Compiler/BfUtil.h b/IDEHelper/Compiler/BfUtil.h index 393564c5..7232c4bf 100644 --- a/IDEHelper/Compiler/BfUtil.h +++ b/IDEHelper/Compiler/BfUtil.h @@ -276,6 +276,8 @@ T* ZeroedAlloc() return new (ZeroedAlloc(sizeof(T))) T(); }*/ +bool BfCheckWildcard(const StringImpl& wildcard, const StringImpl& checkStr); + template T* PlaceNew(void* addr) {