mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Added 'using' fields
This commit is contained in:
parent
ff229f385d
commit
450d541292
13 changed files with 850 additions and 253 deletions
|
@ -857,13 +857,13 @@ void BfAutoComplete::AddProp(BfTypeInstance* typeInst, BfPropertyDef* propDef, c
|
||||||
if (methodDef->mMethodType == BfMethodType_PropertyGetter)
|
if (methodDef->mMethodType == BfMethodType_PropertyGetter)
|
||||||
{
|
{
|
||||||
hasGetter = true;
|
hasGetter = true;
|
||||||
propType = methodInstance->mReturnType;
|
propType = methodInstance->mReturnType;
|
||||||
}
|
}
|
||||||
if (methodDef->mMethodType == BfMethodType_PropertySetter)
|
if (methodDef->mMethodType == BfMethodType_PropertySetter)
|
||||||
{
|
{
|
||||||
hasSetter = true;
|
hasSetter = true;
|
||||||
if (methodInstance->GetParamCount() > 0)
|
if (methodInstance->GetParamCount() > 0)
|
||||||
propType = methodInstance->GetParamType(0);
|
propType = methodInstance->GetParamType(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,6 +1024,63 @@ void BfAutoComplete::AddTypeMembers(BfTypeInstance* typeInst, bool addStatic, bo
|
||||||
AddTypeMembers(outerType, true, false, filter, startType, false, allowImplicitThis, false);
|
AddTypeMembers(outerType, true, false, filter, startType, false, allowImplicitThis, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((typeInst->mTypeDef->mHasUsingFields) &&
|
||||||
|
((typeInst->mTypeInfoEx == NULL) || (typeInst->mTypeInfoEx->mUsingFieldData == NULL)))
|
||||||
|
mModule->PopulateUsingFieldData(typeInst);
|
||||||
|
|
||||||
|
if ((typeInst->mTypeInfoEx != NULL) && (typeInst->mTypeInfoEx->mUsingFieldData != NULL))
|
||||||
|
{
|
||||||
|
for (int pass = 0; pass < 2; pass++)
|
||||||
|
{
|
||||||
|
auto& dict = (pass == 0) ? typeInst->mTypeInfoEx->mUsingFieldData->mEntries : typeInst->mTypeInfoEx->mUsingFieldData->mMethods;
|
||||||
|
for (auto& entryKV : dict)
|
||||||
|
{
|
||||||
|
for (auto& entryList : entryKV.mValue.mLookups)
|
||||||
|
{
|
||||||
|
auto& endEntry = entryList.back();
|
||||||
|
|
||||||
|
bool isStatic = endEntry.IsStatic();
|
||||||
|
if ((isStatic) && (!addStatic))
|
||||||
|
continue;
|
||||||
|
if ((!isStatic) && (!addNonStatic))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool passesProtection = true;
|
||||||
|
for (int entryIdx = 0; entryIdx < entryList.mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
auto& entry = entryList[entryIdx];
|
||||||
|
if (!mModule->CheckProtection(protectionCheckFlags, entry.mTypeInstance, entry.GetDeclaringType(mModule)->mProject,
|
||||||
|
(entryIdx < entryList.mSize - 1) ? entry.GetUsingProtection() : entry.GetProtection(), typeInst))
|
||||||
|
{
|
||||||
|
passesProtection = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!passesProtection)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (endEntry.mKind)
|
||||||
|
{
|
||||||
|
case BfUsingFieldData::MemberRef::Kind_Field:
|
||||||
|
if (endEntry.mTypeInstance->mDefineState < BfTypeDefineState_Defined)
|
||||||
|
mModule->PopulateType(endEntry.mTypeInstance);
|
||||||
|
AddField(endEntry.mTypeInstance, endEntry.mTypeInstance->mTypeDef->mFields[endEntry.mIdx], &endEntry.mTypeInstance->mFieldInstances[endEntry.mIdx], filter);
|
||||||
|
break;
|
||||||
|
case BfUsingFieldData::MemberRef::Kind_Property:
|
||||||
|
AddProp(endEntry.mTypeInstance, endEntry.mTypeInstance->mTypeDef->mProperties[endEntry.mIdx], filter);
|
||||||
|
break;
|
||||||
|
case BfUsingFieldData::MemberRef::Kind_Method:
|
||||||
|
{
|
||||||
|
auto methodDef = endEntry.mTypeInstance->mTypeDef->mMethods[endEntry.mIdx];
|
||||||
|
AddMethod(endEntry.mTypeInstance, methodDef, NULL, methodDef->GetMethodDeclaration(), methodDef->mName, filter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeInstance* selfType, const StringImpl& filter, bool allowPrivate)
|
void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeInstance* selfType, const StringImpl& filter, bool allowPrivate)
|
||||||
|
@ -3866,3 +3923,27 @@ void BfAutoComplete::SetResultStringType(BfType * type)
|
||||||
else
|
else
|
||||||
mResultString += "\n:type\tvaluetype";
|
mResultString += "\n:type\tvaluetype";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfAutoComplete::FixitAddFullyQualify(BfAstNode* refNode, const StringImpl& findName, const SizedArrayImpl<BfUsingFieldData::MemberRef>& foundList)
|
||||||
|
{
|
||||||
|
BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None;
|
||||||
|
String fullName;
|
||||||
|
for (int entryIdx = 0; entryIdx < foundList.mSize - 1; entryIdx++)
|
||||||
|
{
|
||||||
|
auto& entry = foundList[entryIdx];
|
||||||
|
if (entryIdx > 0)
|
||||||
|
fullName += ".";
|
||||||
|
if (!mModule->CheckProtection(protectionCheckFlags, entry.mTypeInstance, entry.GetDeclaringType(mModule)->mProject, entry.GetProtection(), mModule->mCurTypeInstance))
|
||||||
|
fullName += "[Friend]";
|
||||||
|
fullName += entry.GetName(mModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
BfParserData* parser = refNode->GetSourceData()->ToParserData();
|
||||||
|
if (parser != NULL)
|
||||||
|
{
|
||||||
|
AddEntry(AutoCompleteEntry("fixit", StrFormat("Fully qualify 'using' name as '%s.%s'\tqualify|%s|%d|%s.",
|
||||||
|
fullName.c_str(), findName.c_str(),
|
||||||
|
parser->mFileName.c_str(), refNode->mSrcStart,
|
||||||
|
fullName.c_str()).c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -277,6 +277,7 @@ public:
|
||||||
void FixitAddNamespace(BfAstNode* refNode, const StringImpl& namespacStr);
|
void FixitAddNamespace(BfAstNode* refNode, const StringImpl& namespacStr);
|
||||||
void FixitCheckNamespace(BfTypeDef* activeTypeDef, BfAstNode* typeRef, BfTokenNode* nextDotToken);
|
void FixitCheckNamespace(BfTypeDef* activeTypeDef, BfAstNode* typeRef, BfTokenNode* nextDotToken);
|
||||||
void FixitAddConstructor(BfTypeInstance* typeInstance);
|
void FixitAddConstructor(BfTypeInstance* typeInstance);
|
||||||
|
void FixitAddFullyQualify(BfAstNode* refNode, const StringImpl& findName, const SizedArrayImpl<BfUsingFieldData::MemberRef>& foundList);
|
||||||
|
|
||||||
void SetResultStringType(BfType* type);
|
void SetResultStringType(BfType* type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,6 +163,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMetho
|
||||||
void BfMethodMatcher::Init(const BfMethodGenericArguments& methodGenericArguments)
|
void BfMethodMatcher::Init(const BfMethodGenericArguments& methodGenericArguments)
|
||||||
{
|
{
|
||||||
//mArguments = arguments;
|
//mArguments = arguments;
|
||||||
|
mUsingLists = NULL;
|
||||||
mActiveTypeDef = NULL;
|
mActiveTypeDef = NULL;
|
||||||
mBestMethodDef = NULL;
|
mBestMethodDef = NULL;
|
||||||
mBackupMethodDef = NULL;
|
mBackupMethodDef = NULL;
|
||||||
|
@ -2642,7 +2643,7 @@ bool BfMethodMatcher::IsType(BfTypedValue& typedVal, BfType* type)
|
||||||
// This method checks all base classes before checking interfaces. Is that correct?
|
// This method checks all base classes before checking interfaces. Is that correct?
|
||||||
bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck)
|
bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck)
|
||||||
{
|
{
|
||||||
BfMethodDef* prevBesstMethodDef = mBestMethodDef;
|
BfMethodDef* prevBestMethodDef = mBestMethodDef;
|
||||||
auto curTypeInst = typeInstance;
|
auto curTypeInst = typeInstance;
|
||||||
auto curTypeDef = typeInstance->mTypeDef;
|
auto curTypeDef = typeInstance->mTypeDef;
|
||||||
|
|
||||||
|
@ -2812,12 +2813,96 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mBestMethodDef != NULL) && (mMethodType != BfMethodType_Extension))
|
if ((mBestMethodDef != NULL) && (mMethodType != BfMethodType_Extension))
|
||||||
{
|
{
|
||||||
|
if ((mUsingLists != NULL) && (mUsingLists->mSize != 0))
|
||||||
|
mUsingLists->Clear();
|
||||||
|
|
||||||
if (mAutoFlushAmbiguityErrors)
|
if (mAutoFlushAmbiguityErrors)
|
||||||
FlushAmbiguityError();
|
FlushAmbiguityError();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mUsingLists != NULL) && (curTypeInst->mTypeDef->mHasUsingFields) &&
|
||||||
|
((curTypeInst->mTypeInfoEx == NULL) || (curTypeInst->mTypeInfoEx->mUsingFieldData == NULL)))
|
||||||
|
mModule->PopulateUsingFieldData(curTypeInst);
|
||||||
|
|
||||||
|
if (mUsingLists != NULL)
|
||||||
|
{
|
||||||
|
auto _CheckUsingData = [&](BfUsingFieldData* usingData)
|
||||||
|
{
|
||||||
|
BfUsingFieldData::Entry* entry = NULL;
|
||||||
|
if (!usingData->mMethods.TryGetValue(mMethodName, &entry))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int listIdx = 0; listIdx < entry->mLookups.mSize; listIdx++)
|
||||||
|
{
|
||||||
|
bool passesProtection = true;
|
||||||
|
auto& entryList = entry->mLookups[listIdx];
|
||||||
|
for (int entryIdx = 0; entryIdx < entryList.mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
auto& entry = entryList[entryIdx];
|
||||||
|
if (!mModule->CheckProtection(protectionCheckFlags, entry.mTypeInstance, entry.GetDeclaringType(mModule)->mProject,
|
||||||
|
(entryIdx < entryList.mSize - 1) ? entry.GetUsingProtection() : entry.GetProtection(), curTypeInst))
|
||||||
|
{
|
||||||
|
passesProtection = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!passesProtection)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto& entry = entryList.back();
|
||||||
|
BF_ASSERT(entry.mKind == BfUsingFieldData::MemberRef::Kind_Method);
|
||||||
|
auto methodDef = entry.mTypeInstance->mTypeDef->mMethods[entry.mIdx];
|
||||||
|
CheckMethod(curTypeInst, entry.mTypeInstance, methodDef, isFailurePass);
|
||||||
|
if ((mBestMethodDef != methodDef) && (mBackupMethodDef != methodDef))
|
||||||
|
{
|
||||||
|
bool foundAmbiguous = false;
|
||||||
|
for (int checkIdx = 0; checkIdx < mAmbiguousEntries.mSize; checkIdx++)
|
||||||
|
{
|
||||||
|
if (mAmbiguousEntries[checkIdx].mMethodInstance->mMethodDef == methodDef)
|
||||||
|
{
|
||||||
|
mAmbiguousEntries.RemoveAt(checkIdx);
|
||||||
|
foundAmbiguous = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundAmbiguous)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUsingLists->mSize == 0)
|
||||||
|
{
|
||||||
|
mUsingLists->Add(&entryList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (entryList.mSize < (*mUsingLists)[0]->mSize)
|
||||||
|
{
|
||||||
|
// New is shorter
|
||||||
|
mUsingLists->Clear();
|
||||||
|
mUsingLists->Add(&entryList);
|
||||||
|
}
|
||||||
|
else if (entryList.mSize > (*mUsingLists)[0]->mSize)
|
||||||
|
{
|
||||||
|
// Ignore longer
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mUsingLists->Add(&entryList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((curTypeInst->mTypeInfoEx != NULL) && (curTypeInst->mTypeInfoEx->mUsingFieldData != NULL))
|
||||||
|
_CheckUsingData(curTypeInst->mTypeInfoEx->mUsingFieldData);
|
||||||
|
|
||||||
|
if (mBestMethodDef != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto baseType = curTypeInst->mBaseType;
|
auto baseType = curTypeInst->mBaseType;
|
||||||
if (baseType == NULL)
|
if (baseType == NULL)
|
||||||
{
|
{
|
||||||
|
@ -2867,7 +2952,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
|
||||||
if (mAutoFlushAmbiguityErrors)
|
if (mAutoFlushAmbiguityErrors)
|
||||||
FlushAmbiguityError();
|
FlushAmbiguityError();
|
||||||
|
|
||||||
return mBestMethodDef != prevBesstMethodDef;
|
return mBestMethodDef != prevBestMethodDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget, BfTypedValue* staticResult)
|
void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget, BfTypedValue* staticResult)
|
||||||
|
@ -4879,7 +4964,7 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resolvePassData = mModule->mCompiler->mResolvePassData;
|
auto resolvePassData = mModule->mCompiler->mResolvePassData;
|
||||||
if ((resolvePassData != NULL) && (resolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field))
|
if ((resolvePassData != NULL) && (resolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field) && ((flags & BfLookupFieldFlag_IsAnonymous) == 0))
|
||||||
{
|
{
|
||||||
resolvePassData->HandleFieldReference(targetSrc, typeInstance->mTypeDef, fieldDef);
|
resolvePassData->HandleFieldReference(targetSrc, typeInstance->mTypeDef, fieldDef);
|
||||||
}
|
}
|
||||||
|
@ -5620,187 +5705,140 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
||||||
return LoadProperty(targetSrc, target, curCheckType, matchedProp, flags, checkedKind, isInlined);
|
return LoadProperty(targetSrc, target, curCheckType, matchedProp, flags, checkedKind, isInlined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curCheckType->mTypeDef->mHasUsingFields) && ((flags & BfLookupFieldFlag_BindOnly) == 0))
|
if ((curCheckType->mTypeDef->mHasUsingFields) &&
|
||||||
|
((curCheckType->mTypeInfoEx == NULL) || (curCheckType->mTypeInfoEx->mUsingFieldData == NULL)))
|
||||||
|
mModule->PopulateUsingFieldData(curCheckType);
|
||||||
|
|
||||||
|
///
|
||||||
{
|
{
|
||||||
auto usingFieldData = curCheckType->mTypeDef->mUsingFieldData;
|
Array<SizedArray<BfUsingFieldData::MemberRef, 1>*> foundLists;
|
||||||
|
|
||||||
BfUsingFieldData::Entry* usingEntry = NULL;
|
auto _CheckUsingData = [&](BfUsingFieldData* usingData)
|
||||||
if (usingFieldData->mEntries.TryAdd(findName, NULL, &usingEntry))
|
|
||||||
{
|
{
|
||||||
HashSet<BfTypeInstance*> checkedTypeSet;
|
BfUsingFieldData::Entry* entry = NULL;
|
||||||
BfUsingFieldData::FieldRef firstFoundField;
|
if (!usingData->mEntries.TryGetValue(findName, &entry))
|
||||||
|
return;
|
||||||
|
|
||||||
std::function<bool(BfTypeInstance*)> _CheckTypeDef = [&](BfTypeInstance* usingType)
|
for (int listIdx = 0; listIdx < entry->mLookups.mSize; listIdx++)
|
||||||
{
|
{
|
||||||
if (!checkedTypeSet.Add(usingType))
|
bool passesProtection = true;
|
||||||
return false;
|
auto& entryList = entry->mLookups[listIdx];
|
||||||
|
for (int entryIdx = 0; entryIdx < entryList.mSize; entryIdx++)
|
||||||
BfFieldDef* matchedField = NULL;
|
|
||||||
BfTypeInstance* matchedTypeInst = NULL;
|
|
||||||
|
|
||||||
if (curCheckType != usingType)
|
|
||||||
{
|
{
|
||||||
auto curUsingType = usingType;
|
auto& entry = entryList[entryIdx];
|
||||||
while (curUsingType != NULL)
|
if (!mModule->CheckProtection(protectionCheckFlags, entry.mTypeInstance, entry.GetDeclaringType(mModule)->mProject,
|
||||||
|
(entryIdx < entryList.mSize - 1) ? entry.GetUsingProtection() : entry.GetProtection(), curCheckType))
|
||||||
{
|
{
|
||||||
curUsingType->mTypeDef->PopulateMemberSets();
|
passesProtection = false;
|
||||||
|
break;
|
||||||
BfFieldDef* nextField = NULL;
|
|
||||||
BfMemberSetEntry* entry;
|
|
||||||
if (curUsingType->mTypeDef->mFieldSet.TryGetWith(findName, &entry))
|
|
||||||
nextField = (BfFieldDef*)entry->mMemberDef;
|
|
||||||
|
|
||||||
while (nextField != NULL)
|
|
||||||
{
|
|
||||||
auto field = nextField;
|
|
||||||
nextField = nextField->mNextWithSameName;
|
|
||||||
|
|
||||||
if (!mModule->CheckProtection(protectionCheckFlags, curUsingType, field->mDeclaringType->mProject, field->mProtection, usingType))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
matchedTypeInst = curUsingType;
|
|
||||||
matchedField = field;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchedField == NULL)
|
|
||||||
{
|
|
||||||
BfPropertyDef* nextProp = NULL;
|
|
||||||
if (curUsingType->mTypeDef->mPropertySet.TryGetWith(findName, &entry))
|
|
||||||
nextProp = (BfPropertyDef*)entry->mMemberDef;
|
|
||||||
while (nextProp != NULL)
|
|
||||||
{
|
|
||||||
auto propDef = nextProp;
|
|
||||||
nextProp = nextProp->mNextWithSameName;
|
|
||||||
|
|
||||||
if (!mModule->CheckProtection(protectionCheckFlags, curUsingType, propDef->mDeclaringType->mProject, propDef->mProtection, usingType))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
matchedTypeInst = curUsingType;
|
|
||||||
matchedField = propDef;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchedField != NULL)
|
|
||||||
{
|
|
||||||
if (firstFoundField.mTypeInstance == NULL)
|
|
||||||
{
|
|
||||||
firstFoundField = BfUsingFieldData::FieldRef(curUsingType, matchedField);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usingEntry->mConflicts.Add(firstFoundField);
|
|
||||||
usingEntry->mConflicts.Add(BfUsingFieldData::FieldRef(curUsingType, matchedField));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
curUsingType = curUsingType->mBaseType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto curUsingType = usingType;
|
|
||||||
while (curUsingType != NULL)
|
|
||||||
{
|
|
||||||
if (curUsingType->mTypeDef->mUsingFieldData != NULL)
|
|
||||||
{
|
|
||||||
for (auto fieldDef : curUsingType->mTypeDef->mUsingFieldData->mUsingFields)
|
|
||||||
{
|
|
||||||
if (!mModule->CheckProtection(protectionCheckFlags, curUsingType, fieldDef->mDeclaringType->mProject, fieldDef->mUsingProtection, usingType))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fieldDef->mIsProperty)
|
|
||||||
{
|
|
||||||
auto propDef = (BfPropertyDef*)fieldDef;
|
|
||||||
for (auto methodDef : propDef->mMethods)
|
|
||||||
{
|
|
||||||
if (methodDef->mMethodType == BfMethodType_PropertyGetter)
|
|
||||||
{
|
|
||||||
auto methodInstance = mModule->GetRawMethodInstance(curUsingType, methodDef);
|
|
||||||
if (methodInstance == NULL)
|
|
||||||
continue;
|
|
||||||
BfType* returnType = methodInstance->mReturnType;
|
|
||||||
if ((returnType->IsRef()) || (returnType->IsPointer()))
|
|
||||||
returnType = returnType->GetUnderlyingType();
|
|
||||||
auto fieldTypeInst = returnType->ToTypeInstance();
|
|
||||||
if ((fieldTypeInst != NULL) && (_CheckTypeDef(fieldTypeInst)))
|
|
||||||
usingEntry->mLookup.Insert(0, BfUsingFieldData::FieldRef(curUsingType, fieldDef));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (curUsingType->mFieldInstances.IsEmpty())
|
|
||||||
mModule->PopulateType(curCheckType, BfPopulateType_Data);
|
|
||||||
BF_ASSERT(fieldDef->mIdx < (int)curUsingType->mFieldInstances.size());
|
|
||||||
auto fieldInstance = &curUsingType->mFieldInstances[fieldDef->mIdx];
|
|
||||||
if (!fieldInstance->mFieldIncluded)
|
|
||||||
continue;
|
|
||||||
auto fieldType = fieldInstance->mResolvedType;
|
|
||||||
if (fieldType->IsPointer())
|
|
||||||
fieldType = fieldType->GetUnderlyingType();
|
|
||||||
auto fieldTypeInst = fieldType->ToTypeInstance();
|
|
||||||
if ((fieldTypeInst != NULL) && (_CheckTypeDef(fieldTypeInst)))
|
|
||||||
usingEntry->mLookup.Insert(0, BfUsingFieldData::FieldRef(curUsingType, fieldDef));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
curUsingType = curUsingType->mBaseType;
|
|
||||||
}
|
}
|
||||||
|
if (!passesProtection)
|
||||||
if ((matchedField != NULL) && (usingEntry->mLookup.IsEmpty()))
|
continue;
|
||||||
|
|
||||||
|
if (foundLists.mSize == 0)
|
||||||
{
|
{
|
||||||
usingEntry->mLookup.Add(BfUsingFieldData::FieldRef(matchedTypeInst, matchedField));
|
foundLists.Add(&entryList);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return false;
|
|
||||||
};
|
|
||||||
_CheckTypeDef(curCheckType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!usingEntry->mConflicts.IsEmpty()) && (mModule->PreFail()))
|
|
||||||
{
|
|
||||||
BfError* error = mModule->Fail("Ambiguous 'using' field reference", targetSrc);
|
|
||||||
if (error != NULL)
|
|
||||||
{
|
|
||||||
for (auto& conflict : usingEntry->mConflicts)
|
|
||||||
{
|
{
|
||||||
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s.%s' is a candidate", mModule->TypeToString(conflict.mTypeInstance).c_str(), conflict.mFieldDef->mName.c_str()), conflict.mFieldDef->GetRefNode());
|
if (entryList.mSize < foundLists[0]->mSize)
|
||||||
|
{
|
||||||
|
// New is shorter
|
||||||
|
foundLists.Clear();
|
||||||
|
foundLists.Add(&entryList);
|
||||||
|
}
|
||||||
|
else if (entryList.mSize > foundLists[0]->mSize)
|
||||||
|
{
|
||||||
|
// Ignore longer
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundLists.Add(&entryList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if (!usingEntry->mLookup.IsEmpty())
|
if ((curCheckType->mTypeInfoEx != NULL) && (curCheckType->mTypeInfoEx->mUsingFieldData != NULL))
|
||||||
|
_CheckUsingData(curCheckType->mTypeInfoEx->mUsingFieldData);
|
||||||
|
|
||||||
|
if (!foundLists.IsEmpty())
|
||||||
{
|
{
|
||||||
auto initialFieldDef = usingEntry->mLookup[0].mFieldDef;
|
auto foundList = foundLists[0];
|
||||||
if ((initialFieldDef->mIsStatic == target.IsStatic()) &&
|
|
||||||
(mModule->CheckProtection(protectionCheckFlags, curCheckType, initialFieldDef->mDeclaringType->mProject, initialFieldDef->mUsingProtection, startCheckType)))
|
|
||||||
{
|
|
||||||
BfTypeInstance* curTypeInst = curCheckType;
|
|
||||||
BfTypedValue curResult = target;
|
|
||||||
for (int i = 0; i < usingEntry->mLookup.mSize; i++)
|
|
||||||
{
|
|
||||||
auto& fieldRef = usingEntry->mLookup[i];
|
|
||||||
if (mPropDef != NULL)
|
|
||||||
{
|
|
||||||
SetAndRestoreValue<BfTypedValue> prevResult(mResult, BfTypedValue());
|
|
||||||
mPropGetMethodFlags = (BfGetMethodInstanceFlags)(mPropGetMethodFlags | BfGetMethodInstanceFlag_Friend);
|
|
||||||
curResult = GetResult();
|
|
||||||
if (!curResult)
|
|
||||||
return curResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto useFlags = flags;
|
if (foundLists.mSize > 1)
|
||||||
if (i < usingEntry->mLookup.mSize - 1)
|
{
|
||||||
useFlags = (BfLookupFieldFlags)(flags | BfLookupFieldFlag_IsAnonymous);
|
BfError* error = mModule->Fail("Ambiguous 'using' field reference", targetSrc);
|
||||||
curResult = LoadField(targetSrc, curResult, fieldRef.mTypeInstance, fieldRef.mFieldDef, useFlags);
|
if (error != NULL)
|
||||||
if ((!curResult) && (mPropDef == NULL))
|
{
|
||||||
|
for (auto checkList : foundLists)
|
||||||
|
{
|
||||||
|
String errorStr = "'";
|
||||||
|
for (int entryIdx = 0; entryIdx < checkList->mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
if (entryIdx == 0)
|
||||||
|
errorStr += (*checkList)[entryIdx].GetFullName(mModule);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr += ".";
|
||||||
|
errorStr += (*checkList)[entryIdx].GetName(mModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorStr += "' is a candidate";
|
||||||
|
mModule->mCompiler->mPassInstance->MoreInfo(errorStr, (*checkList)[0].GetRefNode(mModule));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypedValue curResult = target;
|
||||||
|
for (int entryIdx = 0; entryIdx < foundList->mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
if ((entryIdx == 0) && (foundList->back().IsStatic()))
|
||||||
|
entryIdx = (int)foundList->mSize - 1;
|
||||||
|
|
||||||
|
auto& entry = (*foundList)[entryIdx];
|
||||||
|
if (mPropDef != NULL)
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<BfTypedValue> prevResult(mResult, BfTypedValue());
|
||||||
|
mPropGetMethodFlags = (BfGetMethodInstanceFlags)(mPropGetMethodFlags | BfGetMethodInstanceFlag_Friend);
|
||||||
|
curResult = GetResult();
|
||||||
|
if (!curResult)
|
||||||
return curResult;
|
return curResult;
|
||||||
}
|
}
|
||||||
return curResult;
|
|
||||||
|
auto useFlags = flags;
|
||||||
|
if (entryIdx < foundList->mSize - 1)
|
||||||
|
useFlags = (BfLookupFieldFlags)(flags | BfLookupFieldFlag_IsAnonymous);
|
||||||
|
|
||||||
|
if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Field)
|
||||||
|
{
|
||||||
|
curResult = LoadField(targetSrc, curResult, entry.mTypeInstance, entry.mTypeInstance->mTypeDef->mFields[entry.mIdx], useFlags);
|
||||||
|
}
|
||||||
|
else if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Property)
|
||||||
|
{
|
||||||
|
curResult = LoadProperty(targetSrc, curResult, entry.mTypeInstance, entry.mTypeInstance->mTypeDef->mProperties[entry.mIdx], useFlags, BfCheckedKind_NotSet, false);
|
||||||
|
}
|
||||||
|
else if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Local)
|
||||||
|
{
|
||||||
|
auto localDef = mModule->mCurMethodState->mLocals[entry.mIdx];
|
||||||
|
curResult = LoadLocal(localDef);
|
||||||
|
}
|
||||||
|
if ((!curResult) && (mPropDef == NULL))
|
||||||
|
return curResult;
|
||||||
|
|
||||||
|
if (entryIdx == foundList->mSize - 1)
|
||||||
|
{
|
||||||
|
auto autoComplete = GetAutoComplete();
|
||||||
|
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(targetSrc)))
|
||||||
|
autoComplete->SetDefinitionLocation(entry.GetRefNode(mModule));
|
||||||
|
|
||||||
|
if ((autoComplete != NULL) && (autoComplete->CheckFixit(targetSrc)))
|
||||||
|
autoComplete->FixitAddFullyQualify(targetSrc, findName, *foundList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return curResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9412,7 +9450,9 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
|
|
||||||
BfTypeInstance* curTypeInst = targetTypeInst;
|
BfTypeInstance* curTypeInst = targetTypeInst;
|
||||||
|
|
||||||
|
Array<SizedArray<BfUsingFieldData::MemberRef, 1>*> methodUsingLists;
|
||||||
BfMethodMatcher methodMatcher(targetSrc, mModule, methodName, argValues.mResolvedArgs, methodGenericArgs);
|
BfMethodMatcher methodMatcher(targetSrc, mModule, methodName, argValues.mResolvedArgs, methodGenericArgs);
|
||||||
|
methodMatcher.mUsingLists = &methodUsingLists;
|
||||||
methodMatcher.mOrigTarget = origTarget;
|
methodMatcher.mOrigTarget = origTarget;
|
||||||
methodMatcher.mTarget = target;
|
methodMatcher.mTarget = target;
|
||||||
methodMatcher.mCheckedKind = checkedKind;
|
methodMatcher.mCheckedKind = checkedKind;
|
||||||
|
@ -9581,7 +9621,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
if (lookupTypeInst != NULL)
|
if (lookupTypeInst != NULL)
|
||||||
methodMatcher.CheckType(lookupTypeInst, target, true);
|
methodMatcher.CheckType(lookupTypeInst, target, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypedValue staticResult;
|
BfTypedValue staticResult;
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
|
@ -9605,6 +9645,96 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
target = mModule->GetThis();
|
target = mModule->GetThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!methodUsingLists.IsEmpty())
|
||||||
|
{
|
||||||
|
auto foundList = methodUsingLists[0];
|
||||||
|
|
||||||
|
if (methodUsingLists.mSize > 1)
|
||||||
|
{
|
||||||
|
BfError* error = mModule->Fail("Ambiguous 'using' method reference", targetSrc);
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
for (auto checkList : methodUsingLists)
|
||||||
|
{
|
||||||
|
String errorStr = "'";
|
||||||
|
for (int entryIdx = 0; entryIdx < checkList->mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
if (entryIdx == 0)
|
||||||
|
errorStr += (*checkList)[entryIdx].GetFullName(mModule);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorStr += ".";
|
||||||
|
errorStr += (*checkList)[entryIdx].GetName(mModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorStr += "' is a candidate";
|
||||||
|
mModule->mCompiler->mPassInstance->MoreInfo(errorStr, (*checkList)[0].GetRefNode(mModule));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypedValue curResult = target;
|
||||||
|
for (int entryIdx = 0; entryIdx < foundList->mSize; entryIdx++)
|
||||||
|
{
|
||||||
|
if ((entryIdx == 0) && (foundList->back().IsStatic()))
|
||||||
|
entryIdx = (int)foundList->mSize - 1;
|
||||||
|
|
||||||
|
auto& entry = (*foundList)[entryIdx];
|
||||||
|
if (mPropDef != NULL)
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<BfTypedValue> prevResult(mResult, BfTypedValue());
|
||||||
|
mPropGetMethodFlags = (BfGetMethodInstanceFlags)(mPropGetMethodFlags | BfGetMethodInstanceFlag_Friend);
|
||||||
|
curResult = GetResult();
|
||||||
|
if (!curResult)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto useFlags = BfLookupFieldFlag_None;
|
||||||
|
if (entryIdx < foundList->mSize - 1)
|
||||||
|
useFlags = (BfLookupFieldFlags)(useFlags | BfLookupFieldFlag_IsAnonymous);
|
||||||
|
|
||||||
|
if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Field)
|
||||||
|
{
|
||||||
|
curResult = LoadField(targetSrc, curResult, entry.mTypeInstance, entry.mTypeInstance->mTypeDef->mFields[entry.mIdx], useFlags);
|
||||||
|
}
|
||||||
|
else if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Property)
|
||||||
|
{
|
||||||
|
curResult = LoadProperty(targetSrc, curResult, entry.mTypeInstance, entry.mTypeInstance->mTypeDef->mProperties[entry.mIdx], useFlags, BfCheckedKind_NotSet, false);
|
||||||
|
}
|
||||||
|
else if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Local)
|
||||||
|
{
|
||||||
|
auto localDef = mModule->mCurMethodState->mLocals[entry.mIdx];
|
||||||
|
curResult = LoadLocal(localDef);
|
||||||
|
}
|
||||||
|
else if (entry.mKind == BfUsingFieldData::MemberRef::Kind_Local)
|
||||||
|
{
|
||||||
|
auto checkMethodDef = entry.mTypeInstance->mTypeDef->mMethods[entry.mIdx];
|
||||||
|
BF_ASSERT(methodDef == checkMethodDef);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!curResult) && (mPropDef == NULL))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (entryIdx == foundList->mSize - 1)
|
||||||
|
{
|
||||||
|
auto autoComplete = GetAutoComplete();
|
||||||
|
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(targetSrc)))
|
||||||
|
autoComplete->SetDefinitionLocation(entry.GetRefNode(mModule));
|
||||||
|
|
||||||
|
if ((autoComplete != NULL) && (autoComplete->CheckFixit(targetSrc)))
|
||||||
|
autoComplete->FixitAddFullyQualify(targetSrc, methodName, *foundList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodDef->mIsStatic)
|
||||||
|
target = BfTypedValue(curTypeInst);
|
||||||
|
else if (curResult)
|
||||||
|
target = curResult;
|
||||||
|
else if ((!methodDef->mIsStatic) && (curTypeInst != NULL))
|
||||||
|
target = mModule->GetDefaultTypedValue(curTypeInst);
|
||||||
|
}
|
||||||
|
|
||||||
// If we call "GetType" on a value type, statically determine the type rather than boxing and then dispatching
|
// 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) &&
|
if ((methodDef) && (target) && (curTypeInst == mModule->mContext->mBfObjectType) &&
|
||||||
(methodDef->mName == "GetType") && (target.mType->IsValueType()) && (argValues.mArguments->IsEmpty()))
|
(methodDef->mName == "GetType") && (target.mType->IsValueType()) && (argValues.mArguments->IsEmpty()))
|
||||||
|
@ -10034,6 +10164,11 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (methodDef == NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// This will flush out any new ambiguity errors from extension methods
|
// This will flush out any new ambiguity errors from extension methods
|
||||||
methodMatcher.FlushAmbiguityError();
|
methodMatcher.FlushAmbiguityError();
|
||||||
|
|
||||||
|
@ -10041,8 +10176,8 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
{
|
{
|
||||||
FinishDeferredEvals(argValues);
|
FinishDeferredEvals(argValues);
|
||||||
auto compiler = mModule->mCompiler;
|
auto compiler = mModule->mCompiler;
|
||||||
if ((compiler->IsAutocomplete()) && (compiler->mResolvePassData->mAutoComplete->CheckFixit(targetSrc)))
|
if ((autoComplete != NULL) && (autoComplete->CheckFixit(targetSrc)))
|
||||||
{
|
{
|
||||||
mModule->CheckTypeRefFixit(targetSrc);
|
mModule->CheckTypeRefFixit(targetSrc);
|
||||||
bool wantStatic = !target.mValue;
|
bool wantStatic = !target.mValue;
|
||||||
if ((targetType == NULL) && (allowImplicitThis))
|
if ((targetType == NULL) && (allowImplicitThis))
|
||||||
|
@ -19934,13 +20069,16 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
|
||||||
|
|
||||||
BfAutoComplete* autoComplete = GetAutoComplete();
|
BfAutoComplete* autoComplete = GetAutoComplete();
|
||||||
bool deferredFixits = false;
|
bool deferredFixits = false;
|
||||||
if ((autoComplete != NULL) && (autoComplete->mResolveType == BfResolveType_GetFixits))
|
|
||||||
|
//TODO: Why was this needed? This breaks fixits on target nodes (ie: 'using' field fixit for 'fully quality')
|
||||||
|
/*if ((autoComplete != NULL) && (autoComplete->mResolveType == BfResolveType_GetFixits))
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> ignoreFixits(autoComplete->mIgnoreFixits, true);
|
SetAndRestoreValue<bool> ignoreFixits(autoComplete->mIgnoreFixits, true);
|
||||||
VisitChild(targetNode);
|
VisitChild(targetNode);
|
||||||
deferredFixits = true;
|
deferredFixits = true;
|
||||||
}
|
}
|
||||||
else if (!evaluatedLeft)
|
else*/
|
||||||
|
if (!evaluatedLeft)
|
||||||
{
|
{
|
||||||
if (auto memberReferenceExpr = BfNodeDynCast<BfMemberReferenceExpression>(targetNode))
|
if (auto memberReferenceExpr = BfNodeDynCast<BfMemberReferenceExpression>(targetNode))
|
||||||
{
|
{
|
||||||
|
|
|
@ -214,6 +214,7 @@ public:
|
||||||
BfType* mCheckReturnType;
|
BfType* mCheckReturnType;
|
||||||
BfMethodType mMethodType;
|
BfMethodType mMethodType;
|
||||||
BfCheckedKind mCheckedKind;
|
BfCheckedKind mCheckedKind;
|
||||||
|
Array<SizedArray<BfUsingFieldData::MemberRef, 1>*>* mUsingLists;
|
||||||
bool mHasArgNames;
|
bool mHasArgNames;
|
||||||
bool mHadExplicitGenericArguments;
|
bool mHadExplicitGenericArguments;
|
||||||
bool mHadOpenGenericArguments;
|
bool mHadOpenGenericArguments;
|
||||||
|
|
|
@ -291,20 +291,27 @@ void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx, BfLoca
|
||||||
{
|
{
|
||||||
if (fieldIdx >= 0)
|
if (fieldIdx >= 0)
|
||||||
{
|
{
|
||||||
localVar->mUnassignedFieldFlags &= ~((int64)1 << fieldIdx);
|
localVar->mUnassignedFieldFlags &= ~((int64)1 << fieldIdx);
|
||||||
|
|
||||||
|
if (localVar->mResolvedType->IsUnion())
|
||||||
|
{
|
||||||
|
// We need more 'smarts' to determine assignment of unions
|
||||||
|
localVar->mUnassignedFieldFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (localVar->mUnassignedFieldFlags == 0)
|
if (localVar->mUnassignedFieldFlags == 0)
|
||||||
{
|
{
|
||||||
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
localVar->mAssignedKind = assignKind;
|
localVar->mAssignedKind = assignKind;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
localVar->mAssignedKind = assignKind;
|
localVar->mAssignedKind = assignKind;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BF_ASSERT(deferredLocalAssignData->mVarIdBarrier != -1);
|
BF_ASSERT(deferredLocalAssignData->mVarIdBarrier != -1);
|
||||||
|
|
||||||
BfAssignedLocal defineVal = {localVar, fieldIdx, assignKind};
|
BfAssignedLocal defineVal = {localVar, fieldIdx, assignKind};
|
||||||
|
|
|
@ -1838,6 +1838,7 @@ public:
|
||||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
|
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
|
||||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
|
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
|
||||||
void DoCEEmit(BfMethodInstance* methodInstance);
|
void DoCEEmit(BfMethodInstance* methodInstance);
|
||||||
|
void PopulateUsingFieldData(BfTypeInstance* typeInstance);
|
||||||
void DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias);
|
void DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias);
|
||||||
void DoPopulateType_InitSearches(BfTypeInstance* typeInstance);
|
void DoPopulateType_InitSearches(BfTypeInstance* typeInstance);
|
||||||
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
||||||
|
|
|
@ -3056,6 +3056,151 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::PopulateUsingFieldData(BfTypeInstance* typeInstance)
|
||||||
|
{
|
||||||
|
if (typeInstance->mTypeInfoEx == NULL)
|
||||||
|
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
||||||
|
|
||||||
|
BF_ASSERT(typeInstance->mTypeInfoEx->mUsingFieldData == NULL);
|
||||||
|
|
||||||
|
BfUsingFieldData* usingFieldData = new BfUsingFieldData();
|
||||||
|
typeInstance->mTypeInfoEx->mUsingFieldData = usingFieldData;
|
||||||
|
|
||||||
|
HashSet<BfTypeInstance*> checkedTypeSet;
|
||||||
|
Array<BfUsingFieldData::MemberRef> memberRefs;
|
||||||
|
std::function<void(BfTypeInstance*, bool)> _CheckType = [&](BfTypeInstance* usingType, bool staticOnly)
|
||||||
|
{
|
||||||
|
if (!checkedTypeSet.Add(usingType))
|
||||||
|
return;
|
||||||
|
defer(
|
||||||
|
{
|
||||||
|
checkedTypeSet.Remove(usingType);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto fieldDef : usingType->mTypeDef->mFields)
|
||||||
|
{
|
||||||
|
if ((staticOnly) && (!fieldDef->mIsStatic))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memberRefs.Add(BfUsingFieldData::MemberRef(usingType, fieldDef));
|
||||||
|
defer(
|
||||||
|
{
|
||||||
|
memberRefs.pop_back();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (memberRefs.Count() > 1)
|
||||||
|
{
|
||||||
|
BfUsingFieldData::Entry* entry = NULL;
|
||||||
|
usingFieldData->mEntries.TryAdd(fieldDef->mName, NULL, &entry);
|
||||||
|
SizedArray<BfUsingFieldData::MemberRef, 1> lookup;
|
||||||
|
for (auto entry : memberRefs)
|
||||||
|
lookup.Add(entry);
|
||||||
|
entry->mLookups.Add(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldDef->mUsingProtection == BfProtection_Hidden)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (usingType->mDefineState < BfTypeDefineState_Defined)
|
||||||
|
{
|
||||||
|
// We need to populate this type now
|
||||||
|
PopulateType(usingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fieldInstance = &usingType->mFieldInstances[fieldDef->mIdx];
|
||||||
|
auto fieldTypeInst = fieldInstance->mResolvedType->ToTypeInstance();
|
||||||
|
if (fieldTypeInst != NULL)
|
||||||
|
_CheckType(fieldTypeInst, fieldDef->mIsStatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto propDef : usingType->mTypeDef->mProperties)
|
||||||
|
{
|
||||||
|
if ((staticOnly) && (!propDef->mIsStatic))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memberRefs.Add(BfUsingFieldData::MemberRef(usingType, propDef));
|
||||||
|
defer(
|
||||||
|
{
|
||||||
|
memberRefs.pop_back();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (memberRefs.Count() > 1)
|
||||||
|
{
|
||||||
|
BfUsingFieldData::Entry* entry = NULL;
|
||||||
|
usingFieldData->mEntries.TryAdd(propDef->mName, NULL, &entry);
|
||||||
|
SizedArray<BfUsingFieldData::MemberRef, 1> lookup;
|
||||||
|
for (auto entry : memberRefs)
|
||||||
|
lookup.Add(entry);
|
||||||
|
entry->mLookups.Add(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propDef->mUsingProtection == BfProtection_Hidden)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (usingType->mDefineState < BfTypeDefineState_Defined)
|
||||||
|
{
|
||||||
|
// We need to populate this type now
|
||||||
|
PopulateType(usingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
BfType* propType = NULL;
|
||||||
|
for (auto methodDef : propDef->mMethods)
|
||||||
|
{
|
||||||
|
auto methodInstance = GetRawMethodInstance(usingType, methodDef);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
continue;
|
||||||
|
if (methodDef->mMethodType == BfMethodType_PropertyGetter)
|
||||||
|
{
|
||||||
|
propType = methodInstance->mReturnType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (methodDef->mMethodType == BfMethodType_PropertySetter)
|
||||||
|
{
|
||||||
|
if (methodInstance->GetParamCount() > 0)
|
||||||
|
{
|
||||||
|
propType = methodInstance->GetParamType(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((propType != NULL) && (propType->IsTypeInstance()))
|
||||||
|
_CheckType(propType->ToTypeInstance(), propDef->mIsStatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto methodDef : usingType->mTypeDef->mMethods)
|
||||||
|
{
|
||||||
|
if ((staticOnly) && (!methodDef->mIsStatic))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//TODO: Support mixins as well
|
||||||
|
if (methodDef->mMethodType != BfMethodType_Normal)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// No auto methods
|
||||||
|
if (methodDef->mMethodDeclaration == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memberRefs.Add(BfUsingFieldData::MemberRef(usingType, methodDef));
|
||||||
|
defer(
|
||||||
|
{
|
||||||
|
memberRefs.pop_back();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (memberRefs.Count() > 1)
|
||||||
|
{
|
||||||
|
BfUsingFieldData::Entry* entry = NULL;
|
||||||
|
usingFieldData->mMethods.TryAdd(methodDef->mName, NULL, &entry);
|
||||||
|
SizedArray<BfUsingFieldData::MemberRef, 1> lookup;
|
||||||
|
for (auto entry : memberRefs)
|
||||||
|
lookup.Add(entry);
|
||||||
|
entry->mLookups.Add(lookup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_CheckType(typeInstance, false);
|
||||||
|
}
|
||||||
|
|
||||||
void BfModule::DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance)
|
void BfModule::DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, genericTypeInstance);
|
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, genericTypeInstance);
|
||||||
|
|
|
@ -6570,23 +6570,23 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (token == BfToken_Using)
|
if (token == BfToken_Using)
|
||||||
// {
|
{
|
||||||
// if ((fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
|
if ((fieldDecl->mConstSpecifier != NULL) && (fieldDecl->mConstSpecifier->mToken == BfToken_Const))
|
||||||
// {
|
{
|
||||||
// Fail("Const cannot be used with 'using' specified", tokenNode);
|
Fail("Const cannot be used with 'using' specified", tokenNode);
|
||||||
// }
|
}
|
||||||
// else if (fieldDecl->mConstSpecifier != NULL)
|
else if (fieldDecl->mConstSpecifier != NULL)
|
||||||
// {
|
{
|
||||||
// Fail("Using already specified", tokenNode);
|
Fail("Using already specified", tokenNode);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// auto usingSpecifier = mAlloc->Alloc<BfUsingSpecifierNode>();
|
auto usingSpecifier = mAlloc->Alloc<BfUsingSpecifierNode>();
|
||||||
// ReplaceNode(tokenNode, usingSpecifier);
|
ReplaceNode(tokenNode, usingSpecifier);
|
||||||
// MEMBER_SET(usingSpecifier, mUsingToken, tokenNode);
|
MEMBER_SET(usingSpecifier, mUsingToken, tokenNode);
|
||||||
// MEMBER_SET(fieldDecl, mConstSpecifier, usingSpecifier);
|
MEMBER_SET(fieldDecl, mConstSpecifier, usingSpecifier);
|
||||||
// handled = true;
|
handled = true;
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (token == BfToken_ReadOnly)
|
if (token == BfToken_ReadOnly)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,125 @@ bool BfTypedValue::CanModify() const
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
BfProtection BfUsingFieldData::MemberRef::GetProtection() const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->mProtection;
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->mProtection;
|
||||||
|
case Kind_Method:
|
||||||
|
return mTypeInstance->mTypeDef->mMethods[mIdx]->mProtection;
|
||||||
|
}
|
||||||
|
return BfProtection_Public;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfProtection BfUsingFieldData::MemberRef::GetUsingProtection() const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->mUsingProtection;
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->mUsingProtection;
|
||||||
|
case Kind_Method:
|
||||||
|
return mTypeInstance->mTypeDef->mMethods[mIdx]->mProtection;
|
||||||
|
}
|
||||||
|
return BfProtection_Public;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypeDef* BfUsingFieldData::MemberRef::GetDeclaringType(BfModule* curModule) const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->mDeclaringType;
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->mDeclaringType;
|
||||||
|
case Kind_Method:
|
||||||
|
return mTypeInstance->mTypeDef->mMethods[mIdx]->mDeclaringType;
|
||||||
|
case Kind_Local:
|
||||||
|
return curModule->GetActiveTypeDef();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfUsingFieldData::MemberRef::GetFullName(BfModule* curModule) const
|
||||||
|
{
|
||||||
|
if (mKind == Kind_Local)
|
||||||
|
return curModule->mCurMethodState->mLocals[mIdx]->mName;
|
||||||
|
|
||||||
|
String result = curModule->TypeToString(mTypeInstance);
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
result += ".";
|
||||||
|
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
result += mTypeInstance->mTypeDef->mFields[mIdx]->mName;
|
||||||
|
break;
|
||||||
|
case Kind_Property:
|
||||||
|
result += mTypeInstance->mTypeDef->mProperties[mIdx]->mName;
|
||||||
|
break;
|
||||||
|
case Kind_Method:
|
||||||
|
result += mTypeInstance->mTypeDef->mMethods[mIdx]->mName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfUsingFieldData::MemberRef::GetName(BfModule* curModule) const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->mName;
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->mName;
|
||||||
|
case Kind_Method:
|
||||||
|
{
|
||||||
|
auto methodInstance = curModule->GetRawMethodInstance(mTypeInstance, mTypeInstance->mTypeDef->mMethods[mIdx]);
|
||||||
|
return curModule->MethodToString(methodInstance, BfMethodNameFlag_OmitTypeName);
|
||||||
|
}
|
||||||
|
case Kind_Local:
|
||||||
|
return curModule->mCurMethodState->mLocals[mIdx]->mName;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
BfAstNode* BfUsingFieldData::MemberRef::GetRefNode(BfModule* curModule) const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->GetRefNode();
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->GetRefNode();
|
||||||
|
case Kind_Method:
|
||||||
|
return mTypeInstance->mTypeDef->mMethods[mIdx]->GetRefNode();
|
||||||
|
case Kind_Local:
|
||||||
|
return curModule->mCurMethodState->mLocals[mIdx]->mNameNode;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BfUsingFieldData::MemberRef::IsStatic() const
|
||||||
|
{
|
||||||
|
switch (mKind)
|
||||||
|
{
|
||||||
|
case Kind_Field:
|
||||||
|
return mTypeInstance->mTypeDef->mFields[mIdx]->mIsStatic;
|
||||||
|
case Kind_Property:
|
||||||
|
return mTypeInstance->mTypeDef->mProperties[mIdx]->mIsStatic;
|
||||||
|
case Kind_Method:
|
||||||
|
return mTypeInstance->mTypeDef->mMethods[mIdx]->mIsStatic;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool BfGenericParamInstance::IsEnum()
|
bool BfGenericParamInstance::IsEnum()
|
||||||
{
|
{
|
||||||
if ((mGenericParamFlags & BfGenericParamFlag_Enum) != 0)
|
if ((mGenericParamFlags & BfGenericParamFlag_Enum) != 0)
|
||||||
|
|
|
@ -1821,19 +1821,91 @@ public:
|
||||||
Array<BfAtomComposite> mNamespaces;
|
Array<BfAtomComposite> mNamespaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BfUsingFieldData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct MemberRef
|
||||||
|
{
|
||||||
|
enum Kind
|
||||||
|
{
|
||||||
|
Kind_None,
|
||||||
|
Kind_Field,
|
||||||
|
Kind_Property,
|
||||||
|
Kind_Method,
|
||||||
|
Kind_Local
|
||||||
|
};
|
||||||
|
|
||||||
|
BfTypeInstance* mTypeInstance;
|
||||||
|
Kind mKind;
|
||||||
|
int mIdx;
|
||||||
|
|
||||||
|
MemberRef()
|
||||||
|
{
|
||||||
|
mTypeInstance = NULL;
|
||||||
|
mKind = Kind_None;
|
||||||
|
mIdx = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberRef(BfTypeInstance* typeInst, BfFieldDef* fieldDef)
|
||||||
|
{
|
||||||
|
mTypeInstance = typeInst;
|
||||||
|
mKind = Kind_Field;
|
||||||
|
mIdx = fieldDef->mIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberRef(BfTypeInstance* typeInst, BfMethodDef* methodDef)
|
||||||
|
{
|
||||||
|
mTypeInstance = typeInst;
|
||||||
|
mKind = Kind_Method;
|
||||||
|
mIdx = methodDef->mIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberRef(BfTypeInstance* typeInst, BfPropertyDef* propDef)
|
||||||
|
{
|
||||||
|
mTypeInstance = typeInst;
|
||||||
|
mKind = Kind_Property;
|
||||||
|
mIdx = propDef->mIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfProtection GetProtection() const;
|
||||||
|
BfProtection GetUsingProtection() const;
|
||||||
|
BfTypeDef* GetDeclaringType(BfModule* curModule) const;
|
||||||
|
String GetFullName(BfModule* curModule) const;
|
||||||
|
String GetName(BfModule* curModule) const;
|
||||||
|
BfAstNode* GetRefNode(BfModule* curModule) const;
|
||||||
|
bool IsStatic() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
SizedArray<SizedArray<MemberRef, 1>, 1> mLookups;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Dictionary<String, Entry> mEntries;
|
||||||
|
Dictionary<String, Entry> mMethods;
|
||||||
|
};
|
||||||
|
|
||||||
class BfTypeInfoEx
|
class BfTypeInfoEx
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BfUsingFieldData* mUsingFieldData;
|
||||||
BfType* mUnderlyingType;
|
BfType* mUnderlyingType;
|
||||||
int64 mMinValue;
|
int64 mMinValue;
|
||||||
int64 mMaxValue;
|
int64 mMaxValue;
|
||||||
|
|
||||||
BfTypeInfoEx()
|
BfTypeInfoEx()
|
||||||
{
|
{
|
||||||
|
mUsingFieldData = NULL;
|
||||||
mUnderlyingType = NULL;
|
mUnderlyingType = NULL;
|
||||||
mMinValue = 0;
|
mMinValue = 0;
|
||||||
mMaxValue = 0;
|
mMaxValue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~BfTypeInfoEx()
|
||||||
|
{
|
||||||
|
delete mUsingFieldData;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -775,13 +775,6 @@ void BfTypeDef::PopulateMemberSets()
|
||||||
fieldDef->mNextWithSameName = (BfFieldDef*)entry->mMemberDef;
|
fieldDef->mNextWithSameName = (BfFieldDef*)entry->mMemberDef;
|
||||||
entry->mMemberDef = fieldDef;
|
entry->mMemberDef = fieldDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldDef->mUsingProtection != BfProtection_Hidden)
|
|
||||||
{
|
|
||||||
if (mUsingFieldData == NULL)
|
|
||||||
mUsingFieldData = new BfUsingFieldData();
|
|
||||||
mUsingFieldData->mUsingFields.Add(fieldDef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mPropertySet.mSourceSize < mProperties.mSize)
|
while (mPropertySet.mSourceSize < mProperties.mSize)
|
||||||
|
@ -795,13 +788,6 @@ void BfTypeDef::PopulateMemberSets()
|
||||||
propDef->mNextWithSameName = (BfPropertyDef*)entry->mMemberDef;
|
propDef->mNextWithSameName = (BfPropertyDef*)entry->mMemberDef;
|
||||||
entry->mMemberDef = propDef;
|
entry->mMemberDef = propDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propDef->mUsingProtection != BfProtection_Hidden)
|
|
||||||
{
|
|
||||||
if (mUsingFieldData == NULL)
|
|
||||||
mUsingFieldData = new BfUsingFieldData();
|
|
||||||
mUsingFieldData->mUsingFields.Add(propDef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,9 +799,7 @@ void BfTypeDef::ClearMemberSets()
|
||||||
|
|
||||||
for (auto entry : mFieldSet)
|
for (auto entry : mFieldSet)
|
||||||
((BfFieldDef*)entry.mMemberDef)->mNextWithSameName = NULL;
|
((BfFieldDef*)entry.mMemberDef)->mNextWithSameName = NULL;
|
||||||
mFieldSet.Clear();
|
mFieldSet.Clear();
|
||||||
delete mUsingFieldData;
|
|
||||||
mUsingFieldData = NULL;
|
|
||||||
|
|
||||||
for (auto entry : mPropertySet)
|
for (auto entry : mPropertySet)
|
||||||
((BfPropertyDef*)entry.mMemberDef)->mNextWithSameName = NULL;
|
((BfPropertyDef*)entry.mMemberDef)->mNextWithSameName = NULL;
|
||||||
|
@ -834,7 +818,6 @@ BfTypeDef::~BfTypeDef()
|
||||||
mSource->mRefCount--;
|
mSource->mRefCount--;
|
||||||
BF_ASSERT(mSource->mRefCount >= 0);
|
BF_ASSERT(mSource->mRefCount >= 0);
|
||||||
}
|
}
|
||||||
delete mUsingFieldData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BfSource* BfTypeDef::GetLastSource()
|
BfSource* BfTypeDef::GetLastSource()
|
||||||
|
@ -3055,8 +3038,6 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
|
||||||
typeDef->mPartials = nextTypeDef->mPartials;
|
typeDef->mPartials = nextTypeDef->mPartials;
|
||||||
typeDef->mMethodSet.Clear();
|
typeDef->mMethodSet.Clear();
|
||||||
typeDef->mFieldSet.Clear();
|
typeDef->mFieldSet.Clear();
|
||||||
delete typeDef->mUsingFieldData;
|
|
||||||
typeDef->mUsingFieldData = NULL;
|
|
||||||
typeDef->mPropertySet.Clear();
|
typeDef->mPropertySet.Clear();
|
||||||
|
|
||||||
delete nextTypeDef;
|
delete nextTypeDef;
|
||||||
|
@ -3170,9 +3151,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
||||||
newField->mIdx = (int)typeDef->mFields.size();
|
newField->mIdx = (int)typeDef->mFields.size();
|
||||||
typeDef->mFields.push_back(newField);
|
typeDef->mFields.push_back(newField);
|
||||||
}
|
}
|
||||||
typeDef->mFieldSet.Clear();
|
typeDef->mFieldSet.Clear();
|
||||||
delete typeDef->mUsingFieldData;
|
|
||||||
typeDef->mUsingFieldData = NULL;
|
|
||||||
|
|
||||||
bool hadNoDeclMethod = false;
|
bool hadNoDeclMethod = false;
|
||||||
int startMethodIdx = (int)typeDef->mMethods.size();
|
int startMethodIdx = (int)typeDef->mMethods.size();
|
||||||
|
|
|
@ -1052,38 +1052,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfUsingFieldData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct FieldRef
|
|
||||||
{
|
|
||||||
BfTypeInstance* mTypeInstance;
|
|
||||||
BfFieldDef* mFieldDef;
|
|
||||||
|
|
||||||
FieldRef()
|
|
||||||
{
|
|
||||||
mTypeInstance = NULL;
|
|
||||||
mFieldDef = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldRef(BfTypeInstance* typeInst, BfFieldDef* fieldDef)
|
|
||||||
{
|
|
||||||
mTypeInstance = typeInst;
|
|
||||||
mFieldDef = fieldDef;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Entry
|
|
||||||
{
|
|
||||||
Array<FieldRef> mConflicts;
|
|
||||||
SizedArray<FieldRef, 1> mLookup;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Array<BfFieldDef*> mUsingFields;
|
|
||||||
Dictionary<String, Entry> mEntries;
|
|
||||||
};
|
|
||||||
|
|
||||||
// For partial classes, the first entry in the map will contain the combined data
|
// For partial classes, the first entry in the map will contain the combined data
|
||||||
class BfTypeDef
|
class BfTypeDef
|
||||||
{
|
{
|
||||||
|
@ -1127,7 +1095,6 @@ public:
|
||||||
Array<BfTypeReference*> mStaticSearch;
|
Array<BfTypeReference*> mStaticSearch;
|
||||||
Array<BfTypeReference*> mInternalAccessSet;
|
Array<BfTypeReference*> mInternalAccessSet;
|
||||||
Array<BfFieldDef*> mFields;
|
Array<BfFieldDef*> mFields;
|
||||||
BfUsingFieldData* mUsingFieldData; // Created during mFieldSet
|
|
||||||
Array<BfPropertyDef*> mProperties;
|
Array<BfPropertyDef*> mProperties;
|
||||||
Array<BfMethodDef*> mMethods;
|
Array<BfMethodDef*> mMethods;
|
||||||
BfTypeDefMemberSet mMethodSet;
|
BfTypeDefMemberSet mMethodSet;
|
||||||
|
@ -1217,8 +1184,7 @@ public:
|
||||||
mOuterType = NULL;
|
mOuterType = NULL;
|
||||||
mTypeDeclaration = NULL;
|
mTypeDeclaration = NULL;
|
||||||
mNextRevision = NULL;
|
mNextRevision = NULL;
|
||||||
mProtection = BfProtection_Public;
|
mProtection = BfProtection_Public;
|
||||||
mUsingFieldData = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BfSource* GetLastSource();
|
BfSource* GetLastSource();
|
||||||
|
|
87
IDEHelper/Tests/src/UsingField.bf
Normal file
87
IDEHelper/Tests/src/UsingField.bf
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tests
|
||||||
|
{
|
||||||
|
class UsingField
|
||||||
|
{
|
||||||
|
class ClassA
|
||||||
|
{
|
||||||
|
public int mA0 = 1;
|
||||||
|
public static int sA0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassB
|
||||||
|
{
|
||||||
|
public int mB0 = 3;
|
||||||
|
public static int sB0 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassC
|
||||||
|
{
|
||||||
|
public int mC0 = 12;
|
||||||
|
public int mC1 = 23;
|
||||||
|
|
||||||
|
public int PropC0 => 123;
|
||||||
|
public int MethodC0() => 234;
|
||||||
|
|
||||||
|
using public static ClassA sA = new .() ~ delete _;
|
||||||
|
ClassB sB = new .() ~ delete _;
|
||||||
|
|
||||||
|
using public ClassB B => sB;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassD
|
||||||
|
{
|
||||||
|
public using protected append ClassC mC;
|
||||||
|
private using append ClassC mC2;
|
||||||
|
|
||||||
|
public int mD0 = 34;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mC.mC0 += 10000;
|
||||||
|
mC2.mC0 += 20000;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Union]
|
||||||
|
struct Vector2
|
||||||
|
{
|
||||||
|
public struct Coords
|
||||||
|
{
|
||||||
|
public float mX;
|
||||||
|
public float mY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[2] mValues;
|
||||||
|
public using Coords mCoords;
|
||||||
|
|
||||||
|
public this(float x, float y)
|
||||||
|
{
|
||||||
|
mX = x;
|
||||||
|
mY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public static void Test()
|
||||||
|
{
|
||||||
|
ClassD cd = scope .();
|
||||||
|
cd.mC0 = 123;
|
||||||
|
Test.Assert(cd.PropC0 == 123);
|
||||||
|
Test.Assert(cd.MethodC0() == 234);
|
||||||
|
Test.Assert(cd.mD0 == 34);
|
||||||
|
|
||||||
|
Test.Assert(ClassD.sA0 == 2);
|
||||||
|
Test.Assert(ClassD.sB0 == 4);
|
||||||
|
|
||||||
|
Vector2 vec = .(1.2f, 2.3f);
|
||||||
|
Test.Assert(sizeof(Vector2) == 8);
|
||||||
|
Test.Assert(vec.mX == 1.2f);
|
||||||
|
Test.Assert(vec.mY == 2.3f);
|
||||||
|
Test.Assert(vec.mValues[0] == 1.2f);
|
||||||
|
Test.Assert(vec.mValues[1] == 2.3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue