From 6b27f0f0b2e113e96050f552b26215685f8f8011 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 14 Oct 2020 11:33:41 -0700 Subject: [PATCH] Internal protection, 'using internal ;` --- IDEHelper/Compiler/BfAst.cpp | 2 +- IDEHelper/Compiler/BfAst.h | 13 +- IDEHelper/Compiler/BfCompiler.cpp | 159 +++++++++++++++------ IDEHelper/Compiler/BfContext.cpp | 2 + IDEHelper/Compiler/BfDefBuilder.cpp | 19 ++- IDEHelper/Compiler/BfDefBuilder.h | 3 +- IDEHelper/Compiler/BfElementVisitor.cpp | 4 +- IDEHelper/Compiler/BfElementVisitor.h | 2 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 4 +- IDEHelper/Compiler/BfModule.cpp | 55 ++++++- IDEHelper/Compiler/BfModule.h | 6 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 78 +++++++--- IDEHelper/Compiler/BfNamespaceVisitor.cpp | 2 +- IDEHelper/Compiler/BfNamespaceVisitor.h | 2 +- IDEHelper/Compiler/BfPrinter.cpp | 4 +- IDEHelper/Compiler/BfPrinter.h | 2 +- IDEHelper/Compiler/BfReducer.cpp | 17 ++- IDEHelper/Compiler/BfResolvePass.h | 1 + IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 14 ++ IDEHelper/Compiler/BfResolvedTypeUtils.h | 10 ++ IDEHelper/Compiler/BfSourceClassifier.cpp | 2 +- IDEHelper/Compiler/BfSourceClassifier.h | 2 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 2 +- IDEHelper/Compiler/BfSystem.cpp | 3 + IDEHelper/Compiler/BfSystem.h | 1 + 25 files changed, 313 insertions(+), 96 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index e6bc8e21..17fa587b 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -631,7 +631,7 @@ void BfStructuralVisitor::Visit(BfUsingDirective* usingDirective) Visit(usingDirective->ToBase()); } -void BfStructuralVisitor::Visit(BfUsingStaticDirective * usingDirective) +void BfStructuralVisitor::Visit(BfUsingModDirective * usingDirective) { Visit(usingDirective->ToBase()); } diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index e66671f9..8394aa1e 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -52,6 +52,7 @@ enum BfProtection : uint8 { BfProtection_Hidden, BfProtection_Private, + BfProtection_Internal, BfProtection_Protected, BfProtection_Public }; @@ -335,7 +336,7 @@ class BfConstructorDeclaration; class BfDestructorDeclaration; class BfQualifiedTypeReference; class BfUsingDirective; -class BfUsingStaticDirective; +class BfUsingModDirective; class BfPropertyMethodDeclaration; class BfPropertyBodyExpression; class BfPropertyDeclaration; @@ -534,7 +535,7 @@ public: virtual void Visit(BfTypeDeclaration* typeDeclaration); virtual void Visit(BfTypeAliasDeclaration* typeDeclaration); virtual void Visit(BfUsingDirective* usingDirective); - virtual void Visit(BfUsingStaticDirective* usingDirective); + virtual void Visit(BfUsingModDirective* usingDirective); virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration); virtual void Visit(BfBlock* block); virtual void Visit(BfBlockExtension* block); @@ -1932,15 +1933,15 @@ public: BfIdentifierNode* mNamespace; }; BF_AST_DECL(BfUsingDirective, BfStatement); -class BfUsingStaticDirective : public BfStatement +class BfUsingModDirective : public BfStatement { public: - BF_AST_TYPE(BfUsingStaticDirective, BfStatement); + BF_AST_TYPE(BfUsingModDirective, BfStatement); BfTokenNode* mUsingToken; - BfTokenNode* mStaticToken; + BfTokenNode* mModToken; BfTypeReference* mTypeRef; -}; BF_AST_DECL(BfUsingStaticDirective, BfStatement); +}; BF_AST_DECL(BfUsingModDirective, BfStatement); class BfAttributeTargetSpecifier : public BfAstNode { diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 51cad01c..162f6905 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -3536,13 +3536,14 @@ void BfCompiler::VisitAutocompleteExteriorIdentifiers() { checkIdentifier = usingDirective->mNamespace; } - else if (auto usingDirective = BfNodeDynCast(checkNode)) + else if (auto usingDirective = BfNodeDynCast(checkNode)) { if (usingDirective->mTypeRef != NULL) { BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL); SetAndRestoreValue prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL); + SetAndRestoreValue prevIgnoreErrors(mContext->mScratchModule->mIgnoreErrors, true); mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, NULL); if (mResolvePassData->mAutoComplete != NULL) mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, isUsingDirective); @@ -3577,26 +3578,37 @@ void BfCompiler::VisitAutocompleteExteriorIdentifiers() } void BfCompiler::VisitSourceExteriorNodes() -{ +{ BP_ZONE("BfCompiler::VisitSourceExteriorNodes"); String str; Array namespaceParts; Array srcNodes; - std::function _AddName = [&](BfAstNode* node) + std::function _AddName = [&](BfAstNode* node, bool wantErrors) { + if (node == NULL) + return false; if (auto qualifiedName = BfNodeDynCast(node)) { - if (!_AddName(qualifiedName->mLeft)) + if (!_AddName(qualifiedName->mLeft, wantErrors)) return false; - if (!_AddName(qualifiedName->mRight)) + if (!_AddName(qualifiedName->mRight, wantErrors)) return false; + return true; } - else if (auto identifier = BfNodeDynCast(node)) + else if (auto qualifedTypeRef = BfNodeDynCast(node)) { - srcNodes.Add(identifier); + if (!_AddName(qualifedTypeRef->mLeft, wantErrors)) + return false; + if (!_AddName(qualifedTypeRef->mRight, wantErrors)) + return false; + return true; + } + else if ((node->IsA()) || (node->IsA())) + { + srcNodes.Add(node); str.Clear(); - identifier->ToString(str); + node->ToString(str); auto atom = mSystem->FindAtom(str); if (atom == NULL) { @@ -3607,14 +3619,44 @@ void BfCompiler::VisitSourceExteriorNodes() prevNamespace += "."; prevNamespace += part->mString; } - - if (prevNamespace.IsEmpty()) - mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", str.c_str()), identifier); - else - mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", str.c_str(), prevNamespace.c_str()), identifier); + if (wantErrors) + { + if (prevNamespace.IsEmpty()) + mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", str.c_str()), node); + else + mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", str.c_str(), prevNamespace.c_str()), node); + } return false; } namespaceParts.Add(atom); + return true; + } + return false; + }; + + auto _CheckNamespace = [&](BfParser* parser, bool wantErrors, bool& failed) + { + for (int i = 0; i < (int)namespaceParts.size(); i++) + { + BfAtomComposite checkNamespace; + checkNamespace.mParts = &namespaceParts[0]; + checkNamespace.mSize = i + 1; + + if (!mSystem->ContainsNamespace(checkNamespace, parser->mProject)) + { + failed = true; + BfAtomComposite prevNamespace; + prevNamespace.mParts = &namespaceParts[0]; + prevNamespace.mSize = i; + if (wantErrors) + { + if (i == 0) + mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", namespaceParts[i]->mString.ToString().c_str()), srcNodes[i]); + else + mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", namespaceParts[i]->mString.ToString().c_str(), prevNamespace.ToString().c_str()), srcNodes[i]); + } + return false; + } } return true; }; @@ -3633,44 +3675,44 @@ void BfCompiler::VisitSourceExteriorNodes() bool failed = false; for (auto node : parser->mParserData->mExteriorNodes) - { + { if (auto usingDirective = BfNodeDynCast(node)) { srcNodes.Clear(); namespaceParts.Clear(); - bool success = _AddName(usingDirective->mNamespace); - - for (int i = 0; i < (int)namespaceParts.size(); i++) - { - BfAtomComposite checkNamespace; - checkNamespace.mParts = &namespaceParts[0]; - checkNamespace.mSize = i + 1; - - if (!mSystem->ContainsNamespace(checkNamespace, parser->mProject)) - { - failed = true; - BfAtomComposite prevNamespace; - prevNamespace.mParts = &namespaceParts[0]; - prevNamespace.mSize = i; - if (i == 0) - mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", namespaceParts[i]->mString.ToString().c_str()), srcNodes[i]); - else - mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", namespaceParts[i]->mString.ToString().c_str(), prevNamespace.ToString().c_str()), srcNodes[i]); - break; - } - } + bool success = _AddName(usingDirective->mNamespace, true); + _CheckNamespace(parser, true, failed); } - else if (auto usingDirective = BfNodeDynCast(node)) + else if (auto usingDirective = BfNodeDynCast(node)) { if (usingDirective->mTypeRef != NULL) { BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL); - SetAndRestoreValue prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL); - mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity); - if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL)) - mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false); - return; + bool wasNamespace = false; + if (usingDirective->mModToken->mToken == BfToken_Internal) + { + srcNodes.Clear(); + namespaceParts.Clear(); + if (_AddName(usingDirective->mTypeRef, false)) + { + wasNamespace = _CheckNamespace(parser, false, failed); + } + } + if (!wasNamespace) + { + SetAndRestoreValue prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL); + + if (auto genericTypeRef = BfNodeDynCast(usingDirective->mTypeRef)) + { + mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity); + } + else + mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity); + + if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL)) + mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false); + } } } } @@ -3861,7 +3903,6 @@ void BfCompiler::ProcessAutocompleteTempType() } VisitSourceExteriorNodes(); - if (autoComplete->mResolveType == BfResolveType_GetFixits) { BfAstNode* conflictStart = NULL; @@ -3978,6 +4019,40 @@ void BfCompiler::ProcessAutocompleteTempType() } } } + BfInternalAccessSet* internalAccessSet = NULL; + if (mResolvePassData->mInternalAccessMap.TryAdd(tempTypeDef, NULL, &internalAccessSet)) + { + for (auto typeRef : tempTypeDef->mInternalAccessSet) + { + if ((typeRef->IsA()) || + (typeRef->IsA())) + { + String checkNamespaceStr; + typeRef->ToString(checkNamespaceStr); + BfAtomComposite checkNamespace; + if (mSystem->ParseAtomComposite(checkNamespaceStr, checkNamespace)) + { + if (mSystem->ContainsNamespace(checkNamespace, tempTypeDef->mProject)) + { + internalAccessSet->mNamespaces.Add(checkNamespace); + continue; + } + } + } + + BfType* type; + if (auto genericTypeRef = BfNodeDynCast(typeRef)) + type = mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(typeRef, BfPopulateType_Identity); + else + type = module->ResolveTypeRef(typeRef, NULL, BfPopulateType_Identity); + if (type != NULL) + { + auto typeInst = type->ToTypeInstance(); + if (typeInst != NULL) + internalAccessSet->mTypes.Add(typeInst); + } + } + } auto _FindAcutalTypeDef = [&](BfTypeDef* tempTypeDef) { diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 1fd4be56..65a15d97 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1004,6 +1004,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild } } + typeInst->ReleaseData(); type->mDefineState = BfTypeDefineState_Undefined; typeInst->mSpecializedMethodReferences.Clear(); typeInst->mLookupResults.Clear(); @@ -1040,6 +1041,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild } typeInst->mStaticSearchMap.Clear(); + typeInst->mInternalAccessMap.Clear(); typeInst->mInterfaces.Clear(); typeInst->mInterfaceMethodTable.Clear(); for (auto operatorInfo : typeInst->mOperatorInfo) diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index ce3ca80c..772bcf8b 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -375,6 +375,8 @@ BfProtection BfDefBuilder::GetProtection(BfTokenNode* protectionToken) return BfProtection_Public; if (protectionToken->GetToken() == BfToken_Protected) return BfProtection_Protected; + if (protectionToken->GetToken() == BfToken_Internal) + return BfProtection_Internal; return BfProtection_Private; } @@ -1437,6 +1439,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) mCurTypeDef->mNestDepth = outerTypeDef->mNestDepth + 1; mCurTypeDef->mNamespaceSearch = outerTypeDef->mNamespaceSearch; mCurTypeDef->mStaticSearch = outerTypeDef->mStaticSearch; + mCurTypeDef->mInternalAccessSet = outerTypeDef->mInternalAccessSet; for (auto outerGenericParamDef : outerTypeDef->mGenericParamDefs) { @@ -1457,6 +1460,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) BF_ASSERT(mCurTypeDef->mNamespaceSearch.size() == 0); mCurTypeDef->mNamespaceSearch = mNamespaceSearch; mCurTypeDef->mStaticSearch = mStaticSearch; + mCurTypeDef->mInternalAccessSet = mInternalAccessSet; } // We need to mix the namespace search into the signature hash because it can change how type references are resolved @@ -1465,10 +1469,10 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) mSystem->RefAtomComposite(usingName); mSignatureHashCtx->MixinStr(usingName.ToString()); } - for (auto& usingName : mCurTypeDef->mStaticSearch) - { + for (auto& usingName : mCurTypeDef->mStaticSearch) + HashNode(*mSignatureHashCtx, usingName); + for (auto& usingName : mCurTypeDef->mInternalAccessSet) HashNode(*mSignatureHashCtx, usingName); - } if ((typeDeclaration->mPartialSpecifier != NULL) && (!isAutoCompleteTempType)) { @@ -2227,12 +2231,17 @@ void BfDefBuilder::Visit(BfUsingDirective* usingDirective) mSystem->ReleaseAtomComposite(usingComposite); } -void BfDefBuilder::Visit(BfUsingStaticDirective* usingDirective) +void BfDefBuilder::Visit(BfUsingModDirective* usingDirective) { if (mResolvePassData != NULL) mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(usingDirective); - if (usingDirective->mTypeRef != NULL) + if (usingDirective->mModToken->mToken == BfToken_Internal) + { + if (usingDirective->mTypeRef != NULL) + mInternalAccessSet.Add(usingDirective->mTypeRef); + } + else if (usingDirective->mTypeRef != NULL) mStaticSearch.Add(usingDirective->mTypeRef); } diff --git a/IDEHelper/Compiler/BfDefBuilder.h b/IDEHelper/Compiler/BfDefBuilder.h index 48c8ad73..a638bf7d 100644 --- a/IDEHelper/Compiler/BfDefBuilder.h +++ b/IDEHelper/Compiler/BfDefBuilder.h @@ -22,6 +22,7 @@ public: BfAtomComposite mNamespace; Array mNamespaceSearch; Array mStaticSearch; + Array mInternalAccessSet; HashContext* mFullHashCtx; HashContext* mSignatureHashCtx; @@ -57,7 +58,7 @@ public: virtual void Visit(BfEnumCaseDeclaration* enumCaseDeclaration) override; virtual void Visit(BfTypeDeclaration* typeDeclaration) override; virtual void Visit(BfUsingDirective* usingDirective) override; - virtual void Visit(BfUsingStaticDirective* usingDirective) override; + virtual void Visit(BfUsingModDirective* usingDirective) override; virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration) override; virtual void Visit(BfBlock* block) override; virtual void Visit(BfRootNode* rootNode) override; diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 170dd86b..92c9b4b8 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -1172,12 +1172,12 @@ void BfElementVisitor::Visit(BfUsingDirective* usingDirective) VisitChild(usingDirective->mNamespace); } -void BfElementVisitor::Visit(BfUsingStaticDirective * usingDirective) +void BfElementVisitor::Visit(BfUsingModDirective* usingDirective) { Visit(usingDirective->ToBase()); VisitChild(usingDirective->mUsingToken); - VisitChild(usingDirective->mStaticToken); + VisitChild(usingDirective->mModToken); VisitChild(usingDirective->mTypeRef); } diff --git a/IDEHelper/Compiler/BfElementVisitor.h b/IDEHelper/Compiler/BfElementVisitor.h index 98c70cfa..f72e79e5 100644 --- a/IDEHelper/Compiler/BfElementVisitor.h +++ b/IDEHelper/Compiler/BfElementVisitor.h @@ -126,7 +126,7 @@ public: virtual void Visit(BfTypeDeclaration* typeDeclaration); virtual void Visit(BfTypeAliasDeclaration* typeDeclaration); virtual void Visit(BfUsingDirective* usingDirective); - virtual void Visit(BfUsingStaticDirective* usingDirective); + virtual void Visit(BfUsingModDirective* usingDirective); virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration); virtual void Visit(BfBlock* block); virtual void Visit(BfRootNode* rootNode); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index a4777844..04ea408f 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2460,7 +2460,7 @@ void BfMethodMatcher::CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, if (checkMethod->mName != mMethodName) continue; - if ((!isFailurePass) && (!mModule->CheckProtection(checkMethod->mProtection, allowProtected, allowPrivate))) + if ((!isFailurePass) && (!mModule->CheckProtection(checkMethod->mProtection, NULL, allowProtected, allowPrivate))) continue; CheckMethod(typeInstance, curTypeInst, checkMethod, isFailurePass); @@ -4059,7 +4059,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar bool isTemporary = target.IsTempAddr(); bool wantsLoadValue = false; bool wantsReadOnly = false; - if ((field->mIsReadOnly) && ((mModule->mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Ctor) || (!target.IsThis()))) + if ((field->mIsReadOnly) && (mModule->mCurMethodInstance != NULL) && ((mModule->mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Ctor) || (!target.IsThis()))) wantsReadOnly = true; bool isComposite = target.mType->IsComposite(); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 662ed30c..a11632fb 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2508,7 +2508,7 @@ void BfModule::SetIllegalExprSrcPos(BfSrcPosFlags flags) //SetIllegalSrcPos((BfSrcPosFlags)(flags | BfSrcPosFlag_Expression)); } -bool BfModule::CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate) +bool BfModule::CheckProtection(BfProtection protection, BfTypeDef* checkType, bool allowProtected, bool allowPrivate) { if ((protection == BfProtection_Public) || ((protection == BfProtection_Protected) && (allowProtected)) || @@ -2519,6 +2519,11 @@ bool BfModule::CheckProtection(BfProtection protection, bool allowProtected, boo mAttributeState->mUsed = true; return true; } + if ((protection == BfProtection_Internal) && (checkType != NULL)) + { + if (CheckInternalProtection(checkType)) + return true; + } return false; } @@ -2627,6 +2632,12 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me return true; } + if ((memberProtection == BfProtection_Internal) && (memberOwner != NULL)) + { + if (CheckInternalProtection(memberOwner->mTypeDef)) + return true; + } + return false; } @@ -3074,7 +3085,7 @@ void BfModule::NotImpl(BfAstNode* astNode) Fail("INTERNAL ERROR: Not implemented", astNode); } -bool BfModule::CheckAccessMemberProtection(BfProtection protection, BfType* memberType) +bool BfModule::CheckAccessMemberProtection(BfProtection protection, BfTypeInstance* memberType) { bool allowPrivate = (memberType == mCurTypeInstance) || (IsInnerType(mCurTypeInstance, memberType)); if (!allowPrivate) @@ -3083,7 +3094,7 @@ bool BfModule::CheckAccessMemberProtection(BfProtection protection, BfType* memb //TODO: We had this commented out, but this makes accessing protected properties fail if (mCurTypeInstance != NULL) allowProtected |= TypeIsSubTypeOf(mCurTypeInstance, memberType->ToTypeInstance()); - if (!CheckProtection(protection, allowProtected, allowPrivate)) + if (!CheckProtection(protection, memberType->mTypeDef, allowProtected, allowPrivate)) { return false; } @@ -3393,6 +3404,42 @@ BfStaticSearch* BfModule::GetStaticSearch() return NULL; } +BfInternalAccessSet* BfModule::GetInternalAccessSet() +{ + auto activeTypeDef = GetActiveTypeDef(); + BfInternalAccessSet* internalAccessSet = NULL; + if ((mCurTypeInstance != NULL) && (mCurTypeInstance->mInternalAccessMap.TryGetValue(activeTypeDef, &internalAccessSet))) + return internalAccessSet; + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mInternalAccessMap.TryGetValue(activeTypeDef, &internalAccessSet))) + return internalAccessSet; + return NULL; +} + +bool BfModule::CheckInternalProtection(BfTypeDef* usingTypeDef) +{ + auto internalAccessSet = GetInternalAccessSet(); + if (internalAccessSet == NULL) + return false; + + for (auto& nameComposite : internalAccessSet->mNamespaces) + { + if (usingTypeDef->mNamespace.StartsWith(nameComposite)) + return true; + } + + for (auto internalType : internalAccessSet->mTypes) + { + auto checkTypeDef = usingTypeDef; + while (checkTypeDef != NULL) + { + if (checkTypeDef == internalType->mTypeDef) + return true; + checkTypeDef = checkTypeDef->mOuterType; + } + } + return false; +} + void PrintUsers(llvm::MDNode* md); BfModuleOptions BfModule::GetModuleOptions() @@ -10688,7 +10735,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri if ((checkMethod->mIsStatic) || (checkMethod->mMethodType != BfMethodType_Ctor)) continue; - if ((!isFailurePass) && (!CheckProtection(checkMethod->mProtection, false, false))) + if ((!isFailurePass) && (!CheckProtection(checkMethod->mProtection, attrTypeInst->mTypeDef, false, false))) continue; methodMatcher.CheckMethod(NULL, attrTypeInst, checkMethod, isFailurePass); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index edca83ac..060ae301 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1458,7 +1458,7 @@ public: void FatalError(const StringImpl& error, const char* file = NULL, int line = -1); void NotImpl(BfAstNode* astNode); void AddMethodReference(const BfMethodRef& methodRef, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); - bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate); + bool CheckProtection(BfProtection protection, BfTypeDef* checkType, bool allowProtected, bool allowPrivate); void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate); bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType); void SetElementType(BfAstNode* astNode, BfSourceElementType elementType); @@ -1651,7 +1651,7 @@ public: void CheckInjectNewRevision(BfTypeInstance* typeInstance); void InitType(BfType* resolvedTypeRef, BfPopulateType populateType); BfProtection FixProtection(BfProtection protection, BfProject* defProject); - bool CheckAccessMemberProtection(BfProtection protection, BfType* memberType); + bool CheckAccessMemberProtection(BfProtection protection, BfTypeInstance* memberType); bool CheckDefineMemberProtection(BfProtection protection, BfType* memberType); void CheckMemberNames(BfTypeInstance* typeInst); void AddDependency(BfType* usedType, BfType* userType, BfDependencyMap::DependencyFlags flags); @@ -1661,6 +1661,8 @@ public: bool IsAttribute(BfTypeInstance* typeInst); void PopulateGlobalContainersList(const BfGlobalLookup& globalLookup); BfStaticSearch* GetStaticSearch(); + BfInternalAccessSet* GetInternalAccessSet(); + bool CheckInternalProtection(BfTypeDef* usingTypeDef); void AddFailType(BfTypeInstance* typeInstance); void MarkDerivedDirty(BfTypeInstance* typeInst); void CheckAddFailType(); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index f63383d1..266ff0c1 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2155,26 +2155,72 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } auto _AddStaticSearch = [&](BfTypeDef* typeDef) - { - if (typeDef->mStaticSearch.IsEmpty()) - return; - BfStaticSearch* staticSearch; - if (typeInstance->mStaticSearchMap.TryAdd(typeDef, NULL, &staticSearch)) + { + if (!typeDef->mStaticSearch.IsEmpty()) { - for (auto typeRef : typeDef->mStaticSearch) + BfStaticSearch* staticSearch; + if (typeInstance->mStaticSearchMap.TryAdd(typeDef, NULL, &staticSearch)) { - auto staticType = ResolveTypeRef(typeRef, NULL, BfPopulateType_Declaration); - if (staticType != NULL) + for (auto typeRef : typeDef->mStaticSearch) { - auto staticTypeInst = staticType->ToTypeInstance(); - if (staticTypeInst == NULL) + auto staticType = ResolveTypeRef(typeRef, NULL, BfPopulateType_Identity); + if (staticType != NULL) { - Fail(StrFormat("Type '%s' cannot be used in a 'using static' declaration", TypeToString(staticType).c_str()), typeRef); + auto staticTypeInst = staticType->ToTypeInstance(); + if (staticTypeInst == NULL) + { + Fail(StrFormat("Type '%s' cannot be used in a 'using static' declaration", TypeToString(staticType).c_str()), typeRef); + } + else + { + staticSearch->mStaticTypes.Add(staticTypeInst); + AddDependency(staticTypeInst, typeInstance, BfDependencyMap::DependencyFlag_StaticValue); + } } - else + } + } + } + if (!typeDef->mInternalAccessSet.IsEmpty()) + { + BfInternalAccessSet* internalAccessSet; + if (typeInstance->mInternalAccessMap.TryAdd(typeDef, NULL, &internalAccessSet)) + { + for (auto typeRef : typeDef->mInternalAccessSet) + { + if ((typeRef->IsA()) || + (typeRef->IsA())) { - staticSearch->mStaticTypes.Add(staticTypeInst); - AddDependency(staticTypeInst, typeInstance, BfDependencyMap::DependencyFlag_StaticValue); + String checkNamespaceStr; + typeRef->ToString(checkNamespaceStr); + BfAtomComposite checkNamespace; + if (mSystem->ParseAtomComposite(checkNamespaceStr, checkNamespace)) + { + if (mSystem->ContainsNamespace(checkNamespace, typeDef->mProject)) + { + mSystem->RefAtomComposite(checkNamespace); + internalAccessSet->mNamespaces.Add(checkNamespace); + continue; + } + } + } + + BfType* internalType = NULL; + if (auto genericTypeRef = BfNodeDynCast(typeRef)) + internalType = mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(typeRef, BfPopulateType_Identity); + else + internalType = ResolveTypeRef(typeRef, NULL, BfPopulateType_Identity); + if (internalType != NULL) + { + auto internalTypeInst = internalType->ToTypeInstance(); + if (internalTypeInst == NULL) + { + Fail(StrFormat("Type '%s' cannot be used in a 'using internal' declaration", TypeToString(internalType).c_str()), typeRef); + } + else + { + internalAccessSet->mTypes.Add(internalTypeInst); + AddDependency(internalTypeInst, typeInstance, BfDependencyMap::DependencyFlag_StaticValue); + } } } } @@ -5837,7 +5883,7 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, { auto latestCheckType = checkType->GetLatest(); - if ((!isFailurePass) && (!CheckProtection(latestCheckType->mProtection, allowProtected, allowPrivate))) + if ((!isFailurePass) && (!CheckProtection(latestCheckType->mProtection, latestCheckType, allowProtected, allowPrivate))) continue; if (checkType->mProject != checkOuterType->mTypeDef->mProject) @@ -9413,7 +9459,7 @@ BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, B BfTypeVector typeVector; for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++) typeVector.push_back(GetGenericParamType(BfGenericParamKind_Type, i)); - return ResolveTypeDef(genericTypeDef, typeVector); + return ResolveTypeDef(genericTypeDef, typeVector, populateType); } } diff --git a/IDEHelper/Compiler/BfNamespaceVisitor.cpp b/IDEHelper/Compiler/BfNamespaceVisitor.cpp index 80252f4a..a9ea2766 100644 --- a/IDEHelper/Compiler/BfNamespaceVisitor.cpp +++ b/IDEHelper/Compiler/BfNamespaceVisitor.cpp @@ -23,7 +23,7 @@ void BfNamespaceVisitor::Visit(BfUsingDirective* usingDirective) mResolvePassData->HandleNamespaceReference(usingDirective->mNamespace, usingComposite); } -void BfNamespaceVisitor::Visit(BfUsingStaticDirective* usingDirective) +void BfNamespaceVisitor::Visit(BfUsingModDirective* usingDirective) { BfAstNode* useNode = usingDirective->mTypeRef; BfAstNode* checkNode = usingDirective->mTypeRef; diff --git a/IDEHelper/Compiler/BfNamespaceVisitor.h b/IDEHelper/Compiler/BfNamespaceVisitor.h index 0f59dca5..89edd11a 100644 --- a/IDEHelper/Compiler/BfNamespaceVisitor.h +++ b/IDEHelper/Compiler/BfNamespaceVisitor.h @@ -22,7 +22,7 @@ public: } virtual void Visit(BfUsingDirective* usingDirective) override; - virtual void Visit(BfUsingStaticDirective* usingDirective) override; + virtual void Visit(BfUsingModDirective* usingDirective) override; virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration) override; virtual void Visit(BfBlock* block) override; virtual void Visit(BfRootNode* rootNode) override; diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index e87b3767..f2b85e02 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2755,12 +2755,12 @@ void BfPrinter::Visit(BfUsingDirective* usingDirective) ExpectNewLine(); } -void BfPrinter::Visit(BfUsingStaticDirective * usingDirective) +void BfPrinter::Visit(BfUsingModDirective* usingDirective) { ExpectNewLine(); VisitChild(usingDirective->mUsingToken); ExpectSpace(); - VisitChild(usingDirective->mStaticToken); + VisitChild(usingDirective->mModToken); ExpectSpace(); VisitChild(usingDirective->mTypeRef); diff --git a/IDEHelper/Compiler/BfPrinter.h b/IDEHelper/Compiler/BfPrinter.h index e1ab6e09..0bf6c6d9 100644 --- a/IDEHelper/Compiler/BfPrinter.h +++ b/IDEHelper/Compiler/BfPrinter.h @@ -217,7 +217,7 @@ public: virtual void Visit(BfTypeAliasDeclaration* typeDeclaration) override; virtual void Visit(BfTypeDeclaration* typeDeclaration) override; virtual void Visit(BfUsingDirective* usingDirective) override; - virtual void Visit(BfUsingStaticDirective* usingDirective) override; + virtual void Visit(BfUsingModDirective* usingDirective) override; virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration) override; virtual void Visit(BfBlock* block) override; virtual void Visit(BfRootNode* rootNode) override; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index bd72c59c..deefcad9 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -5957,6 +5957,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, int depth, BfAstNod case BfToken_Public: case BfToken_Protected: case BfToken_Private: + case BfToken_Internal: case BfToken_Virtual: case BfToken_Override: case BfToken_Abstract: @@ -6024,7 +6025,8 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, int depth, BfAstNod if ((token == BfToken_Public) || (token == BfToken_Protected) || - (token == BfToken_Private)) + (token == BfToken_Private) || + (token == BfToken_Internal)) { if (memberDecl->mProtectionSpecifier != NULL) { @@ -6246,7 +6248,8 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf token = tokenNode->GetToken(); if ((token == BfToken_Private) || (token == BfToken_Protected) || - (token == BfToken_Public)) + (token == BfToken_Public) || + (token == BfToken_Internal)) { if (protectionSpecifier != NULL) { @@ -7905,13 +7908,13 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi { if (auto nextTokenNode = BfNodeDynCast(mVisitorPos.GetNext())) { - if (nextTokenNode->mToken == BfToken_Static) + if ((nextTokenNode->mToken == BfToken_Static) || (nextTokenNode->mToken == BfToken_Internal)) { - auto usingDirective = mAlloc->Alloc(); + auto usingDirective = mAlloc->Alloc(); ReplaceNode(tokenNode, usingDirective); usingDirective->mUsingToken = tokenNode; - MEMBER_SET(usingDirective, mStaticToken, nextTokenNode); + MEMBER_SET(usingDirective, mModToken, nextTokenNode); mVisitorPos.MoveNext(); auto typeRef = CreateTypeRefAfter(usingDirective); @@ -8029,6 +8032,7 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi case BfToken_Public: case BfToken_Private: case BfToken_Protected: + case BfToken_Internal: case BfToken_Static: { auto nextNode = mVisitorPos.GetNext(); @@ -8078,7 +8082,8 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi BfToken token = tokenNode->GetToken(); if ((token == BfToken_Public) || (token == BfToken_Protected) || - (token == BfToken_Private)) + (token == BfToken_Private) || + (token == BfToken_Internal)) { if (typeDeclaration->mProtectionSpecifier != NULL) { diff --git a/IDEHelper/Compiler/BfResolvePass.h b/IDEHelper/Compiler/BfResolvePass.h index 24de4ffb..383a9db9 100644 --- a/IDEHelper/Compiler/BfResolvePass.h +++ b/IDEHelper/Compiler/BfResolvePass.h @@ -48,6 +48,7 @@ public: BfAutoComplete* mAutoComplete; Array mAutoCompleteTempTypes; // Contains multiple values when we have nested types Dictionary mStaticSearchMap; + Dictionary mInternalAccessMap; BfSourceClassifier* mSourceClassifier; Array mExteriorAutocompleteCheckNodes; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index ea1f1179..a974344e 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1411,6 +1411,7 @@ BfMethodInstanceGroup::~BfMethodInstanceGroup() BfTypeInstance::~BfTypeInstance() { + ReleaseData(); delete mTypeInfoEx; delete mGenericTypeInfo; delete mCustomAttributes; @@ -1423,6 +1424,17 @@ BfTypeInstance::~BfTypeInstance() delete mConstHolder; } +void BfTypeInstance::ReleaseData() +{ + for (auto& kv : mInternalAccessMap) + { + auto& internalAcessSet = kv.mValue; + for (auto& namespaceComposite : internalAcessSet.mNamespaces) + mModule->mSystem->ReleaseAtomComposite(namespaceComposite); + } + mInternalAccessMap.Clear(); +} + int BfTypeInstance::GetSplatCount() { if (IsValuelessType()) @@ -2797,6 +2809,8 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outOuterTypeInstance) { + if (ctx->mModule->mCurTypeInstance == NULL) + return NULL; BfTypeDef* commonOuterType = ctx->mModule->FindCommonOuterType(ctx->mModule->mCurTypeInstance->mTypeDef, outerType); if ((commonOuterType == NULL) && (outerType != NULL)) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 0463096b..5ddf3160 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1654,6 +1654,13 @@ public: Array mStaticTypes; }; +class BfInternalAccessSet +{ +public: + Array mTypes; + Array mNamespaces; +}; + class BfTypeInfoEx { public: @@ -1760,6 +1767,7 @@ public: Array mFieldInstances; Array mInternalMethods; Dictionary mStaticSearchMap; + Dictionary mInternalAccessMap; bool mHasStaticInitMethod; bool mHasStaticDtorMethod; bool mHasStaticMarkMethod; @@ -1854,6 +1862,8 @@ public: } ~BfTypeInstance(); + + void ReleaseData(); virtual bool IsInstanceOf(BfTypeDef* typeDef) override { return typeDef == mTypeDef; } virtual BfModule* GetModule() override { return mModule; } diff --git a/IDEHelper/Compiler/BfSourceClassifier.cpp b/IDEHelper/Compiler/BfSourceClassifier.cpp index 068ada0e..c9bbecda 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.cpp +++ b/IDEHelper/Compiler/BfSourceClassifier.cpp @@ -664,7 +664,7 @@ void BfSourceClassifier::Visit(BfUsingDirective* usingDirective) } } -void BfSourceClassifier::Visit(BfUsingStaticDirective* usingDirective) +void BfSourceClassifier::Visit(BfUsingModDirective* usingDirective) { BfElementVisitor::Visit(usingDirective); } diff --git a/IDEHelper/Compiler/BfSourceClassifier.h b/IDEHelper/Compiler/BfSourceClassifier.h index 9fc596b7..aeea9b5f 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.h +++ b/IDEHelper/Compiler/BfSourceClassifier.h @@ -120,7 +120,7 @@ public: virtual void Visit(BfTypeDeclaration* typeDeclaration) override; virtual void Visit(BfTypeAliasDeclaration* typeDeclaration) override; virtual void Visit(BfUsingDirective* usingDirective) override; - virtual void Visit(BfUsingStaticDirective* usingDirective) override; + virtual void Visit(BfUsingModDirective* usingDirective) override; virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration) override; virtual void Visit(BfBlock* block) override; virtual void Visit(BfRootNode* rootNode) override; diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index b51038b7..7fba147a 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3923,7 +3923,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) auto checkTypeDef = checkTypeInst->mTypeDef; if (checkTypeDef->mDtorDef != NULL) { - if (!CheckProtection(checkTypeDef->mDtorDef->mProtection, allowProtected, allowPrivate)) + if (!CheckProtection(checkTypeDef->mDtorDef->mProtection, checkTypeInst->mTypeDef, allowProtected, allowPrivate)) { auto error = Fail(StrFormat("'%s.~this()' is inaccessible due to its protection level", TypeToString(checkTypeInst).c_str()), deleteStmt->mExpression); // CS0122 } diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 54337b48..002b5ee8 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -657,6 +657,7 @@ void BfTypeDef::FreeMembers() mNamespaceSearch.Clear(); mStaticSearch.Clear(); + mInternalAccessSet.Clear(); for (auto allocNode : mDirectAllocNodes) delete allocNode; @@ -832,6 +833,7 @@ void BfTypeDef::ReportMemory(MemReporter* memReporter) memReporter->Add(sizeof(BfTypeDef)); memReporter->AddVec(mNamespaceSearch, false); memReporter->AddVec(mStaticSearch, false); + memReporter->AddVec(mInternalAccessSet, false); memReporter->AddVecPtr("Fields", mFields, false); memReporter->AddVecPtr("Properties", mProperties, false); @@ -2656,6 +2658,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) RefAtomComposite(name); typeDef->mStaticSearch = nextTypeDef->mStaticSearch; + typeDef->mInternalAccessSet = nextTypeDef->mInternalAccessSet; for (auto prevField : typeDef->mFields) { diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index a1aadfc7..beb4cbf1 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -885,6 +885,7 @@ public: BfProtection mProtection; Array mNamespaceSearch; Array mStaticSearch; + Array mInternalAccessSet; Array mFields; Array mProperties; Array mMethods;