Просмотр исходного кода

Added ability to lookup types with 'using static'

Brian Fiete 5 лет назад
Родитель
Сommit
a02de171ef

+ 2 - 2
IDEHelper/Compiler/BfModule.h

@@ -1694,13 +1694,13 @@ public:
 	void CheckIdentifierFixit(BfAstNode* node);
 	void TypeRefNotFound(BfTypeReference* typeRef, const char* appendName = NULL);
 	bool ValidateTypeWildcard(BfTypeReference* typeRef, bool isAttributeRef);
-	BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
+	BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0);
 	BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true);
 	BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeReference*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
 	//BfType* ResolveTypeRef(BfIdentifierNode* identifier, const BfSizedArray<BfTypeReference*>& genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
 	BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data);
 	BfType* ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType = BfPopulateType_Data);
-	BfType* ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false);
+	BfType* ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false, int numGenericArgs = 0);
 	BfType* ResolveInnerType(BfType* outerType, BfIdentifierNode* identifier, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false);
 	BfTypeDef* GetCombinedPartialTypeDef(BfTypeDef* type);
 	BfTypeInstance* GetOuterType(BfType* type);

+ 79 - 31
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -5257,7 +5257,7 @@ void BfModule::HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDe
 		mCompiler->mResolvePassData->HandleMethodGenericParam(refNode, typeDef, methodDef, methodGenericParamIdx);
 }
 
-BfType* BfModule::ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, BfPopulateType populateType, bool ignoreErrors)
+BfType* BfModule::ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, BfPopulateType populateType, bool ignoreErrors, int numGenericArgs)
 {
 	BfTypeDef* nestedTypeDef = NULL;
 
@@ -5315,7 +5315,14 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfTypeReference* typeRef,
 							if ((!isFailurePass) && (!CheckProtection(latestCheckType->mProtection, allowProtected, allowPrivate)))
 								continue;
 
-							if (checkType->mName->mString == findName)
+							if (checkType->mProject != checkOuterType->mTypeDef->mProject)
+							{
+								auto visibleProjectSet = GetVisibleProjectSet();
+								if ((visibleProjectSet == NULL) || (!visibleProjectSet->Contains(checkType->mProject)))
+									continue;
+							}
+
+							if ((checkType->mName->mString == findName) && (checkType->GetSelfGenericParamCount() == numGenericArgs))
 							{
 								if (isFailurePass)
 								{
@@ -5696,7 +5703,7 @@ BfTypeDef* BfModule::ResolveGenericInstanceDef(BfGenericInstanceTypeRef* generic
 	if (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(typeRef))
 	{		
 		BfAutoParentNodeEntry autoParentNodeEntry(this, genericTypeRef);
-		auto type = ResolveTypeRef(qualifiedTypeRef, BfPopulateType_TypeDef);
+		auto type = ResolveTypeRef(qualifiedTypeRef, BfPopulateType_TypeDef, BfResolveTypeRefFlag_None, numGenericParams);
 		if (type == NULL)
 			return NULL;
 		if (outType != NULL)
@@ -6676,6 +6683,28 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene
 				mSystem->FindTypeDef(findName, numGenericArgs, useTypeDef->mProject, checkNamespace, allowPrivate, &lookupCtx);
 		}
 	}
+
+	if (!lookupCtx.HasValidMatch())
+	{
+		auto staticSearch = GetStaticSearch();
+		if (staticSearch != NULL)
+		{
+			for (auto staticTypeInstance : staticSearch->mStaticTypes)
+			{
+				if (mSystem->FindTypeDef(findName, numGenericArgs, useTypeDef->mProject, staticTypeInstance->mTypeDef->mFullNameEx, false, &lookupCtx))
+				{
+					if (lookupCtx.HasValidMatch())
+						break;
+					
+					if (lookupCtx.mBestTypeDef->mProtection < BfProtection_Public)
+					{
+						protErrorTypeDef = lookupCtx.mBestTypeDef;
+						protErrorOuterType = staticTypeInstance;
+					}					
+				}
+			}
+		}
+	}
 	
 	if ((error != NULL) && (lookupCtx.mAmbiguousTypeDef != NULL))
 	{
@@ -7110,7 +7139,7 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
 	return BfTypedValue();
 }
 
-BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
+BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags, int numGenericArgs)
 {
 	BP_ZONE("BfModule::ResolveTypeRef");
 
@@ -7183,7 +7212,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		auto namedTypeRef = BfNodeDynCastExact<BfNamedTypeReference>(typeRef);
 		auto directStrTypeRef = BfNodeDynCastExact<BfDirectStrTypeReference>(typeRef);
 		if (((namedTypeRef != NULL) && (namedTypeRef->mNameNode != NULL)) || (directStrTypeRef != NULL))
-		{			
+		{
 			StringT<128> findName;
 			if (namedTypeRef != NULL)
 				namedTypeRef->mNameNode->ToString(findName);
@@ -7392,10 +7421,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 				}
 			}
 		}
-			
+		
 		if ((typeDef == NULL) && (mCurTypeInstance != NULL))
 		{
-			// Try searching within inner type				
+			// Try searching within inner type
 			auto checkOuterType = mCurTypeInstance;
 			while (checkOuterType != NULL)
 			{
@@ -7414,7 +7443,25 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 				checkOuterType = GetOuterType(checkOuterType);
 			}
 		}
-			
+		
+		if (typeDef == NULL)
+		{
+			auto staticSearch = GetStaticSearch();
+			if (staticSearch != NULL)
+			{
+				for (auto staticTypeInst : staticSearch->mStaticTypes)
+				{
+					auto resolvedType = ResolveInnerType(staticTypeInst, typeRef, populateType, true);
+					if (resolvedType != NULL)
+					{
+						if (mCurTypeInstance != NULL)
+							AddDependency(staticTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
+						return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags);
+					}
+				}
+			}
+		}
+
 		if (typeDef == NULL)
 		{
 #ifdef BF_AST_HAS_PARENT_MEMBER
@@ -7596,7 +7643,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
 		}
 
-		auto resolvedType = ResolveInnerType(leftType, qualifiedTypeRef->mRight, populateType);
+		auto resolvedType = ResolveInnerType(leftType, qualifiedTypeRef->mRight, populateType, false, numGenericArgs);
 		if ((resolvedType != NULL) && (mCurTypeInstance != NULL))
 			AddDependency(leftType, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
 		return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags);
@@ -7787,15 +7834,18 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			return ResolveTypeResult(typeRef, primType, populateType, resolveFlags);
 		}
 
-		if ((mCurTypeInstance != NULL) && (typeDef->mGenericParamDefs.size() != 0))
+		BfTypeInstance* outerTypeInstance = lookupCtx.mRootOuterTypeInstance;
+		if (outerTypeInstance == NULL)
+			outerTypeInstance = mCurTypeInstance;
+		if ((outerTypeInstance != NULL) && (typeDef->mGenericParamDefs.size() != 0))
 		{
 			// Try to inherit generic params from current parent
 						
 			BfTypeDef* outerType = mSystem->GetCombinedPartial(typeDef->mOuterType);
 			BF_ASSERT(!outerType->mIsPartial);
-			if (TypeHasParentOrEquals(mCurTypeInstance->mTypeDef, outerType))
+			if (TypeHasParentOrEquals(outerTypeInstance->mTypeDef, outerType))
 			{
-				BfType* checkCurType = mCurTypeInstance;
+				BfType* checkCurType = outerTypeInstance;
 				if (checkCurType->IsBoxed())
 					checkCurType = checkCurType->GetUnderlyingType();
 				if (checkCurType->IsTypeAlias())
@@ -8012,24 +8062,23 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
 			return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
 		}
-
+		
+		BfTypeInstance* outerTypeInstance = mCurTypeInstance;
+		
 		auto outerType = typeDef->mOuterType;
 		BfTypeDef* commonOuterType = NULL;
-		if (mCurTypeInstance != NULL)
+
+		int startDefGenericParamIdx = 0;
+		commonOuterType = BfResolvedTypeSet::FindRootCommonOuterType(outerType, &lookupCtx, outerTypeInstance);
+		if ((commonOuterType) && (outerTypeInstance->IsGenericTypeInstance()))
 		{
-			// Copy generic params for our parent type if the current type instance shares that parent type						
-			auto outerType = typeDef->mOuterType;
-			commonOuterType = FindCommonOuterType(mCurTypeInstance->mTypeDef, outerType);
-			if ((commonOuterType) && (mCurTypeInstance->IsGenericTypeInstance()))
-			{
-				int startDefGenericParamIdx = (int)commonOuterType->mGenericParamDefs.size();
-				auto parentTypeInstance = (BfTypeInstance*)mCurTypeInstance;
-				if (parentTypeInstance->IsTypeAlias())
-					parentTypeInstance = (BfTypeInstance*)GetOuterType(parentTypeInstance)->ToTypeInstance();
-				for (int i = 0; i < startDefGenericParamIdx; i++)
-					genericArgs.push_back(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i]);
-			}
-		}
+			startDefGenericParamIdx = (int)commonOuterType->mGenericParamDefs.size();
+			auto parentTypeInstance = outerTypeInstance;
+			if (parentTypeInstance->IsTypeAlias())
+				parentTypeInstance = (BfTypeInstance*)GetOuterType(parentTypeInstance)->ToTypeInstance();
+			for (int i = 0; i < startDefGenericParamIdx; i++)
+				genericArgs.push_back(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i]);
+		}		
 
 		for (auto genericArgRef : genericArguments)
 		{
@@ -8080,13 +8129,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
 			return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
 		}
-
-		int startDefGenericParamIdx = 0;
+		
 		genericTypeInst->mTypeDef = typeDef;
 
-		if ((commonOuterType != NULL) && (mCurTypeInstance->IsGenericTypeInstance()))
+		if ((commonOuterType != NULL) && (outerTypeInstance->IsGenericTypeInstance()))
 		{			
-			auto parentTypeInstance = (BfTypeInstance*)mCurTypeInstance;
+			auto parentTypeInstance = outerTypeInstance;
 			if (parentTypeInstance->IsTypeAlias())
 				parentTypeInstance = (BfTypeInstance*)GetOuterType(parentTypeInstance)->ToTypeInstance();
 			for (int i = 0; i < startDefGenericParamIdx; i++)

+ 74 - 14
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -2590,6 +2590,31 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx,
 	return Hash(resolvedType, ctx);
 }
 
+BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outOuterTypeInstance)
+{
+	BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, outerType);
+	if ((commonOuterType == NULL) && (outerType != NULL))
+	{
+		auto staticSearch = ctx->mModule->GetStaticSearch();
+		if (staticSearch != NULL)
+		{
+			for (auto staticTypeInst : staticSearch->mStaticTypes)
+			{
+				auto foundOuterType = ctx->mModule->FindCommonOuterType(staticTypeInst->mTypeDef, outerType);
+				if ((foundOuterType != NULL) &&
+					((commonOuterType == NULL) || (foundOuterType->mNestDepth > commonOuterType->mNestDepth)))
+				{
+					commonOuterType = foundOuterType;
+					outOuterTypeInstance = staticTypeInst;
+				}
+			}
+		}
+	}
+	if (outOuterTypeInstance != NULL)
+		ctx->mRootOuterTypeInstance = outOuterTypeInstance;
+	return commonOuterType;
+}
+
 int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags)
 {
 	if ((typeRef == ctx->mRootTypeRef) && (ctx->mRootTypeDef != NULL) &&
@@ -2598,7 +2623,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 		BfTypeDef* typeDef = ctx->mRootTypeDef;
 	
 		int hashVal = typeDef->mHash;
-
+		
 		if (typeDef->mGenericParamDefs.size() != 0)
 		{
 			auto checkTypeInstance = ctx->mModule->mCurTypeInstance;
@@ -2606,14 +2631,38 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 				checkTypeInstance = checkTypeInstance->GetUnderlyingType()->ToTypeInstance();
 
 			auto outerType = ctx->mModule->mSystem->GetOuterTypeNonPartial(typeDef);
-			BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, outerType);
+			
+			BfTypeDef* commonOuterType;
+			if (typeRef == ctx->mRootTypeRef)
+				commonOuterType = FindRootCommonOuterType(outerType, ctx, checkTypeInstance);
+			else
+				commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, outerType);
+
+			if ((commonOuterType == NULL) && (outerType != NULL))
+			{
+				auto staticSearch = ctx->mModule->GetStaticSearch();
+				if (staticSearch != NULL)
+				{
+					for (auto staticTypeInst : staticSearch->mStaticTypes)
+					{
+						auto foundOuterType = ctx->mModule->FindCommonOuterType(staticTypeInst->mTypeDef, outerType);
+						if ((foundOuterType != NULL) &&
+							((commonOuterType == NULL) || (foundOuterType->mNestDepth > commonOuterType->mNestDepth)))
+						{
+							commonOuterType = foundOuterType;
+							checkTypeInstance = staticTypeInst;
+						}
+					}
+				}
+			}
+
 			if ((commonOuterType == NULL) || (commonOuterType->mGenericParamDefs.size() == 0))
 			{
 				ctx->mModule->Fail("Generic arguments expected", typeRef);
 				ctx->mFailed = true;
 				return 0;
 			}
-
+			
 			BF_ASSERT(checkTypeInstance->IsGenericTypeInstance());
 			auto curGenericTypeInst = (BfTypeInstance*)checkTypeInstance;
 			int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size();
@@ -2688,12 +2737,18 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 		}
 		
 		// Do we need to add generic arguments from an in-context outer class?
-		if ((elementTypeDef->mOuterType != NULL) && (ctx->mModule->mCurTypeInstance != NULL) && (ctx->mModule->mCurTypeInstance->IsGenericTypeInstance()))
+		if ((elementTypeDef->mOuterType != NULL) && (ctx->mModule->mCurTypeInstance != NULL))
 		{
-			BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, elementTypeDef->mOuterType);
-			if (commonOuterType != NULL)
+			BfTypeInstance* checkTypeInstance = ctx->mModule->mCurTypeInstance;
+			BfTypeDef* commonOuterType;
+			if (typeRef == ctx->mRootTypeRef)
+				commonOuterType = FindRootCommonOuterType(elementTypeDef->mOuterType, ctx, checkTypeInstance);
+			else
+				commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, elementTypeDef->mOuterType);
+			
+			if ((commonOuterType != NULL) && (checkTypeInstance->IsGenericTypeInstance()))
 			{
-				auto parentTypeInstance = (BfTypeInstance*)ctx->mModule->mCurTypeInstance;
+				auto parentTypeInstance = checkTypeInstance;
 				int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size();
 				for (int i = 0; i < numParentGenericParams; i++)			
 					hashVal = ((hashVal ^ (Hash(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i], ctx))) << 5) - hashVal;
@@ -3252,7 +3307,11 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfType
 }
 
 bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* lhsTypeGenericArguments, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx)
-{	
+{
+	BfTypeInstance* rootOuterTypeInstance = ctx->mModule->mCurTypeInstance;
+	if ((rhsTypeDef == ctx->mRootTypeDef) && (ctx->mRootOuterTypeInstance != NULL))
+		rootOuterTypeInstance = ctx->mRootOuterTypeInstance;
+
 	auto rhsGenericTypeInstRef = BfNodeDynCastExact<BfGenericInstanceTypeRef>(rhs);
 	if (rhsGenericTypeInstRef == NULL)
 	{
@@ -3268,15 +3327,16 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfType
 			}
 		}
 
-		if ((rhsTypeDef != NULL) && (ctx->mModule->mCurTypeInstance != NULL))
+		if ((rhsTypeDef != NULL) && (rootOuterTypeInstance != NULL))
 		{
 			// See if we're referring to an non-generic inner type where the outer type is generic
 			if (lhsGenericType->mTypeDef != rhsTypeDef)
 				return false;
-			BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, rhsTypeDef->mOuterType);
+
+			BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(rootOuterTypeInstance->mTypeDef, rhsTypeDef->mOuterType);
 			if (commonOuterType != NULL)
 			{
-				BfTypeInstance* checkTypeInstance = ctx->mModule->mCurTypeInstance;
+				BfTypeInstance* checkTypeInstance = rootOuterTypeInstance;
 				if (checkTypeInstance->IsBoxed())
 					checkTypeInstance = checkTypeInstance->GetUnderlyingType()->ToTypeInstance();
 				BF_ASSERT(checkTypeInstance->IsGenericTypeInstance());
@@ -3307,12 +3367,12 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfType
 	int genericParamOffset = 0;
 
 	// Do we need to add generic arguments from an in-context outer class?
-	if ((elementTypeDef->mOuterType != NULL) && (ctx->mModule->mCurTypeInstance != NULL) && (ctx->mModule->mCurTypeInstance->IsGenericTypeInstance()))
+	if ((elementTypeDef->mOuterType != NULL) && (rootOuterTypeInstance != NULL) && (rootOuterTypeInstance->IsGenericTypeInstance()))
 	{
-		BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, elementTypeDef->mOuterType);
+		BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(rootOuterTypeInstance->mTypeDef, elementTypeDef->mOuterType);
 		if (commonOuterType != NULL)
 		{
-			auto parentTypeInstance = (BfTypeInstance*)ctx->mModule->mCurTypeInstance;
+			auto parentTypeInstance = rootOuterTypeInstance;
 			genericParamOffset = (int) commonOuterType->mGenericParamDefs.size();
 			for (int i = 0; i < genericParamOffset; i++)
 				for (auto genericArg : parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments)

+ 4 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -2328,6 +2328,7 @@ public:
 		BfModule* mModule;
 		BfTypeReference* mRootTypeRef;
 		BfTypeDef* mRootTypeDef;		
+		BfTypeInstance* mRootOuterTypeInstance;
 		BfType* mResolvedType;		
 		BfResolveTypeRefFlags mResolveFlags;
 		bool mFailed;		
@@ -2336,7 +2337,8 @@ public:
 		LookupContext()
 		{
 			mRootTypeRef = NULL;
-			mRootTypeDef = NULL;			
+			mRootTypeDef = NULL;
+			mRootOuterTypeInstance = NULL;
 			mModule = NULL;
 			mResolvedType = NULL;
 			mFailed = false;
@@ -2348,6 +2350,7 @@ public:
 	};
 
 public:
+	static BfTypeDef* FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outCheckTypeInstance);
 	static BfVariant EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& constGenericParam);
 	static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* lhsTypeGenericArguments, BfTypeReference* rhs, LookupContext* ctx, int& genericParamOffset);
 	static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* typeGenericArguments, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx);

+ 45 - 0
IDEHelper/Tests/src/UsingStatic.bf

@@ -0,0 +1,45 @@
+#pragma warning disable 168
+
+using static Tests.USOuter;
+using static Tests.USOuter.USInnerC<int>;
+
+namespace Tests
+{
+	class USOuter
+	{
+		public static int sVal0 = 123;
+
+		public class USInnerA
+		{
+			public class USInnerB<T>
+			{
+
+			}
+		}
+
+		public class USInnerC<T>
+		{
+			public class USInnerD
+			{
+
+			}
+
+			public class USInnerE<T2>
+			{
+
+			}
+		}
+	}
+
+	class UsingStatic
+	{
+		public static void TestBasics()
+		{
+			USInnerA innerA;
+			USInnerA.USInnerB<int> innerB;
+			int val = sVal0;
+			USInnerD id;
+			USInnerE<float> ie;
+		}
+	}
+}