From fa65029dfa212d76939d08d65dda0f8272ffc320 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 31 Dec 2020 09:56:51 -0800 Subject: [PATCH] Fixed false signature change with multiple extensions --- BeefySysLib/util/String.cpp | 18 ++++++++ BeefySysLib/util/String.h | 30 ++++++++++++ IDEHelper/Compiler/BfAst.cpp | 9 ++++ IDEHelper/Compiler/BfAst.h | 1 + IDEHelper/Compiler/BfDefBuilder.cpp | 71 ++++++++++++++++++++++++++--- IDEHelper/Compiler/BfDefBuilder.h | 1 + IDEHelper/Compiler/BfSystem.h | 33 +++++++++++++- 7 files changed, 155 insertions(+), 8 deletions(-) diff --git a/BeefySysLib/util/String.cpp b/BeefySysLib/util/String.cpp index 29488442..c65fee26 100644 --- a/BeefySysLib/util/String.cpp +++ b/BeefySysLib/util/String.cpp @@ -67,6 +67,24 @@ bool StringView::operator!=(const StringImpl& strB) const return strncmp(this->mPtr, strB.GetPtr(), this->mLength) != 0; } +bool StringView::StartsWith(const StringView& b, StringView::CompareKind comparisonType) const +{ + if (this->mLength < b.mLength) + return false; + if (comparisonType == String::CompareKind_OrdinalIgnoreCase) + return String::EqualsIgnoreCaseHelper(mPtr, b.mPtr, b.mLength); + return String::EqualsHelper(mPtr, b.mPtr, b.mLength); +} + +bool StringView::EndsWith(const StringView& b, StringView::CompareKind comparisonType) const +{ + if (this->mLength < b.mLength) + return false; + if (comparisonType == String::CompareKind_OrdinalIgnoreCase) + return String::EqualsIgnoreCaseHelper(this->mPtr + this->mLength - b.mLength, b.mPtr, b.mLength); + return String::EqualsHelper(this->mPtr + this->mLength - b.mLength, b.mPtr, b.mLength); +} + intptr StringView::IndexOf(const StringView& subStr, bool ignoreCase) const { for (intptr ofs = 0; ofs <= mLength - subStr.mLength; ofs++) diff --git a/BeefySysLib/util/String.h b/BeefySysLib/util/String.h index e51d6fc8..f86cf312 100644 --- a/BeefySysLib/util/String.h +++ b/BeefySysLib/util/String.h @@ -16,6 +16,17 @@ struct StringSplitEnumerator; class StringView { +public: + enum CompareKind + { + CompareKind_CurrentCulture = 0, + CompareKind_CurrentCultureIgnoreCase = 1, + CompareKind_InvariantCulture = 2, + CompareKind_InvariantCultureIgnoreCase = 3, + CompareKind_Ordinal = 4, + CompareKind_OrdinalIgnoreCase = 5, + }; + public: const char* mPtr; intptr mLength; @@ -253,6 +264,23 @@ public: return mLength; } + bool StartsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const; + bool EndsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const; + + bool StartsWith(char c) const + { + if (this->mLength == 0) + return false; + return this->mPtr[0] == c; + } + + bool EndsWith(char c) const + { + if (this->mLength == 0) + return false; + return this->mPtr[this->mLength - 1] == c; + } + intptr IndexOf(const StringView& subStr, bool ignoreCase = false) const; intptr IndexOf(const StringView& subStr, int32 startIdx) const; intptr IndexOf(const StringView& subStr, int64 startIdx) const; @@ -488,6 +516,8 @@ public: CompareKind_OrdinalIgnoreCase = 5, }; + friend class StringView; + public: typedef int int_strsize; diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 3b8d9315..15e35451 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -1006,6 +1006,15 @@ bool BfAstNode::Equals(const StringImpl& str) return strncmp(str.GetPtr(), source->mSrc + mSrcStart, len) == 0; } +bool BfAstNode::Equals(const StringView& str) +{ + int len = mSrcEnd - mSrcStart; + if (len != str.mLength) + return false; + auto source = GetSourceData(); + return strncmp(str.mPtr, source->mSrc + mSrcStart, len) == 0; +} + bool BfAstNode::Equals(const char* str) { auto source = GetSourceData(); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 0592993b..9f3178c5 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -1090,6 +1090,7 @@ public: StringView ToStringView(); void ToString(StringImpl& str); bool Equals(const StringImpl& str); + bool Equals(const StringView& str); bool Equals(const char* str); void Init(BfParser* bfParser); void Accept(BfStructuralVisitor* bfVisitor); diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index d9a9bda8..cdbf2ad7 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -1262,6 +1262,57 @@ void BfDefBuilder::AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, co methodDef->mParams.push_back(paramDef); } +BfTypeDef* BfDefBuilder::ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* checkTypeDef) +{ + if (!mCurTypeDef->IsExtension()) + return prevTypeDef; + + BF_ASSERT(mCurTypeDef->mGenericParamDefs.size() == prevTypeDef->mGenericParamDefs.size()); + BF_ASSERT(mCurTypeDef->mGenericParamDefs.size() == checkTypeDef->mGenericParamDefs.size()); + + bool prevMatches = true; + bool checkMatches = true; + + for (int genericParamIdx = 0; genericParamIdx < (int)mCurTypeDef->mGenericParamDefs.size(); genericParamIdx++) + { + BfGenericParamDef* paramDef = mCurTypeDef->mGenericParamDefs[genericParamIdx]; + BfGenericParamDef* prevParamDef = prevTypeDef->mGenericParamDefs[genericParamIdx]; + BfGenericParamDef* checkParamDef = checkTypeDef->mGenericParamDefs[genericParamIdx]; + + if (*paramDef != *prevParamDef) + prevMatches = false; + if (*paramDef != *checkParamDef) + checkMatches = false; + } + + if (mCurTypeDef->mExternalConstraints.mSize == prevTypeDef->mExternalConstraints.mSize) + { + for (int constraintIdx = 0; constraintIdx < mCurTypeDef->mExternalConstraints.mSize; constraintIdx++) + { + if (mCurTypeDef->mExternalConstraints[constraintIdx] != prevTypeDef->mExternalConstraints[constraintIdx]) + prevMatches = false; + } + } + else + prevMatches = false; + + if (mCurTypeDef->mExternalConstraints.mSize == checkTypeDef->mExternalConstraints.mSize) + { + for (int constraintIdx = 0; constraintIdx < mCurTypeDef->mExternalConstraints.mSize; constraintIdx++) + { + if (mCurTypeDef->mExternalConstraints[constraintIdx] != checkTypeDef->mExternalConstraints[constraintIdx]) + checkMatches = false; + } + } + else + checkMatches = false; + + if ((!prevMatches) && (checkMatches)) + return checkTypeDef; + + return prevTypeDef; +} + void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) { BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData); @@ -1374,7 +1425,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) SetAndRestoreValue prevFullHashCtx(mFullHashCtx, &fullHashCtx); SetAndRestoreValue prevSignatureHashCtx(mSignatureHashCtx, &signatureHashCtx); - + if (bfParser != NULL) { mFullHashCtx->MixinStr(bfParser->mFileName); @@ -1627,6 +1678,12 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) } } + int outerGenericSize = 0; + if (mCurTypeDef->mOuterType != NULL) + outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size(); + bool isGeneric = (outerGenericSize != 0) || (typeDeclaration->mGenericParams != NULL); + ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, &mCurTypeDef->mExternalConstraints, outerGenericSize, isGeneric); + if (!isAutoCompleteTempType) { BfTypeDef* prevDef = NULL; @@ -1670,6 +1727,12 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) prevRevisionTypeDef = checkTypeDef; prevDef = checkTypeDef; } + else + { + auto bestTypeDef = ComparePrevTypeDef(prevRevisionTypeDef, checkTypeDef); + prevRevisionTypeDef = bestTypeDef; + prevDef = bestTypeDef; + } } } else @@ -1731,12 +1794,6 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) BfLogSysM("Creating TypeDef %p Hash:%d from TypeDecl: %p Source: %p ResolvePass: %d AutoComplete:%d\n", mCurTypeDef, mSystem->mTypeDefs.GetHash(mCurTypeDef), typeDeclaration, typeDeclaration->GetSourceData(), mResolvePassData != NULL, isAutoCompleteTempType); - - int outerGenericSize = 0; - if (mCurTypeDef->mOuterType != NULL) - outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size(); - bool isGeneric = (outerGenericSize != 0) || (typeDeclaration->mGenericParams != NULL); - ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, &mCurTypeDef->mExternalConstraints, outerGenericSize, isGeneric); BF_ASSERT(mCurTypeDef->mNameEx == NULL); diff --git a/IDEHelper/Compiler/BfDefBuilder.h b/IDEHelper/Compiler/BfDefBuilder.h index a351ee78..21dd2c97 100644 --- a/IDEHelper/Compiler/BfDefBuilder.h +++ b/IDEHelper/Compiler/BfDefBuilder.h @@ -37,6 +37,7 @@ public: static BfMethodDef* AddDtor(BfTypeDef* typeDef); static void AddDynamicCastMethods(BfTypeDef* typeDef); void AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName); + BfTypeDef* ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* checkTypeDef); void FinishTypeDef(bool wantsToString); void ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef); void ParseAttributes(BfAttributeDirective* attributes, BfTypeDef* typeDef); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 2702338e..c2f83db9 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -628,13 +628,44 @@ public: { mGenericParamFlags = BfGenericParamFlag_None; } + + bool operator==(const BfConstraintDef& other) const + { + if (mGenericParamFlags != other.mGenericParamFlags) + return false; + if (mConstraints.mSize != other.mConstraints.mSize) + return false; + for (int i = 0; i < mConstraints.mSize; i++) + { + if (!mConstraints[i]->Equals(other.mConstraints[i]->ToStringView())) + return false; + } + return true; + } + + bool operator!=(const BfConstraintDef& other) const + { + return !(*this == other); + } }; class BfGenericParamDef : public BfConstraintDef { public: String mName; - Array mNameNodes; // 0 is always the def name + Array mNameNodes; // 0 is always the def name + + bool operator==(const BfGenericParamDef& other) const + { + if (mName != other.mName) + return false; + return *(BfConstraintDef*)this == *(BfConstraintDef*)&other; + } + + bool operator!=(const BfGenericParamDef& other) const + { + return !(*this == other); + } }; class BfExternalConstraintDef : public BfConstraintDef