📄 asbeautifier.cpp
字号:
labelIndent = state;}/** * set the state of the preprocessor indentation option. * If true, multiline #define statements will be indented. * * @param state state of option. */void ASBeautifier::setPreprocessorIndent(bool state){ preprocessorIndent = state;}/** * set the state of the empty line fill option. * If true, empty lines will be filled with the whitespace. * of their previous lines. * If false, these lines will remain empty. * * @param state state of option. */void ASBeautifier::setEmptyLineFill(bool state){ emptyLineFill = state;}/** * get the number of spaces per indent * * @return value of indentLength option.*/int ASBeautifier::getIndentLength(void){ return indentLength;}/** * get the char used for indentation, space or tab * * @return the char used for indentation. */string ASBeautifier::getIndentString(void){ return indentString;}/** * get the state of the case indentation option. If true, lines of 'case' * statements will be indented one additional indent. * * @return state of caseIndent option. */bool ASBeautifier::getCaseIndent(void){ return caseIndent;}/** * get C style identifier. * If true, a C source is being indented. * * @return state of isCStyle option. */bool ASBeautifier::getCStyle(void){ return isCStyle;}/** * get Java style identifier. * If true, a Java source is being indented. * * @return state of isJavaStyle option. */bool ASBeautifier::getJavaStyle(void){ return isJavaStyle;}/** * get C# style identifier. * If true, a C# source is being indented. * * @return state of isSharpStyle option. */bool ASBeautifier::getSharpStyle(void){ return isSharpStyle;}/** * get the state of the empty line fill option. * If true, empty lines will be filled with the whitespace. * of their previous lines. * If false, these lines will remain empty. * * @return state of emptyLineFill option. */bool ASBeautifier::getEmptyLineFill(void){ return emptyLineFill;}/** * check if there are any indented lines ready to be read by nextLine() * * @return are there any indented lines ready? */bool ASBeautifier::hasMoreLines() const{ return sourceIterator->hasMoreLines();}/** * get the next indented line. * * @return indented line. */string ASBeautifier::nextLine(){ return beautify(sourceIterator->nextLine());}/** * beautify a line of source code. * every line of source code in a source code file should be sent * one after the other to the beautify method. * * @return the indented line. * @param originalLine the original unindented line. */string ASBeautifier::beautify(const string &originalLine){ string line; bool isInLineComment = false; bool lineStartsInComment = false; bool isInClass = false; bool isInSwitch = false; bool isImmediatelyAfterConst = false; bool isSpecialChar = false; bool haveCaseIndent = false; bool closingBracketReached = false; bool shouldIndentBrackettedLine = true; bool previousLineProbation = (probationHeader != NULL); bool isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar; char ch = ' '; char prevCh; char tempCh; int tabCount = 0; int spaceTabCount = 0; int lineOpeningBlocksNum = 0; int lineClosingBlocksNum = 0; int i; string outBuffer; // the newly idented line is bufferd here const string *lastLineHeader = NULL; size_t headerStackSize = headerStack->size(); currentHeader = NULL; lineStartsInComment = isInComment; blockCommentNoBeautify = blockCommentNoIndent; previousLineProbationTab = false; haveLineContinuationChar = false; // handle and remove white spaces around the line: // If not in comment, first find out size of white space before line, // so that possible comments starting in the line continue in // relation to the preliminary white-space. if (isInQuoteContinuation) { // trim a single space added by ASFormatter, otherwise leave it alone if (!(originalLine.length() == 1 && originalLine[0] == ' ')) line = originalLine; } else if (!isInComment) { int strlen = originalLine.length(); leadingWhiteSpaces = 0; for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++) { if (originalLine[j] == '\t') leadingWhiteSpaces += indentLength; else leadingWhiteSpaces++; } line = trim(originalLine); } else { // convert leading tabs to spaces string spaceTabs(indentLength, ' '); string newLine = originalLine; int strlen = newLine.length(); for (int j=0; j < leadingWhiteSpaces && j < strlen; j++) { if (newLine[j] == '\t') { newLine.replace(j, 1, spaceTabs); strlen = newLine.length(); } } // trim the comment leaving the new leading whitespace int trimSize = 0; strlen = newLine.length(); while (trimSize < strlen && trimSize < leadingWhiteSpaces && isWhiteSpace(newLine[trimSize])) trimSize++; while (trimSize < strlen && isWhiteSpace(newLine[strlen-1])) strlen--; line = newLine.substr(trimSize, strlen); int spacesToDelete; size_t trimEnd = line.find_last_not_of(" \t"); if (trimEnd == string::npos) spacesToDelete = line.length(); else spacesToDelete = line.length() - 1 - trimEnd; if (spacesToDelete > 0) line.erase(trimEnd + 1, spacesToDelete); } if (line.length() == 0) { if (backslashEndsPrevLine) // must continue to clear variables line = ' '; else if (emptyLineFill && !isInQuoteContinuation && headerStackSize > 0) return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount); else return line; } // handle preprocessor commands if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine)) { if (line[0] == '#') { string preproc = trim(string(line.c_str() + 1)); // When finding a multi-lined #define statement, the original beautifier // 1. sets its isInDefineDefinition flag // 2. clones a new beautifier that will be used for the actual indentation // of the #define. This clone is put into the activeBeautifierStack in order // to be called for the actual indentation. // The original beautifier will have isInDefineDefinition = true, isInDefine = false // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 && line[line.length() - 1] == '\\') { if (!isInDefineDefinition) { ASBeautifier *defineBeautifier; // this is the original beautifier isInDefineDefinition = true; // push a new beautifier into the active stack // this beautifier will be used for the indentation of this define defineBeautifier = new ASBeautifier(*this); activeBeautifierStack->push_back(defineBeautifier); } else { // the is the cloned beautifier that is in charge of indenting the #define. isInDefine = true; } } else if (preproc.compare(0, 2, "if") == 0) { // push a new beautifier into the stack waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size()); activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size()); waitingBeautifierStack->push_back(new ASBeautifier(*this)); } else if (preproc.compare(0, 4/*2*/, "else") == 0) { if (waitingBeautifierStack && !waitingBeautifierStack->empty()) { // MOVE current waiting beautifier to active stack. activeBeautifierStack->push_back(waitingBeautifierStack->back()); waitingBeautifierStack->pop_back(); } } else if (preproc.compare(0, 4, "elif") == 0) { if (waitingBeautifierStack && !waitingBeautifierStack->empty()) { // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. activeBeautifierStack->push_back(new ASBeautifier(*(waitingBeautifierStack->back()))); } } else if (preproc.compare(0, 5, "endif") == 0) { int stackLength; ASBeautifier *beautifier; if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->empty()) { stackLength = waitingBeautifierStackLengthStack->back(); waitingBeautifierStackLengthStack->pop_back(); while ((int) waitingBeautifierStack->size() > stackLength) { beautifier = waitingBeautifierStack->back(); waitingBeautifierStack->pop_back(); delete beautifier; } } if (!activeBeautifierStackLengthStack->empty()) { stackLength = activeBeautifierStackLengthStack->back(); activeBeautifierStackLengthStack->pop_back(); while ((int) activeBeautifierStack->size() > stackLength) { beautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); delete beautifier; } } } } // check if the last char is a backslash if (line.length() > 0) backslashEndsPrevLine = (line[line.length() - 1] == '\\'); else backslashEndsPrevLine = false; // check if this line ends a multi-line #define // if so, use the #define's cloned beautifier for the line's indentation // and then remove it from the active beautifier stack and delete it. if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) { string beautifiedLine; ASBeautifier *defineBeautifier; isInDefineDefinition = false; defineBeautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); beautifiedLine = defineBeautifier->beautify(line); delete defineBeautifier; return beautifiedLine; } // unless this is a multi-line #define, return this precompiler line as is. if (!isInDefine && !isInDefineDefinition) return originalLine; } // if there exists any worker beautifier in the activeBeautifierStack, // then use it instead of me to indent the current line. // variables set by ASFormatter must be updated. if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty()) { activeBeautifierStack->back()->inLineNumber = inLineNumber; activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify; activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray; // must return originalLine not the trimmed line return activeBeautifierStack->back()->beautify(originalLine); } // calculate preliminary indentation based on data from past lines if (!inStatementIndentStack->empty()) spaceTabCount = inStatementIndentStack->back(); for (i = 0; i < (int) headerStackSize; i++) { isInClass = false; if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET && (*headerStack)[i] == &AS_OPEN_BRACKET))) ++tabCount; if (!isJavaStyle && !namespaceIndent && i >= 1 && (*headerStack)[i-1] == &AS_NAMESPACE && (*headerStack)[i] == &AS_OPEN_BRACKET) --tabCount; if (isCStyle && i >= 1 && (*headerStack)[i-1] == &AS_CLASS && (*headerStack)[i] == &AS_OPEN_BRACKET) { if (classIndent) ++tabCount; isInClass = true; } // is the switchIndent option is on, indent switch statements an additional indent. else if (switchIndent && i > 1 && (*headerStack)[i-1] == &AS_SWITCH && (*headerStack)[i] == &AS_OPEN_BRACKET ) { ++tabCount; isInSwitch = true; } } if (!lineStartsInComment && isCStyle && isInClass && classIndent && headerStackSize >= 2 && (*headerStack)[headerStackSize-2] == &AS_CLASS && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; else if (!lineStartsInComment && isInSwitch && switchIndent && headerStackSize >= 2 && (*headerStack)[headerStackSize-2] == &AS_SWITCH && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; if (isInClassHeader) { isInClassHeaderTab = true; tabCount += 2; } if (isInConditional) { --tabCount; } // parse characters in the current line. for (i = 0; i < (int) line.length(); i++) { outBuffer.append(1, line[i]); // check for utf-8 characters // isalnum() will display an assert message in debug if not bypassed here if ((unsigned) line[i] > 255) continue; tempCh = line[i]; prevCh = ch; ch = tempCh; if (isWhiteSpace(ch)) continue; // handle special characters (i.e. backslash+character such as \n, \t, ...) if (isInQuote && !isInVerbatimQuote) { if (isSpecialChar) { isSpecialChar = false; continue; } if (line.compare(i, 2, "\\\\") == 0) { outBuffer.append(1, '\\'); i++; continue; } if (ch == '\\') { if (peekNextChar(line, i) == ' ') // is this '\' at end of line haveLineContinuationChar = true; else isSpecialChar = true; continue; } } else if (isInDefine && ch == '\\') continue; // handle quotes (such as 'x' and "Hello Dolly") if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\'')) { if (!isInQuote) { quoteChar = ch; isInQuote = true; if (isSharpStyle && prevCh == '@') isInVerbatimQuote = true; } else if (isInVerbatimQuote && ch == '"') { if (peekNextChar(line, i) == '"') // check consecutive quotes { outBuffer.append(1, '"'); i++; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -