From 076931cf3b590dcc2d6aedbc6f6656b6162a8cc7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 28 Mar 2020 14:26:14 -0700 Subject: [PATCH] Working on wrapping for formatter --- IDEHelper/Compiler/BfAst.cpp | 7 + IDEHelper/Compiler/BfAst.h | 10 +- IDEHelper/Compiler/BfCompiler.cpp | 6 + IDEHelper/Compiler/BfContext.cpp | 48 +++--- IDEHelper/Compiler/BfParser.cpp | 42 ++--- IDEHelper/Compiler/BfPrinter.cpp | 258 ++++++++++++++++++++++++++++-- IDEHelper/Compiler/BfPrinter.h | 2 + IDEHelper/Compiler/BfReducer.cpp | 8 +- 8 files changed, 315 insertions(+), 66 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index ed99bb21..a881413d 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/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) diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 6d76ed6f..7c002c3d 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/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 \ No newline at end of file diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index aee21392..3c784153 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/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); diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 04a99743..b4ec99ab 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/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 } diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index da244acf..f3ef6442 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/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->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; +// } } } } diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index c2c90b97..d530c5a4 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/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(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(); diff --git a/IDEHelper/Compiler/BfPrinter.h b/IDEHelper/Compiler/BfPrinter.h index a7852da1..3c24d36e 100644 --- a/IDEHelper/Compiler/BfPrinter.h +++ b/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; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 544bdc6b..a9719421 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -8330,14 +8330,15 @@ BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode* while (mDocumentCheckIdx < mSource->mSidechannelRootNode->mChildArr.mSize) { auto checkComment = BfNodeDynCast(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++;