Przeglądaj źródła

Working on wrapping for formatter

Brian Fiete 5 lat temu
rodzic
commit
076931cf3b

+ 7 - 0
IDEHelper/Compiler/BfAst.cpp

@@ -1784,6 +1784,13 @@ BfBinaryOp Beefy::BfGetFlippedBinaryOp(BfBinaryOp origOp)
 	return BfBinaryOp_None;
 }
 
+bool Beefy::BfIsCommentBlock(BfCommentKind commentKind)
+{
+	return
+		(commentKind == BfCommentKind_Block) ||
+		(commentKind == BfCommentKind_Documentation_Block_Pre) ||
+		(commentKind == BfCommentKind_Documentation_Block_Post);
+}
 
 BfInlineAsmInstruction::AsmArg::AsmArg()
 	: mType(ARGTYPE_Immediate)

+ 7 - 3
IDEHelper/Compiler/BfAst.h

@@ -1760,9 +1760,12 @@ public:
 
 enum BfCommentKind
 {
-	BfCommentKind_Normal,
-	BfCommentKind_Documentation_Pre,
-	BfCommentKind_Documentation_Post,
+	BfCommentKind_Line,
+	BfCommentKind_Block,
+	BfCommentKind_Documentation_Block_Pre,
+	BfCommentKind_Documentation_Line_Pre,
+	BfCommentKind_Documentation_Block_Post,
+	BfCommentKind_Documentation_Line_Post,			
 };
 
 class BfCommentNode : public BfAstNode
@@ -3182,5 +3185,6 @@ const char* BfGetOpName(BfUnaryOp unaryOp);
 BfBinaryOp BfTokenToBinaryOp(BfToken token);
 BfUnaryOp BfTokenToUnaryOp(BfToken token);
 BfAssignmentOp BfTokenToAssignmentOp(BfToken token);
+bool BfIsCommentBlock(BfCommentKind commentKind);
 
 NS_BF_END

+ 6 - 0
IDEHelper/Compiler/BfCompiler.cpp

@@ -5712,6 +5712,12 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 {
 	BP_ZONE("BfCompiler::Compile");
 	
+	if (mSystem->mTypeDefs.mCount == 0)
+	{
+		// No-source bailout
+		return true;
+	}
+
 	if (!mOptions.mErrorString.IsEmpty())
 	{
 		mPassInstance->Fail(mOptions.mErrorString);

+ 24 - 24
IDEHelper/Compiler/BfContext.cpp

@@ -772,30 +772,30 @@ void BfContext::AddTypeToWorkList(BfType* type)
 void BfContext::ValidateDependencies()
 {
 #if _DEBUG
-	BP_ZONE("BfContext::ValidateDependencies");
-	BfLogSysM("ValidateDependencies\n");
-
-	bool deletedNewTypes = false;
-	auto itr = mResolvedTypes.begin();
-	while (itr != mResolvedTypes.end())
-	{
-		auto type = itr.mCurEntry->mValue;		
-		if ((type->IsGenericTypeInstance()) && (type->mDefineState > BfTypeDefineState_Undefined))
-		{
-			// We can't contain deleted generic arguments without being deleted ourselves
-			BfGenericTypeInstance* genericType = (BfGenericTypeInstance*)type;
-
-			for (auto genericTypeArg : genericType->mTypeGenericArguments)
-			{
-				auto depType = genericTypeArg->ToDependedType();
-				if (depType != NULL)
-				{
-					BF_ASSERT(depType->mDependencyMap.mTypeSet.ContainsKey(type));					
-				}
-			}
-		}
-		++itr;
-	}
+// 	BP_ZONE("BfContext::ValidateDependencies");
+// 	BfLogSysM("ValidateDependencies\n");
+// 
+// 	bool deletedNewTypes = false;
+// 	auto itr = mResolvedTypes.begin();
+// 	while (itr != mResolvedTypes.end())
+// 	{
+// 		auto type = itr.mCurEntry->mValue;		
+// 		if ((type->IsGenericTypeInstance()) && (type->mDefineState > BfTypeDefineState_Undefined))
+// 		{
+// 			// We can't contain deleted generic arguments without being deleted ourselves
+// 			BfGenericTypeInstance* genericType = (BfGenericTypeInstance*)type;
+// 
+// 			for (auto genericTypeArg : genericType->mTypeGenericArguments)
+// 			{
+// 				auto depType = genericTypeArg->ToDependedType();
+// 				if (depType != NULL)
+// 				{
+// 					BF_ASSERT(depType->mDependencyMap.mTypeSet.ContainsKey(type));					
+// 				}
+// 			}
+// 		}
+// 		++itr;
+// 	}
 #endif
 }
 

+ 23 - 19
IDEHelper/Compiler/BfParser.cpp

@@ -626,17 +626,17 @@ void BfParser::AddErrorNode(int startIdx, int endIdx)
 
 BfCommentKind BfParser::GetCommentKind(int startIdx)
 {
-	if (((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] == '<')) ||
-		((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] == '<')))
-	{
-		return BfCommentKind_Documentation_Post;
-	}
-	if (((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] != '/')) ||
-		((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] != '/')))
-	{
-		return BfCommentKind_Documentation_Pre;
-	}
-	return BfCommentKind_Normal;
+	if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] == '<'))
+		return BfCommentKind_Documentation_Block_Post;
+	if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] == '<'))
+		return BfCommentKind_Documentation_Line_Post;
+	if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] != '/'))
+		return BfCommentKind_Documentation_Block_Pre;
+	if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] != '/'))
+		return BfCommentKind_Documentation_Line_Pre;
+	if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*'))
+		return BfCommentKind_Block;
+	return BfCommentKind_Line;
 }
 
 bool BfParser::EvaluatePreprocessor(BfExpression* expr)
@@ -1950,6 +1950,7 @@ void BfParser::NextToken(int endIdx)
 
 				if (mPreprocessorIgnoredSectionNode == NULL)
 				{
+					auto commentKind = GetCommentKind(mTokenStart);
 					bool handled = false;
 					if (!mPendingSideNodes.IsEmpty())
 					{
@@ -1957,8 +1958,10 @@ void BfParser::NextToken(int endIdx)
 						{							
 							// This is required for folding '///' style multi-line documentation into a single node
 							if (prevComment->GetTriviaStart() == mTriviaStart)
-							{
-								if (GetCommentKind(prevComment->mSrcStart) == GetCommentKind(mTokenStart))
+							{								
+								auto prevCommentKind = GetCommentKind(prevComment->mSrcStart);
+
+								if ((!BfIsCommentBlock(commentKind)) && (commentKind == prevCommentKind))
 								{
 									prevComment->SetSrcEnd(mSrcIdx);
 									handled = true;
@@ -1971,7 +1974,7 @@ void BfParser::NextToken(int endIdx)
 					{
 						auto bfCommentNode = mAlloc->Alloc<BfCommentNode>();
 						bfCommentNode->Init(this);						
-						bfCommentNode->mCommentKind = GetCommentKind(mTokenStart);
+						bfCommentNode->mCommentKind = commentKind;
 						mSidechannelRootNode->Add(bfCommentNode);
 						mPendingSideNodes.push_back(bfCommentNode);
 					}
@@ -2025,11 +2028,12 @@ void BfParser::NextToken(int endIdx)
 										// This is required for folding documentation into a single node
 										if (prevComment->GetTriviaStart() == mTriviaStart)
 										{
-											if (GetCommentKind(prevComment->mSrcStart) == GetCommentKind(mTokenStart))
-											{
-												prevComment->SetSrcEnd(mSrcIdx);
-												handled = true;
-											}
+											//TODO: Why did we allow merging BLOCKS of comments together? This messes up BfPrinter word wrapping on comments
+// 											if (GetCommentKind(prevComment->mSrcStart) == GetCommentKind(mTokenStart))
+// 											{
+// 												prevComment->SetSrcEnd(mSrcIdx);
+// 												handled = true;
+// 											}
 										}
 									}
 								}

+ 241 - 17
IDEHelper/Compiler/BfPrinter.cpp

@@ -1,18 +1,21 @@
 #include "BfPrinter.h"
 #include "BfParser.h"
 #include "BfUtil.h"
+#include "BeefySysLib/util/UTF8.h"
 
 USING_NS_BF;
 
-BfPrinter::BfPrinter(BfRootNode* rootNode, BfRootNode* sidechannelRootNode, BfRootNode* errorRootNode)
-{	
+// This is a really long line, I'm testing to see what's up. This is a really long line, I'm testing to see what's up. This is a really long line, I'm testing to see what's up.
+// This is a really long line, I'm testing to see what's up.
+BfPrinter::BfPrinter(BfRootNode *rootNode, BfRootNode *sidechannelRootNode, BfRootNode *errorRootNode)
+{
 	mSource = rootNode->GetSourceData();
-	mParser = mSource->ToParserData();	
+	mParser = mSource->ToParserData();
 
 	if (sidechannelRootNode != NULL)
 		mSidechannelItr = sidechannelRootNode->begin();
 	mSidechannelNextNode = mSidechannelItr.Get();
-	
+
 	if (errorRootNode != NULL)
 		mErrorItr = errorRootNode->begin();	
 	mErrorNextNode = mErrorItr.Get();	
@@ -39,10 +42,28 @@ BfPrinter::BfPrinter(BfRootNode* rootNode, BfRootNode* sidechannelRootNode, BfRo
 	mVirtualNewLineIdx = 0;
 	mHighestCharId = 0;
 	mCurTypeDecl = NULL;
+	mCurCol = 0;
+	mMaxCol = 120;
 }
 
 void BfPrinter::Write(const StringView& str)
 {	
+	if (str == '\n')
+		mCurCol = 0;
+	else if (mMaxCol > 0)
+	{
+		int startCol = mCurCol;
+
+		for (int i = 0; i < (int)str.mLength; i++)
+		{
+			char c = str[i];
+			if (c == '\t')
+				mCurCol = ((mCurCol + 1) & ~3) + 4;			
+			else
+				mCurCol++;
+		}	
+	}	
+
 	mOutString.Append(str);
 	if (mCharMapping != NULL)
 	{
@@ -108,6 +129,28 @@ void BfPrinter::FlushIndent()
 void BfPrinter::Write(BfAstNode* node, int start, int len)
 {
 	FlushIndent();	
+
+	if (mMaxCol > 0)
+	{
+		int startCol = mCurCol;
+		
+		auto parserData = node->GetParserData();
+
+		for (int i = 0; i < len; i++)
+		{
+			char c = parserData->mSrc[start + i];
+			if (c == '\t')
+				mCurCol = ((mCurCol + 1) & ~3) + 4;
+			else
+				mCurCol++;
+		}
+
+ 		if ((mCurCol > mMaxCol) && (startCol != 0))
+ 		{
+			NOP;
+ 		}
+	}
+
 	mOutString.Append(node->GetSourceData()->mSrc + start, len);
 	if (mCharMapping != NULL)
 	{
@@ -256,6 +299,8 @@ int BfPrinter::CalcOrigLineSpacing(BfAstNode* bfAstNode, int* lineStartIdx)
 
 void BfPrinter::WriteIgnoredNode(BfAstNode* node)
 {
+	bool wasExpectingNewLine = mExpectingNewLine;
+
 	mTriviaIdx = std::max(mTriviaIdx, node->GetTriviaStart());
 	int endIdx = mTriviaIdx;	
 	int crCount = 0;
@@ -290,6 +335,46 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
 		}
 	}	
 
+	auto commentNode = BfNodeDynCast<BfCommentNode>(node);
+	bool isBlockComment = false;
+	bool isStarredBlockComment = false;
+
+	if (commentNode != NULL)
+	{
+		if ((commentNode->mCommentKind == BfCommentKind_Block) ||
+			(commentNode->mCommentKind == BfCommentKind_Documentation_Block_Pre) ||
+			(commentNode->mCommentKind == BfCommentKind_Documentation_Block_Post))
+		{
+			isBlockComment = true;
+
+			int lineCount = 0;
+			bool onNewLine = false;
+			for (int srcIdx = startIdx; srcIdx < endIdx; srcIdx++)
+			{
+				char checkC = astNodeSrc->mSrc[srcIdx];
+				if (checkC == '\n')
+				{
+					onNewLine = true;
+					lineCount++;
+					if (lineCount >= 2)
+						break;
+				}
+				else if ((checkC == '*') && (onNewLine))
+					isStarredBlockComment = true;
+				else if ((checkC != ' ') && (checkC != '\t'))
+					onNewLine = false;
+			}
+		}
+	}
+	bool doWrap = (commentNode != NULL) && (mMaxCol > 0);
+	bool prevHadWrap = false;
+
+	if (commentNode != NULL)
+	{
+		Visit((BfAstNode*)node);
+		startIdx = node->mSrcStart;
+	}
+
 	// This handles tab adjustment within multiline comments
 	FlushIndent();	
 	bool isNewLine = false;	
@@ -300,9 +385,90 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
 #endif
 
 		bool emitChar = true;
+		
 		char c = astNodeSrc->mSrc[srcIdx];
-		if (c == '\n')		
-			isNewLine = true;		
+		if (c == '\n')
+		{
+			isNewLine = true;
+
+			if (prevHadWrap)
+			{
+				bool merging = false;
+
+				int blockContentStart = -1;
+
+				bool foundStar = false;
+				int startIdx = srcIdx;
+				for (int checkIdx = srcIdx + 1; checkIdx < endIdx + 1; checkIdx++)
+				{
+					char checkC = astNodeSrc->mSrc[checkIdx];					
+
+					if (isBlockComment)
+					{
+						if (checkC == '\n')
+							break;
+
+						if ((isStarredBlockComment) && (!foundStar) && (checkC == '*'))
+						{
+							foundStar = true;
+							continue;
+						}
+
+						if ((checkC != ' ') && (checkC != '\t'))
+						{
+							if (blockContentStart == -1)
+							{
+								blockContentStart = checkIdx;
+							}
+
+							// Only do merge if we have content on this line
+							if (isalnum(checkC))
+							{
+								srcIdx = blockContentStart;
+								merging = true;
+								break;
+							}
+						}
+					}
+					else
+					{
+						if ((checkC == '/') && (astNodeSrc->mSrc[checkIdx + 1] == '/'))
+						{
+							srcIdx = checkIdx;
+							while (srcIdx < endIdx)
+							{
+								char checkC = astNodeSrc->mSrc[srcIdx];
+								if (checkC != '/')
+									break;
+								srcIdx++;
+							}
+							merging = true;
+							break;
+						}
+
+						if ((checkC != ' ') && (checkC != '\t'))
+							break;
+					}					
+				}
+
+				if (merging)
+				{
+					srcIdx--;
+					while (srcIdx < endIdx - 1)
+					{
+						char checkC = astNodeSrc->mSrc[srcIdx + 1];
+						if ((checkC != ' ') && (checkC != '\t'))
+							break;
+						srcIdx++;
+					}
+					Write(" ");
+					continue;
+				}
+			}
+
+			mCurCol = 0;
+			prevHadWrap = false;
+		}
 		else if (isNewLine) 
 		{
 			if (c == ' ')
@@ -319,21 +485,78 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
 			{					
 				// Leave left-aligned preprocessor nodes that are commented out
 				if ((c != '#') || (mQueuedSpaceCount > 0))
-					mQueuedSpaceCount = std::max(0, mQueuedSpaceCount + mLastSpaceOffset);				
+					mQueuedSpaceCount = std::max(0, mQueuedSpaceCount + mLastSpaceOffset);
+				else
+					mQueuedSpaceCount = mCurIndentLevel * 4; // Do default indent
 				isNewLine = false;				
 			}
 		}
 
 		if (emitChar)
-		{						
-			FlushIndent();
-			mOutString.Append(c);
-			if (mCharMapping != NULL)
+		{	
+			int startIdx = srcIdx;
+
+			if (c != '\n')
 			{
-				if (srcIdx < mParser->mSrcLength)				
-					mCharMapping->push_back(srcIdx);				
-				else
-					mCharMapping->push_back(-1);
+				while (srcIdx < endIdx)
+				{				
+					char c = astNodeSrc->mSrc[srcIdx + 1];
+					if (isspace((uint8)c))
+						break;
+					srcIdx++;
+				}
+			}
+			
+			if (doWrap)
+			{
+				int len = 0;
+				for (int idx = startIdx; idx <= srcIdx; idx++)
+				{
+					char c = astNodeSrc->mSrc[idx];
+					if (isutf(c))
+						len++;
+				}
+				
+				if (mCurCol + len > mMaxCol)
+				{
+					Write("\n");
+					mQueuedSpaceCount = mCurIndentLevel * 4;
+					FlushIndent();
+
+					if (isStarredBlockComment)
+						Write(" * ");
+					else if (!isBlockComment)					
+						Write("// ");
+					prevHadWrap = true;					
+					
+					while (startIdx < endIdx)
+					{
+						char c = astNodeSrc->mSrc[startIdx];
+						if (!isspace((uint8)c))
+							break;
+						startIdx++;
+					}
+				}
+			}
+
+			FlushIndent();			
+
+			for (int idx = startIdx; idx <= srcIdx; idx++)
+			{
+				char c = astNodeSrc->mSrc[idx];
+				mOutString.Append(c);
+				if (mCharMapping != NULL)
+				{
+					if (idx < mParser->mSrcLength)
+						mCharMapping->push_back(idx);
+					else
+						mCharMapping->push_back(-1);
+				}
+
+				if (c == '\n')
+					mCurCol = 0;				
+				else if (isutf(c))
+					mCurCol++;
 			}
 		}
 	}
@@ -342,6 +565,7 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
 
 	mTriviaIdx = endIdx;	
 	mIsFirstStatementInBlock = false;
+	mExpectingNewLine = wasExpectingNewLine;
 }
 
 void BfPrinter::Visit(BfAstNode* bfAstNode)
@@ -496,7 +720,7 @@ void BfPrinter::Visit(BfAstNode* bfAstNode)
 								// Found previous line
 								usedTrivia = true;
 								Write("\n");
-								mQueuedSpaceCount = mCurIndentLevel * 4;																
+								mQueuedSpaceCount = mCurIndentLevel * 4;
 
 								// Indents extra if we have a statement split over multiple lines
 								if (!mExpectingNewLine)
@@ -2171,7 +2395,7 @@ void BfPrinter::Visit(BfPropertyDeclaration* propertyDeclaration)
 		}
 		QueueVisitChild(indexerDeclaration->mCloseBracket);
 		ExpectSpace();
-	}
+	}	
 
 	QueueVisitChild(propertyDeclaration->mEqualsNode);
 	ExpectSpace();

+ 2 - 0
IDEHelper/Compiler/BfPrinter.h

@@ -62,6 +62,8 @@ public:
 	int mQueuedSpaceCount;
 	int mLastSpaceOffset; // Indent difference from original to new	
 	bool mExpectingNewLine;
+	int mCurCol;
+	int mMaxCol;
 
 	bool mIsFirstStatementInBlock;
 	bool mForceUseTrivia;

+ 5 - 3
IDEHelper/Compiler/BfReducer.cpp

@@ -8330,14 +8330,15 @@ BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode*
 	while (mDocumentCheckIdx < mSource->mSidechannelRootNode->mChildArr.mSize)
 	{
 		auto checkComment = BfNodeDynCast<BfCommentNode>(mSource->mSidechannelRootNode->mChildArr[mDocumentCheckIdx]);
-		if ((checkComment == NULL) || (checkComment->mCommentKind == BfCommentKind_Normal))
+		if ((checkComment == NULL) || (checkComment->mCommentKind == BfCommentKind_Block) || (checkComment->mCommentKind == BfCommentKind_Line))
 		{
 			mDocumentCheckIdx++;
 			continue;
 		}
 		if (checkComment->GetSrcEnd() > defNodeEnd->GetSrcStart())
 		{
-			if (checkComment->mCommentKind == BfCommentKind_Documentation_Post)
+			if ((checkComment->mCommentKind == BfCommentKind_Documentation_Line_Post) ||
+				(checkComment->mCommentKind == BfCommentKind_Documentation_Block_Post))
 			{
 				int defEnd = defNodeEnd->GetSrcEnd();
 				if (checkDocAfter)
@@ -8368,7 +8369,8 @@ BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode*
 			return NULL;
 		}
 
-		if (checkComment->mCommentKind != BfCommentKind_Documentation_Pre)
+		if ((checkComment->mCommentKind != BfCommentKind_Documentation_Line_Pre) && 
+			(checkComment->mCommentKind != BfCommentKind_Documentation_Block_Pre))
 		{
 			// Skip this, not used
 			mDocumentCheckIdx++;