📄 asformatter.cpp
字号:
/*
* Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
*
* ASFormatter.cpp
* by Tal Davidson (davidsont@bigfoot.com)
* This file is a part of "Artistic Style" - an indentater and reformatter
* of C, C++, C# and Java source files.
*
* The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. *
*
* Patches:
* 26 November 1998 - Richard Bullington -
* A correction of line-breaking in headers following '}',
* was created using a variation of a patch by Richard Bullington.
*/
#include "compiler_defines.h"
#include "astyle.h"
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>
#include <iostream>
#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; }
#define IS_A(a,b) ( ((a) & (b)) == (b))
#ifdef USES_NAMESPACE
using namespace std;
namespace astyle
{
#endif
bool ASFormatter::calledInitStatic = false;
vector<const string*> ASFormatter::headers;
vector<const string*> ASFormatter::nonParenHeaders;
vector<const string*> ASFormatter::preprocessorHeaders;
vector<const string*> ASFormatter::preDefinitionHeaders;
vector<const string*> ASFormatter::preCommandHeaders;
vector<const string*> ASFormatter::operators;
vector<const string*> ASFormatter::assignmentOperators;
/**
* Constructor of ASFormatter
*/
ASFormatter::ASFormatter()
{
staticInit();
preBracketHeaderStack = NULL;
bracketTypeStack = NULL;
parenStack = NULL;
sourceIterator = NULL;
bracketFormatMode = NONE_MODE;
shouldPadOperators = false;
shouldPadParenthesies = false;
shouldBreakOneLineBlocks = true;
shouldBreakOneLineStatements = true;
shouldConvertTabs = false;
shouldBreakBlocks = false;
shouldBreakClosingHeaderBlocks = false;
shouldBreakClosingHeaderBrackets = false;
shouldBreakElseIfs = false;
}
/**
* Destructor of ASFormatter
*/
ASFormatter::~ASFormatter()
{
DELETE_CONTAINER( preBracketHeaderStack );
}
/**
* initialization of static data of ASFormatter.
*/
void ASFormatter::staticInit()
{
if (calledInitStatic)
return;
calledInitStatic = true;
headers.push_back(&AS_IF);
headers.push_back(&AS_ELSE);
headers.push_back(&AS_DO);
headers.push_back(&AS_WHILE);
headers.push_back(&AS_FOR);
headers.push_back(&AS_SYNCHRONIZED);
headers.push_back(&AS_TRY);
headers.push_back(&AS_CATCH);
headers.push_back(&AS_FINALLY);
headers.push_back(&AS_SWITCH);
headers.push_back(&AS_TEMPLATE);
headers.push_back(&AS_FOREACH); headers.push_back(&AS_LOCK); headers.push_back(&AS_UNSAFE); headers.push_back(&AS_FIXED); headers.push_back(&AS_GET); headers.push_back(&AS_SET); headers.push_back(&AS_ADD); headers.push_back(&AS_REMOVE);
nonParenHeaders.push_back(&AS_ELSE);
nonParenHeaders.push_back(&AS_DO);
nonParenHeaders.push_back(&AS_TRY);
nonParenHeaders.push_back(&AS_FINALLY);
nonParenHeaders.push_back(&AS_UNSAFE);
nonParenHeaders.push_back(&AS_GET); nonParenHeaders.push_back(&AS_SET); nonParenHeaders.push_back(&AS_ADD); nonParenHeaders.push_back(&AS_REMOVE);
// nonParenHeaders.push_back(&AS_TEMPLATE);
preDefinitionHeaders.push_back(&AS_CLASS);
preDefinitionHeaders.push_back(&AS_INTERFACE);
preDefinitionHeaders.push_back(&AS_NAMESPACE);
preDefinitionHeaders.push_back(&AS_STRUCT);
preCommandHeaders.push_back(&AS_EXTERN);
preCommandHeaders.push_back(&AS_THROWS);
preCommandHeaders.push_back(&AS_CONST);
preprocessorHeaders.push_back(&AS_BAR_DEFINE);
//// DEVEL: removed the folowing lines
////preprocessorHeaders.push_back(&AS_BAR_INCLUDE);
////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef
////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif
////preprocessorHeaders.push_back(&AS_BAR_ENDIF);
operators.push_back(&AS_PLUS_ASSIGN);
operators.push_back(&AS_MINUS_ASSIGN);
operators.push_back(&AS_MULT_ASSIGN);
operators.push_back(&AS_DIV_ASSIGN);
operators.push_back(&AS_MOD_ASSIGN);
operators.push_back(&AS_OR_ASSIGN);
operators.push_back(&AS_AND_ASSIGN);
operators.push_back(&AS_XOR_ASSIGN);
operators.push_back(&AS_EQUAL);
operators.push_back(&AS_PLUS_PLUS);
operators.push_back(&AS_MINUS_MINUS);
operators.push_back(&AS_NOT_EQUAL);
operators.push_back(&AS_GR_EQUAL);
operators.push_back(&AS_GR_GR_GR_ASSIGN);
operators.push_back(&AS_GR_GR_ASSIGN);
operators.push_back(&AS_GR_GR_GR);
operators.push_back(&AS_GR_GR);
operators.push_back(&AS_LS_EQUAL);
operators.push_back(&AS_LS_LS_LS_ASSIGN);
operators.push_back(&AS_LS_LS_ASSIGN);
operators.push_back(&AS_LS_LS_LS);
operators.push_back(&AS_LS_LS);
operators.push_back(&AS_ARROW);
operators.push_back(&AS_AND);
operators.push_back(&AS_OR);
operators.push_back(&AS_COLON_COLON);
//// BUGFIX: removed the folowing lines
//// operators.push_back(&AS_PAREN_PAREN);
//// operators.push_back(&AS_BLPAREN_BLPAREN);
operators.push_back(&AS_PLUS);
operators.push_back(&AS_MINUS);
operators.push_back(&AS_MULT);
operators.push_back(&AS_DIV);
operators.push_back(&AS_MOD);
operators.push_back(&AS_QUESTION);
operators.push_back(&AS_COLON);
operators.push_back(&AS_ASSIGN);
operators.push_back(&AS_LS);
operators.push_back(&AS_GR);
operators.push_back(&AS_NOT);
operators.push_back(&AS_BIT_OR);
operators.push_back(&AS_BIT_AND);
operators.push_back(&AS_BIT_NOT);
operators.push_back(&AS_BIT_XOR);
operators.push_back(&AS_OPERATOR);
operators.push_back(&AS_COMMA);
// operators.push_back(&AS_SEMICOLON);
operators.push_back(&AS_RETURN);
assignmentOperators.push_back(&AS_PLUS_ASSIGN);
assignmentOperators.push_back(&AS_MINUS_ASSIGN);
assignmentOperators.push_back(&AS_MULT_ASSIGN);
assignmentOperators.push_back(&AS_DIV_ASSIGN);
assignmentOperators.push_back(&AS_MOD_ASSIGN);
assignmentOperators.push_back(&AS_XOR_ASSIGN);
assignmentOperators.push_back(&AS_OR_ASSIGN);
assignmentOperators.push_back(&AS_AND_ASSIGN);
assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
assignmentOperators.push_back(&AS_ASSIGN);
}
/**
* initialize the ASFormatter.
*
* init() should be called every time a ASFormatter object is to start
* formatting a NEW source file.
* init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
* that will be used to iterate through the source code. This object will be
* deleted during the ASFormatter's destruction, and thus should not be
* deleted elsewhere.
*
* @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
*/
void ASFormatter::init(ASSourceIterator *si)
{
ASBeautifier::init(si);
sourceIterator = si;
INIT_CONTAINER( preBracketHeaderStack, new vector<const string*> );
INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
bracketTypeStack->push_back(DEFINITION_TYPE);
INIT_CONTAINER( parenStack, new vector<int> );
parenStack->push_back(0);
currentHeader = NULL;
currentLine = string("");
formattedLine = "";
currentChar = ' ';
previousCommandChar = ' ';
previousNonWSChar = ' ';
quoteChar = '"';
charNum = 0;
previousOperator = NULL;
isVirgin = true;
isInLineComment = false;
isInComment = false;
isInPreprocessor = false;
doesLineStartComment = false;
isInQuote = false;
isSpecialChar = false;
isNonParenHeader = true;
foundPreDefinitionHeader = false;
foundPreCommandHeader = false;
foundQuestionMark = false;
isInLineBreak = false;
endOfCodeReached = false;
isLineReady = false;
isPreviousBracketBlockRelated = true;
isInPotentialCalculation = false;
//foundOneLineBlock = false;
shouldReparseCurrentChar = false;
passedSemicolon = false;
passedColon = false;
isInTemplate = false;
shouldBreakLineAfterComments = false;
isImmediatelyPostComment = false;
isImmediatelyPostLineComment = false;
isImmediatelyPostEmptyBlock = false;
isPrependPostBlockEmptyLineRequested = false;
isAppendPostBlockEmptyLineRequested = false;
prependEmptyLine = false;
foundClosingHeader = false;
previousReadyFormattedLineLength = 0;
isImmediatelyPostHeader = false;
isInHeader = false;
}
/**
* get the next formatted line.
*
* @return formatted line.
*/
string ASFormatter::nextLine()
{
const string *newHeader;
bool isCharImmediatelyPostComment = false;
bool isPreviousCharPostComment = false;
bool isCharImmediatelyPostLineComment = false;
bool isInVirginLine = isVirgin;
bool isCharImmediatelyPostOpenBlock = false;
bool isCharImmediatelyPostCloseBlock = false;
bool isCharImmediatelyPostTemplate = false;
bool isCharImmediatelyPostHeader = false;
if (!isFormattingEnabled())
return ASBeautifier::nextLine();
while (!isLineReady)
{
if (shouldReparseCurrentChar)
shouldReparseCurrentChar = false;
else if (!getNextChar())
{
breakLine();
return beautify(readyFormattedLine);
}
else // stuff to do when reading a new character...
{
// make sure that a virgin '{' at the begining ofthe file will be treated as a block...
if (isInVirginLine && currentChar == '{')
previousCommandChar = '{';
isPreviousCharPostComment = isCharImmediatelyPostComment;
isCharImmediatelyPostComment = false;
isCharImmediatelyPostTemplate = false;
isCharImmediatelyPostHeader = false;
}
if (isInLineComment)
{
appendCurrentChar();
// explicitely break a line when a line comment's end is found.
if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length())
{
isInLineBreak = true;
isInLineComment = false;
isImmediatelyPostLineComment = true;
currentChar = 0; //make sure it is a neutral char.
}
continue;
}
else if (isInComment)
{
if (isSequenceReached(AS_CLOSE_COMMENT))
{
isInComment = false;
isImmediatelyPostComment = true;
appendSequence(AS_CLOSE_COMMENT);
goForward(1);
}
else
appendCurrentChar();
continue;
}
// not in line comment or comment
else if (isInQuote)
{
if (isSpecialChar)
{
isSpecialChar = false;
appendCurrentChar();
}
else if (currentChar == '\\')
{
isSpecialChar = true;
appendCurrentChar();
}
else if (quoteChar == currentChar)
{
isInQuote = false;
appendCurrentChar();
}
else
{
appendCurrentChar();
}
continue;
}
// handle white space - needed to simplify the rest.
if (isWhiteSpace(currentChar) || isInPreprocessor)
{
////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar()))
appendCurrentChar();
continue;
}
/* not in MIDDLE of quote or comment or white-space of any type ... */
if (isSequenceReached(AS_OPEN_LINE_COMMENT))
{
isInLineComment = true;
if (shouldPadOperators)
appendSpacePad();
appendSequence(AS_OPEN_LINE_COMMENT);
goForward(1);
continue;
}
else if (isSequenceReached(AS_OPEN_COMMENT))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -