mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Added reflect method filters
This commit is contained in:
parent
f566daacea
commit
f9c0f2a311
9 changed files with 204 additions and 112 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -6042,18 +6042,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1452,12 +1452,28 @@ 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)
|
||||
|
@ -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();
|
||||
|
@ -2538,7 +2499,6 @@ 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;
|
||||
|
||||
|
|
|
@ -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<String> methodReflectFilters;
|
||||
Array<String> 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);
|
||||
}
|
||||
|
|
|
@ -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<String> mTypeFilters;
|
||||
Array<String> mAttributeFilters;
|
||||
|
@ -1298,8 +1309,8 @@ public:
|
|||
int mEmitDebugInfo;
|
||||
BfOptionFlags mAndFlags;
|
||||
BfOptionFlags mOrFlags;
|
||||
Array<String> mReflectMethodFilters;
|
||||
Array<String> mReflectMethodAttributeFilters;
|
||||
Array<MethodFilter> mReflectMethodFilters;
|
||||
Array<MethodFilter> mReflectMethodAttributeFilters;
|
||||
int mAllocStackTraceDepth;
|
||||
|
||||
public:
|
||||
|
@ -1317,6 +1328,11 @@ public:
|
|||
else
|
||||
return (mOrFlags & flags) != 0;
|
||||
}
|
||||
|
||||
bool HasReflectMethodFilters()
|
||||
{
|
||||
return !mReflectMethodFilters.IsEmpty() || !mReflectMethodAttributeFilters.IsEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
class BfSystem
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -276,6 +276,8 @@ T* ZeroedAlloc()
|
|||
return new (ZeroedAlloc(sizeof(T))) T();
|
||||
}*/
|
||||
|
||||
bool BfCheckWildcard(const StringImpl& wildcard, const StringImpl& checkStr);
|
||||
|
||||
template <typename T>
|
||||
T* PlaceNew(void* addr)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue