Преглед изворни кода

Better handling of merge conflict markers

Brian Fiete пре 5 година
родитељ
комит
c76c19e852
3 измењених фајлова са 185 додато и 31 уклоњено
  1. 61 0
      IDEHelper/Compiler/BfCompiler.cpp
  2. 123 30
      IDEHelper/Compiler/BfParser.cpp
  3. 1 1
      IDEHelper/Compiler/BfParser.h

+ 61 - 0
IDEHelper/Compiler/BfCompiler.cpp

@@ -3856,6 +3856,67 @@ void BfCompiler::ProcessAutocompleteTempType()
 	}	
 	VisitSourceExteriorNodes();
 
+
+	if (autoComplete->mResolveType == BfResolveType_GetFixits)
+	{
+		BfAstNode* conflictStart = NULL;
+		BfAstNode* conflictSplit = NULL;		
+
+		auto src = mResolvePassData->mParser->mSrc;
+
+		for (int checkIdx = 0; checkIdx < (int)mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mSize; checkIdx++)
+		{
+			auto sideNode = mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mVals[checkIdx];
+			if (autoComplete->CheckFixit(sideNode))
+			{
+				if (src[sideNode->mSrcStart] == '<')
+				{
+					conflictStart = sideNode;
+					conflictSplit = NULL;
+				}				
+			}
+			else
+			{
+				if (src[sideNode->mSrcStart] == '<')
+				{
+					conflictStart = NULL;
+					conflictSplit = NULL;
+				}
+				else if (src[sideNode->mSrcStart] == '=')
+				{
+					if (conflictStart != NULL)
+						conflictSplit = sideNode;
+				}
+				else if (src[sideNode->mSrcStart] == '>')
+				{
+					if (conflictSplit != NULL)
+					{
+						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept First\tdelete|%s-%d|\x01""delete|%s-%d|",
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), sideNode->mSrcEnd - conflictSplit->mSrcStart + 1,
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+
+						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Second\tdelete|%s-%d|\x01""delete|%s-%d|",
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+
+						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Both\tdelete|%s-%d|\x01""delete|%s-%d|\x01""delete|%s-%d|",
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictSplit->mSrcStart + 1,
+							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+
+						conflictStart = NULL;
+						conflictSplit = NULL;
+					}
+				}
+			}
+		}
+
+		for (auto sideNode : mResolvePassData->mParser->mSidechannelRootNode->mChildArr)
+		{
+			
+		}
+	}
+
 	if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
 	{
 		BfNamespaceVisitor namespaceVisitor;

+ 123 - 30
IDEHelper/Compiler/BfParser.cpp

@@ -885,8 +885,8 @@ void BfParser::HandleIncludeNext(BfAstNode* paramNode)
 
 }
 
-void BfParser::HandlePreprocessor()
-{
+bool BfParser::HandlePreprocessor()
+{	
 	int triviaStart = mTriviaStart;
 
 	int checkIdx = 0;
@@ -896,6 +896,8 @@ void BfParser::HandlePreprocessor()
 		{
 			if (mPreprocessorIgnoreDepth == 0)
 			{
+				if (mSrc[mSrcIdx - 1] != '#')
+					return false;
 				mPassInstance->FailAt("Preprocessor directives must appear as the first non-whitespace character on a line", mSourceData, checkIdx);
 				break;
 			}
@@ -907,6 +909,25 @@ void BfParser::HandlePreprocessor()
 	String pragma;
 	String pragmaParam;
 
+	switch (mSrc[mSrcIdx - 1])
+	{	
+	case '<':
+		if (mPreprocessorIgnoreDepth > 0)
+			return false;
+		pragma = "<<<";
+		break;
+	case '=':
+		if (mPreprocessorIgnoreDepth > 0)
+			return false;
+		pragma = "===";	
+		break;	
+	case '>':
+		if (mPreprocessorIgnoreDepth > 1)
+			return false;		
+		pragma = ">>>";
+		break;
+	}
+	
 	bool atEnd = false;
 
 	int startIdx = mSrcIdx - 1;
@@ -945,8 +966,16 @@ void BfParser::HandlePreprocessor()
 
 		if (charIdx == -1)
 		{
-			if (!IsWhitespaceOrPunctuation(c))
-				charIdx = mSrcIdx - 1;
+			if (!pragma.IsEmpty())
+			{
+				if (!IsWhitespace(c))
+					charIdx = mSrcIdx - 1;
+			}
+			else
+			{
+				if (!IsWhitespaceOrPunctuation(c))
+					charIdx = mSrcIdx - 1;
+			}
 		}
 		else if ((IsWhitespaceOrPunctuation(c)) && (spaceIdx == -1))
 			spaceIdx = mSrcIdx - 1;
@@ -955,7 +984,7 @@ void BfParser::HandlePreprocessor()
 	if (charIdx == -1)
 	{
 		mPassInstance->FailAt("Preprocessor directive expected", mSourceData, startIdx);
-		return;
+		return true;
 	}
 
 	int endIdx = mSrcIdx - 1;
@@ -967,25 +996,32 @@ void BfParser::HandlePreprocessor()
 	}
 
 	BfBlock* paramNode = NULL;
-	if (spaceIdx != -1)
-	{
-		pragma = String(mSrc + charIdx, mSrc + spaceIdx);
-		int breakIdx = spaceIdx;
-		while (spaceIdx <= endIdx)
+	if (pragma.IsEmpty())
+	{		
+		if (spaceIdx != -1)
 		{
-			if (!isspace((uint8)mSrc[spaceIdx]))
-				break;
-			spaceIdx++;
-		}
-		if (spaceIdx <= endIdx)
-			pragmaParam = String(mSrc + spaceIdx, mSrc + endIdx + 1);
+			pragma = String(mSrc + charIdx, mSrc + spaceIdx);
+			int breakIdx = spaceIdx;
+			while (spaceIdx <= endIdx)
+			{
+				if (!isspace((uint8)mSrc[spaceIdx]))
+					break;
+				spaceIdx++;
+			}
+			if (spaceIdx <= endIdx)
+				pragmaParam = String(mSrc + spaceIdx, mSrc + endIdx + 1);
 
-		paramNode = ParseInlineBlock(breakIdx, endIdx);
+			paramNode = ParseInlineBlock(breakIdx, endIdx);
+		}
+		else
+		{
+			pragma = String(mSrc + charIdx, mSrc + endIdx + 1);
+			mSrcIdx = endIdx + 1;
+		}
 	}
 	else
 	{
-		pragma = String(mSrc + charIdx, mSrc + endIdx + 1);
-		mSrcIdx = endIdx + 1;
+		mSrcIdx--;
 	}
 
 	bool wantsSingleParam = true;
@@ -997,11 +1033,11 @@ void BfParser::HandlePreprocessor()
 		BF_ASSERT(!mPreprocessorNodeStack.empty());
 
 		int ignoreEnd = std::max(mPreprocessorIgnoredSectionNode->GetSrcStart(), mLineStart - 1);
-		if (pragma == "endif")
+		if ((pragma == "endif") || (pragma == ">>>"))
 		{
 			mPreprocessorIgnoreDepth--;
 			if (mPreprocessorIgnoreDepth > 0)
-				return;
+				return true;
 			mPreprocessorNodeStack.pop_back();
 			mPreprocessorIgnoredSectionNode->SetSrcEnd(ignoreEnd);
 			mPreprocessorIgnoredSectionNode = NULL;
@@ -1037,7 +1073,7 @@ void BfParser::HandlePreprocessor()
 						{
 							mPreprocessorIgnoredSectionStarts.insert(mSrcIdx);
 						}
-						return;
+						return true;
 					}
 				}
 			}
@@ -1077,18 +1113,24 @@ void BfParser::HandlePreprocessor()
 		}
 
 		if (mPreprocessorIgnoreDepth > 0)
-			return;
+			return true;
 	}
 	else
 	{
-		if ((pragma == "if") ||
+		if ((pragma == "if") || (pragma == "<<<") ||
 			((mCompatMode) && (pragma == "ifdef")) ||
 			((mCompatMode) && (pragma == "ifndef")))
 		{
 			wantsSingleParam = false;
 			wantedParam = true;
 			bool found = false;
-			if (!mQuickCompatMode)
+			if (pragma == "<<<")
+			{
+				mPassInstance->FailAt("Conflict marker found", mSourceData, startIdx, endIdx - startIdx + 1);
+				wantedParam = false;
+				found = true;
+			}
+			else if (!mQuickCompatMode)
 			{
 				if (pragma == "if")
 					found = HandleProcessorCondition(paramNode) != MaybeBool_False;
@@ -1108,7 +1150,7 @@ void BfParser::HandlePreprocessor()
 				mPreprocessorIgnoreDepth = 1;
 			}
 		}
-		else if (pragma == "else")
+		else if ((pragma == "else") || (pragma == "==="))
 		{
 			if (!mQuickCompatMode && !mCompleteParse)
 			{
@@ -1251,6 +1293,8 @@ void BfParser::HandlePreprocessor()
 		mSidechannelRootNode->Add(mPreprocessorIgnoredSectionNode);
 		mPendingSideNodes.push_back(mPreprocessorIgnoredSectionNode);
 	}
+
+	return true;
 }
 
 static int ValSign(int64 val)
@@ -1350,7 +1394,11 @@ void BfParser::NextToken(int endIdx)
 				break;
 			}
 
-			if ((c != '#') || (!isLineStart))
+			if ((c == '>') && (mSrc[mSrcIdx] == '>') && (mSrc[mSrcIdx + 1] == '>'))
+			{
+				// Allow through
+			}
+			else if ((c != '#') || (!isLineStart))
 			{
 				if (c == '\n')
 				{
@@ -1393,9 +1441,26 @@ void BfParser::NextToken(int endIdx)
 			{
 				if (mSrc[mSrcIdx + 1] == '=')
 				{
-					mToken = BfToken_CompareStrictEquals;
-					++mSrcIdx;
-					mTokenEnd = ++mSrcIdx;
+					if (mSrc[mSrcIdx + 2] == '=')
+					{						
+						if (HandlePreprocessor())
+						{
+							// Conflict split
+							break;
+						}
+						else
+						{
+							mToken = BfToken_CompareStrictEquals;
+							++mSrcIdx;
+							mTokenEnd = ++mSrcIdx;
+						}
+					}
+					else
+					{
+						mToken = BfToken_CompareStrictEquals;
+						++mSrcIdx;
+						mTokenEnd = ++mSrcIdx;
+					}
 				}
 				else
 				{
@@ -1526,6 +1591,20 @@ void BfParser::NextToken(int endIdx)
 					mToken = BfToken_ShiftLeftEquals;
 					mTokenEnd = ++mSrcIdx;
 				}
+				else if (mSrc[mSrcIdx] == '<')
+				{
+					mSrcIdx--;
+					if (HandlePreprocessor())
+					{
+						// Conflict end
+						break;
+					}
+					else
+					{
+						mSrcIdx++;
+						mToken = BfToken_LDblChevron;
+					}
+				}
 				else
 					mToken = BfToken_LDblChevron;
 			}
@@ -1556,6 +1635,20 @@ void BfParser::NextToken(int endIdx)
 					mToken = BfToken_ShiftRightEquals;
 					mTokenEnd = ++mSrcIdx;
 				}
+				else if (mSrc[mSrcIdx] == '>')
+				{
+					mSrcIdx--;
+					if (HandlePreprocessor())
+					{
+						// Conflict start
+						break;
+					}
+					else
+					{
+						mSrcIdx++;
+						mToken = BfToken_RDblChevron;
+					}
+				}
 				else
 					mToken = BfToken_RDblChevron;
 			}

+ 1 - 1
IDEHelper/Compiler/BfParser.h

@@ -198,7 +198,7 @@ public:
 	BfExpression* CreateInlineExpressionFromNode(BfBlock* block);
 	bool EvaluatePreprocessor(BfExpression* expr);
 	BfBlock* ParseInlineBlock(int spaceIdx, int endIdx);
-	void HandlePreprocessor();	
+	bool HandlePreprocessor();	
 	bool IsUnwarnedAt(BfAstNode* node);
 	bool SrcPtrHasToken(const char* name);
 	uint32 GetTokenHash();