📄 asformatter.cpp
字号:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ASFormatter.cpp * * This file is a part of "Artistic Style" - an indentation and * reformatting tool for C, C++, C# and Java source files. * http://astyle.sourceforge.net * * The "Artistic Style" project, including all files needed to * compile it, is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */#include "astyle.h"#include <algorithm>#include <fstream>#include <iostream>// can trace only if NDEBUG is not defined#ifndef NDEBUG// #define TRACEunpad// #define TRACEcomment// #define TRACEheader// #define TRACEbracket// #define TRACEarray#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \|| defined(TRACEbracket) || defined(TRACEarray)ofstream *traceOutF;#define TRACEF#endif#endif#ifdef TRACEunpad#define TRunpad(a,b,c) if(b > 0 || c > 0) *traceOutF << traceLineNumber << " " << b << a << c << endl#else#define TRunpad(a,b,c) ((void)0)#endif#ifdef TRACEcomment#define TRcomment(a) *traceOutF << traceLineNumber << " " << a << endl#else#define TRcomment(a) ((void)0)#endif#ifdef TRACEheader#define TRxtra(a) *traceOutF << traceLineNumber << " " << a << endl#else#define TRxtra(a) ((void)0)#endif#ifdef TRACEbracket#define TRbracket(a) *traceOutF << traceLineNumber << " " << a << endl#else#define TRbracket(a) ((void)0)#endif#ifdef TRACEarray#define TRarray(a) *traceOutF << traceLineNumber << " " << a << endl#else#define TRarray(a) ((void)0)#endif#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))using namespace std;namespace astyle{vector<const string*> ASFormatter::headers;vector<const string*> ASFormatter::nonParenHeaders;vector<const string*> ASFormatter::preDefinitionHeaders;vector<const string*> ASFormatter::preCommandHeaders;vector<const string*> ASFormatter::operators;vector<const string*> ASFormatter::assignmentOperators;vector<const string*> ASFormatter::castOperators;/** * Constructor of ASFormatter */ASFormatter::ASFormatter(){ preBracketHeaderStack = NULL; bracketTypeStack = NULL; parenStack = NULL; lineCommentNoIndent = false; sourceIterator = NULL; bracketFormatMode = NONE_MODE; shouldPadOperators = false; shouldPadParensOutside = false; shouldPadParensInside = false; shouldUnPadParens = false; shouldBreakOneLineBlocks = true; shouldBreakOneLineStatements = true; shouldConvertTabs = false; shouldBreakBlocks = false; shouldBreakClosingHeaderBlocks = false; shouldBreakClosingHeaderBrackets = false; shouldBreakElseIfs = false;#ifdef TRACEF // create a trace text file string traceFileName = "tracef.txt"; char* env = getenv("HOME"); if (env != NULL) traceFileName = string(env) + string("/tracef.txt"); else { env = getenv("USERPROFILE"); if (env != NULL) traceFileName = string(env) + string("\\My Documents\\tracef.txt"); else { cout << "\nCould not open tracef.txt\n" << endl; exit(1); } } traceOutF = new ofstream(traceFileName.c_str());#endif}/** * Destructor of ASFormatter */ASFormatter::~ASFormatter(){ DELETE_CONTAINER(preBracketHeaderStack);#ifdef TRACEF delete traceOutF;#endif}/** * initialization of static data of ASFormatter. */void ASFormatter::staticInit(){ static int formatterFileType = 9; // initialized with an invalid type if (fileType == formatterFileType) // don't build unless necessary return; formatterFileType = fileType; headers.clear(); nonParenHeaders.clear(); assignmentOperators.clear(); operators.clear(); preDefinitionHeaders.clear(); preCommandHeaders.clear(); castOperators.clear(); ASResource::buildHeaders(headers, fileType); ASResource::buildNonParenHeaders(nonParenHeaders, fileType); ASResource::buildAssignmentOperators(assignmentOperators); ASResource::buildOperators(operators); ASResource::buildPreDefinitionHeaders(preDefinitionHeaders); ASResource::buildPreCommandHeaders(preCommandHeaders); ASResource::buildCastOperators(castOperators);}/** * 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){ staticInit(); ASBeautifier::init(si); ASEnhancer::init(getIndentLength(), getIndentString(), getCStyle(), getJavaStyle(), getSharpStyle(), getCaseIndent(), getEmptyLineFill()); sourceIterator = si; INIT_CONTAINER(preBracketHeaderStack, new vector<const string*>); INIT_CONTAINER(bracketTypeStack, new vector<BracketType>); bracketTypeStack->push_back(NULL_TYPE); INIT_CONTAINER(parenStack, new vector<int>); parenStack->push_back(0); // parenStack must contain this default entry currentHeader = NULL; currentLine = string(""); readyFormattedLine = string(""); formattedLine = ""; currentChar = ' '; previousChar = ' '; previousCommandChar = ' '; previousNonWSChar = ' '; quoteChar = '"'; charNum = 0; spacePadNum = 0; previousReadyFormattedLineLength = string::npos; templateDepth = 0; traceLineNumber = 0; previousBracketType = NULL_TYPE; previousOperator = NULL; isVirgin = true; isInLineComment = false; isInComment = false; isInPreprocessor = false; doesLineStartComment = false; isInQuote = false; isInVerbatimQuote = false; haveLineContinuationChar = false; isInQuoteContinuation = false; isSpecialChar = false; isNonParenHeader = true; foundNamespaceHeader = false; foundClassHeader = false; foundPreDefinitionHeader = false; foundPreCommandHeader = false; foundCastOperator = false; foundQuestionMark = false; isInLineBreak = false; endOfCodeReached = false; isLineReady = false; isPreviousBracketBlockRelated = true; isInPotentialCalculation = false; shouldReparseCurrentChar = false; passedSemicolon = false; passedColon = false; isInTemplate = false; isInBlParen = false;// shouldBreakLineAfterComments = false; isImmediatelyPostComment = false; isImmediatelyPostLineComment = false; isImmediatelyPostEmptyBlock = false; isImmediatelyPostPreprocessor = false; isPrependPostBlockEmptyLineRequested = false; isAppendPostBlockEmptyLineRequested = false; prependEmptyLine = false; appendOpeningBracket = false; foundClosingHeader = false; previousReadyFormattedLineLength = 0; isImmediatelyPostHeader = false; isInHeader = false; isInCase = false;#ifdef TRACEF // traceFileName will be empty if ASTYLE_LIB is defined if (traceFileName.empty()) *traceOutF << "new file" << endl; else *traceOutF << traceFileName << endl;#endif}/** * get the next formatted line. * * @return formatted line. */string ASFormatter::nextLine(){ // these are reset with each new line const string *newHeader; bool isInVirginLine = isVirgin; isCharImmediatelyPostComment = false; isPreviousCharPostComment = false; isCharImmediatelyPostLineComment = false; isCharImmediatelyPostOpenBlock = false; isCharImmediatelyPostCloseBlock = false; isCharImmediatelyPostTemplate = false; traceLineNumber++; 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 == '{' && lineBeginsWith('{')) previousCommandChar = '{'; isPreviousCharPostComment = isCharImmediatelyPostComment; isCharImmediatelyPostComment = false; isCharImmediatelyPostTemplate = false; }// if (inLineNumber >= 1159)// int x = 1; if (isInLineComment) { appendCurrentChar(); // explicitely break a line when a line comment's end is found. if (charNum + 1 == (int) currentLine.length()) { isInLineBreak = true; isInLineComment = false; isImmediatelyPostLineComment = true; currentChar = 0; //make sure it is a neutral char. } continue; } else if (isInComment) { if (isSequenceReached("*/")) { 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; } else if (currentChar == '\\' && !isInVerbatimQuote) { if (peekNextChar() == ' ') // is this '\' at end of line haveLineContinuationChar = true; else isSpecialChar = true; } else if (isInVerbatimQuote && currentChar == '"' ) { if (peekNextChar() == '"') // check consecutive quotes { appendSequence("\"\""); goForward(1); continue; } else { isInQuote = false; isInVerbatimQuote = false; } } else if (quoteChar == currentChar) { isInQuote = false; } appendCurrentChar(); continue; } if (isSequenceReached("//")) { if (currentLine[charNum+2] == '\xf2') // check for windows line marker isAppendPostBlockEmptyLineRequested = false; isInLineComment = true; // do not indent if in column 1 or 2 if (lineCommentNoIndent == false) { if (charNum == 0) lineCommentNoIndent = true; else if (charNum == 1 && currentLine[0] == ' ') lineCommentNoIndent = true; } // move comment if spaces were added or deleted if (lineCommentNoIndent == false && spacePadNum != 0) adjustComments(); formattedLineCommentNum = formattedLine.length(); appendSequence(AS_OPEN_LINE_COMMENT); goForward(1); // explicitely break a line when a line comment's end is found. if (charNum + 1 == (int) currentLine.length()) { isInLineBreak = true; isInLineComment = false; isImmediatelyPostLineComment = true; currentChar = 0; //make sure it is a neutral char. } continue; } else if (isSequenceReached("/*")) { isInComment = true; if (spacePadNum != 0) adjustComments(); formattedLineCommentNum = formattedLine.length(); appendSequence(AS_OPEN_COMMENT); goForward(1); continue; } else if (currentChar == '"' || currentChar == '\'') { isInQuote = true; if (isSharpStyle && previousChar == '@') isInVerbatimQuote = true; quoteChar = currentChar; appendCurrentChar(); continue; } // handle white space - needed to simplify the rest. if (isWhiteSpace(currentChar) || isInPreprocessor) { appendCurrentChar(); continue; } /* not in MIDDLE of quote or comment or white-space of any type ... */ // need to reset 'previous' chars if appending a bracket if (appendOpeningBracket) previousCommandChar = previousNonWSChar = previousChar = '{'; // check if in preprocessor // ** isInPreprocessor will be automatically reset at the begining // of a new line in getnextChar() if (isCStyle && currentChar == '#') { isInPreprocessor = true; appendCurrentChar(); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -