📄 asbeautifier.cpp
字号:
{
if (ch == '}')
{
// first check if this '}' closes a previous block, or a static array...
if (!bracketBlockStateStack->empty())
{
bool bracketBlockState = bracketBlockStateStack->back();
bracketBlockStateStack->pop_back();
if (!bracketBlockState)
{
if (!inStatementIndentStackSizeStack->empty())
{
// this bracket is a static array
int previousIndentStackSize = inStatementIndentStackSizeStack->back();
inStatementIndentStackSizeStack->pop_back();
while (previousIndentStackSize < (int) inStatementIndentStack->size())
inStatementIndentStack->pop_back();
parenDepth--;
if (i == 0)
shouldIndentBrackettedLine = false;
if (!parenIndentStack->empty())
{
int poppedIndent = parenIndentStack->back();
parenIndentStack->pop_back();
if (i == 0)
spaceTabCount = poppedIndent;
}
}
continue;
}
}
// this bracket is block closer...
++lineClosingBlocksNum;
if (!inStatementIndentStackSizeStack->empty())
inStatementIndentStackSizeStack->pop_back();
if (!blockParenDepthStack->empty())
{
parenDepth = blockParenDepthStack->back();
blockParenDepthStack->pop_back();
isInStatement = blockStatementStack->back();
blockStatementStack->pop_back();
if (isInStatement)
blockTabCount--;
}
closingBracketReached = true;
int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET);
if (headerPlace != -1)
{
const string *popped = headerStack->back();
while (popped != &AS_OPEN_BRACKET)
{
headerStack->pop_back();
popped = headerStack->back();
}
headerStack->pop_back();
if (!tempStacks->empty())
{
vector<const string*> *temp = tempStacks->back();
tempStacks->pop_back();
delete temp;
}
}
ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
}
/*
* Create a temporary snapshot of the current block's header-list in the
* uppermost inner stack in tempStacks, and clear the headerStack up to
* the begining of the block.
* Thus, the next future statement will think it comes one indent past
* the block's '{' unless it specifically checks for a companion-header
* (such as a previous 'if' for an 'else' header) within the tempStacks,
* and recreates the temporary snapshot by manipulating the tempStacks.
*/
if (!tempStacks->back()->empty())
while (!tempStacks->back()->empty())
tempStacks->back()->pop_back();
while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
{
tempStacks->back()->push_back(headerStack->back());
headerStack->pop_back();
}
if (parenDepth == 0 && ch == ';')
isInStatement = false;
previousLastLineHeader = NULL;
isInClassHeader = false;
isInQuestion = false;
continue;
}
// check for preBlockStatements ONLY if not within parenthesies
// (otherwise 'struct XXX' statements would be wrongly interpreted...)
if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0)
{
const string *newHeader = findHeader(line, i, preBlockStatements);
if (newHeader != NULL)
{
isInClassHeader = true;
outBuffer.append(newHeader->substr(1));
i += newHeader->length() - 1;
headerStack->push_back(newHeader);
}
}
// Handle operators
immediatelyPreviousAssignmentOp = NULL;
// Check if an operator has been reached.
const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
if (foundAssignmentOp == &AS_RETURN)
foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
const string *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
// Since findHeader's boundry checking was not used above, it is possible
// that both an assignment op and a non-assignment op where found,
// e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
// found operator.
if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
foundAssignmentOp = NULL;
else
foundNonAssignmentOp = NULL;
if (foundNonAssignmentOp != NULL)
{
if (foundNonAssignmentOp->length() > 1)
{
outBuffer.append(foundNonAssignmentOp->substr(1));
i += foundNonAssignmentOp->length() - 1;
}
}
else if (foundAssignmentOp != NULL)
{
if (foundAssignmentOp->length() > 1)
{
outBuffer.append(foundAssignmentOp->substr(1));
i += foundAssignmentOp->length() - 1;
}
if (!isInOperator && !isInTemplate && !isNonInStatementArray)
{
registerInStatementIndent(line, i, spaceTabCount, 0, false);
immediatelyPreviousAssignmentOp = foundAssignmentOp;
isInStatement = true;
}
}
if (isInOperator)
isInOperator = false;
}
// handle special cases of unindentation:
/*
* if '{' doesn't follow an immediately previous '{' in the headerStack
* (but rather another header such as "for" or "if", then unindent it
* by one indentation relative to its block.
*/
if (!lineStartsInComment
&& !blockIndent
&& outBuffer.length() > 0
&& outBuffer[0] == '{'
&& !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
&& !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
&& shouldIndentBrackettedLine)
--tabCount;
else if (!lineStartsInComment
&& outBuffer.length() > 0
&& outBuffer[0] == '}'
&& shouldIndentBrackettedLine)
--tabCount;
// correctly indent one-line-blocks...
else if (!lineStartsInComment
&& outBuffer.length() > 0
&& lineOpeningBlocksNum > 0
&& lineOpeningBlocksNum == lineClosingBlocksNum
&& previousLineProbationTab)
--tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
if (tabCount < 0)
tabCount = 0;
// take care of extra bracket indentatation option...
if (bracketIndent && outBuffer.length() > 0 && shouldIndentBrackettedLine)
if (outBuffer[0] == '{' || outBuffer[0] == '}')
tabCount++;
if (isInDefine)
{
if (outBuffer[0] == '#')
{
string preproc = trim(string(outBuffer.c_str() + 1));
if (preproc.compare(0, 6, "define") == 0)
{
if (!inStatementIndentStack->empty()
&& inStatementIndentStack->back() > 0)
{
defineTabCount = tabCount;
}
else
{
defineTabCount = tabCount - 1;
tabCount--;
}
}
}
tabCount -= defineTabCount;
}
if (tabCount < 0)
tabCount = 0;
if (lineCommentNoBeautify || blockCommentNoBeautify)
tabCount = spaceTabCount = 0;
// finally, insert indentations into begining of line
prevFinalLineSpaceTabCount = spaceTabCount;
prevFinalLineTabCount = tabCount;
if (shouldForceTabIndentation)
{
tabCount += spaceTabCount / indentLength;
spaceTabCount = spaceTabCount % indentLength;
}
outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer;
if (lastLineHeader != NULL)
previousLastLineHeader = lastLineHeader;
return outBuffer;
}
string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
{
string ws;
for (int i = 0; i < tabCount; i++)
ws += indentString;
while ((spaceTabCount--) > 0)
ws += string(" ");
return ws;
}
/**
* register an in-statement indent.
*/
void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
int minIndent, bool updateParenStack)
{
int inStatementIndent;
int remainingCharNum = line.length() - i;
int nextNonWSChar = getNextProgramCharDistance(line, i);
// if indent is around the last char in the line, indent instead 2 spaces from the previous indent
if (nextNonWSChar == remainingCharNum)
{
int previousIndent = spaceTabCount;
if (!inStatementIndentStack->empty())
previousIndent = inStatementIndentStack->back();
inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent);
if (updateParenStack)
parenIndentStack->push_back(previousIndent);
return;
}
if (updateParenStack)
parenIndentStack->push_back(i + spaceTabCount);
inStatementIndent = i + nextNonWSChar + spaceTabCount;
if (i + nextNonWSChar < minIndent)
inStatementIndent = minIndent + spaceTabCount;
if (i + nextNonWSChar > maxInStatementIndent)
inStatementIndent = indentLength * 2 + spaceTabCount;
if (!inStatementIndentStack->empty() &&
inStatementIndent < inStatementIndentStack->back())
inStatementIndent = inStatementIndentStack->back();
if (isNonInStatementArray)
inStatementIndent = 0;
inStatementIndentStack->push_back(inStatementIndent);
}
/**
* get distance to the next non-white sspace, non-comment character in the line.
* if no such character exists, return the length remaining to the end of the line.
*/
int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
{
bool inComment = false;
int remainingCharNum = line.length() - i;
int charDistance;
char ch;
for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
{
ch = line[i + charDistance];
if (inComment)
{
if (line.compare(i + charDistance, 2, "*/") == 0)
{
charDistance++;
inComment = false;
}
continue;
}
else if (isWhiteSpace(ch))
continue;
else if (ch == '/')
{
if (line.compare(i + charDistance, 2, "//") == 0)
return remainingCharNum;
else if (line.compare(i + charDistance, 2, "/*") == 0)
{
charDistance++;
inComment = true;
}
}
else
return charDistance;
}
return charDistance;
}
/**
* check if a specific line position contains a header, out of several possible headers.
*
* @return a pointer to the found header. if no header was found then return NULL.
*/
const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
{
int maxHeaders = possibleHeaders.size();
// const string *header = NULL;
int p;
for (p = 0; p < maxHeaders; p++)
{
const string *header = possibleHeaders[p];
if (line.compare(i, header->length(), header->c_str()) == 0)
{
// check that this is a header and not a part of a longer word
// (e.g. not at its begining, not at its middle...)
int lineLength = line.length();
int headerEnd = i + header->length();
char startCh = (*header)[0]; // first char of header
char endCh = 0; // char just after header
char prevCh = 0; // char just before header
if (headerEnd < lineLength)
{
endCh = line[headerEnd];
}
if (i > 0)
{
prevCh = line[i-1];
}
if (!checkBoundry)
{
return header;
}
else if (prevCh != 0
&& isLegalNameChar(startCh)
&& isLegalNameChar(prevCh))
{
return NULL;
}
else if (headerEnd >= lineLength
|| !isLegalNameChar(startCh)
|| !isLegalNameChar(endCh))
{
return header;
}
else
{
return NULL;
}
}
}
return NULL;
}
/**
* find the index number of a string element in a container of strings
*
* @return the index number of element in the ocntainer. -1 if element not found.
* @param container a vector of strings.
* @param element the element to find .
*/
int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
{
vector<const string*>::const_iterator where;
where = find(container.begin(), container.end(), element);
if (where == container.end())
return -1;
else
return (int) (where - container.begin());
}
/**
* trim removes the white space surrounding a line.
*
* @return the trimmed line.
* @param str the line to trim.
*/
string ASBeautifier::trim(const string &str)
{
int start = 0;
int end = str.length() - 1;
while (start < end && isWhiteSpace(str[start]))
start++;
while (start <= end && isWhiteSpace(str[end]))
end--;
string returnStr(str, start, end + 1 - start);
return returnStr;
}
/**
* peek at the next unread character.
*
* @return the next unread character.
* @param line the line to check.
* @param i the current char position on the line.
*/
char ASBeautifier::peekNextChar(string &line, int i)
{
char ch = ' ';
size_t peekNum = line.find_first_not_of(" \t", i + 1);
if (peekNum == string::npos)
return ch;
ch = line[peekNum];
return ch;
}
} // end namespace astyle
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -